@oslokommune/punkt-elements 16.24.1 → 16.25.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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,23 @@ og skriver commits ca etter [Conventional Commits](https://conventionalcommits.o
5
5
 
6
6
  ---
7
7
 
8
+ ## [16.25.0](https://github.com/oslokommune/punkt/compare/16.24.1...16.25.0) (2026-06-12)
9
+
10
+ ### ⚠ BREAKING CHANGES
11
+ Ingen
12
+
13
+ ### Features
14
+ Ingen
15
+
16
+ ### Bug Fixes
17
+ Ingen
18
+
19
+ ### Chores
20
+ Ingen
21
+
22
+ ---
23
+
24
+
8
25
  ## [16.24.1](https://github.com/oslokommune/punkt/compare/16.24.0...16.24.1) (2026-05-29)
9
26
 
10
27
  ### ⚠ BREAKING CHANGES
@@ -54,6 +54,7 @@ export declare class PktHeaderService extends PktElementWithSlot<IPktHeader> imp
54
54
  private setupScrollListener;
55
55
  private handleScroll;
56
56
  private handleClickOutside;
57
+ private handleSlotContentClick;
57
58
  private handleFocusOut;
58
59
  private handleEscapeKey;
59
60
  private restoreFocus;
@@ -6,7 +6,7 @@ import { t as u } from "./if-defined-VShASPdu.js";
6
6
  import "./button-CR-KWhTT.js";
7
7
  import { n as d, t as f } from "./ref-BgoHEsEt.js";
8
8
  import { t as p } from "./booleanish-BmcOU-43.js";
9
- import "./link-ClUNY__5.js";
9
+ import "./link-DauiNRMq.js";
10
10
  import "./textinput-CZrBM-Fj.js";
11
11
  //#region ../../shared-types/header.ts
12
12
  var m = (e) => typeof e.target == "string" ? {
@@ -189,6 +189,10 @@ var v = "https://punkt-cdn.oslo.kommune.no/latest/logos/", y = class extends l {
189
189
  }, this.handleClickOutside = (e) => {
190
190
  let t = e.target;
191
191
  this.user && this.openMenu === "user" && !t.closest(".pkt-header-service__user-container") && (this.openMenu = "none"), this.openMenu === "slot" && !t.closest(".pkt-header-service__slot-container") && (this.openMenu = "none"), this.openMenu === "search" && !t.closest(".pkt-header-service__search-container") && !t.closest(".pkt-header-service__search-input") && (this.openMenu = "none");
192
+ }, this.handleSlotContentClick = (e) => {
193
+ if (!this.isTablet || this.openMenu !== "slot") return;
194
+ let t = e.target.closest("a[href], button, [role=\"link\"], [role=\"button\"], [role=\"menuitem\"], [role=\"menuitemradio\"], [role=\"menuitemcheckbox\"]");
195
+ !t || !this.slotContentRef.value?.contains(t) || t.closest("[data-pkt-header-keep-open]") || t.disabled || t.getAttribute("aria-disabled") === "true" || (this.openMenu = "none");
192
196
  }, this.handleFocusOut = (e, t) => {
193
197
  let n = e.relatedTarget, r;
194
198
  switch (t) {
@@ -369,7 +373,11 @@ var v = "https://punkt-cdn.oslo.kommune.no/latest/logos/", y = class extends l {
369
373
  </button>
370
374
  </span>
371
375
  ` : i`
372
- <span class="pkt-header-service__service-name" translate="no" @click=${this.handleServiceClick}>
376
+ <span
377
+ class="pkt-header-service__service-name"
378
+ translate="no"
379
+ @click=${this.handleServiceClick}
380
+ >
373
381
  <span class="pkt-header-service__service-link">${this.serviceName}</span>
374
382
  </span>
375
383
  ` : t;
@@ -409,6 +417,7 @@ var v = "https://punkt-cdn.oslo.kommune.no/latest/logos/", y = class extends l {
409
417
  id="mobile-slot-menu"
410
418
  role=${this.isTablet ? "menu" : t}
411
419
  aria-label=${this.isTablet ? "Meny" : t}
420
+ @click=${this.handleSlotContentClick}
412
421
  ${d(this.slotContentRef)}
413
422
  >
414
423
  ${c(this)}
@@ -1,4 +1,4 @@
1
- const e=require(`./element-CXAtr6Gu.cjs`),t=require(`./class-map-B8Ja0q7n.cjs`),n=require(`./element-with-slot-Cmxb9h4H.cjs`);require(`./icon-Dw6I0HDV.cjs`);const r=require(`./if-defined-LTjAScFG.cjs`);require(`./button-Dwv11n6R.cjs`);const i=require(`./ref-CBdWMlde.cjs`),a=require(`./booleanish-jJLlnr6-.cjs`);require(`./link-B5ur0Rym.cjs`),require(`./textinput-C_6kvf87.cjs`);var o=e=>typeof e.target==`string`?{title:e.title,iconName:e.iconName,href:e.target}:{title:e.title,iconName:e.iconName,onClick:e.target},s=e=>o(e),c=e=>{if(!e)return;let t=typeof e==`string`?new Date(e):e;if(!isNaN(t.getTime()))return t.toLocaleDateString(`nb-NO`,{day:`numeric`,month:`long`,year:`numeric`,hour:`2-digit`,minute:`2-digit`})},l=class extends e.t{constructor(...e){super(...e),this.canChangeRepresentation=!1,this.logoutOnClick=!1}handleChangeRepresentation(){this.dispatchEvent(new CustomEvent(`change-representation`,{bubbles:!0,composed:!0}))}handleLogout(){this.dispatchEvent(new CustomEvent(`log-out`,{bubbles:!0,composed:!0}))}handleMenuItemClick(e){`onClick`in e&&typeof e.onClick==`function`&&e.onClick()}renderLinkOrButton(n,r){let i=`href`in n,a=t.t({"pkt-user-menu__link":!0,"pkt-link-button":!i,"pkt-link":!i,"pkt-link--icon-left":!i,[r||``]:!!r});return i?e.p`
1
+ const e=require(`./element-CXAtr6Gu.cjs`),t=require(`./class-map-B8Ja0q7n.cjs`),n=require(`./element-with-slot-Cmxb9h4H.cjs`);require(`./icon-Dw6I0HDV.cjs`);const r=require(`./if-defined-LTjAScFG.cjs`);require(`./button-Dwv11n6R.cjs`);const i=require(`./ref-CBdWMlde.cjs`),a=require(`./booleanish-jJLlnr6-.cjs`);require(`./link-EZ0-lS3W.cjs`),require(`./textinput-C_6kvf87.cjs`);var o=e=>typeof e.target==`string`?{title:e.title,iconName:e.iconName,href:e.target}:{title:e.title,iconName:e.iconName,onClick:e.target},s=e=>o(e),c=e=>{if(!e)return;let t=typeof e==`string`?new Date(e):e;if(!isNaN(t.getTime()))return t.toLocaleDateString(`nb-NO`,{day:`numeric`,month:`long`,year:`numeric`,hour:`2-digit`,minute:`2-digit`})},l=class extends e.t{constructor(...e){super(...e),this.canChangeRepresentation=!1,this.logoutOnClick=!1}handleChangeRepresentation(){this.dispatchEvent(new CustomEvent(`change-representation`,{bubbles:!0,composed:!0}))}handleLogout(){this.dispatchEvent(new CustomEvent(`log-out`,{bubbles:!0,composed:!0}))}handleMenuItemClick(e){`onClick`in e&&typeof e.onClick==`function`&&e.onClick()}renderLinkOrButton(n,r){let i=`href`in n,a=t.t({"pkt-user-menu__link":!0,"pkt-link-button":!i,"pkt-link":!i,"pkt-link--icon-left":!i,[r||``]:!!r});return i?e.p`
2
2
  <pkt-link
3
3
  icon-name=${n.iconName||e.d}
4
4
  href=${n.href}
@@ -80,7 +80,7 @@ const e=require(`./element-CXAtr6Gu.cjs`),t=require(`./class-map-B8Ja0q7n.cjs`),
80
80
  `:e.d}
81
81
  </ul>
82
82
  </nav>
83
- `}};e.n([e.o({type:Object})],l.prototype,`user`,void 0),e.n([e.o({type:String,attribute:`formatted-last-logged-in`})],l.prototype,`formattedLastLoggedIn`,void 0),e.n([e.o({type:Object})],l.prototype,`representing`,void 0),e.n([e.o({type:Array,attribute:`user-menu`})],l.prototype,`userMenu`,void 0),e.n([e.o({type:Boolean,attribute:`can-change-representation`,converter:a.t})],l.prototype,`canChangeRepresentation`,void 0),e.n([e.o({type:Boolean,attribute:`logout-on-click`,converter:a.t})],l.prototype,`logoutOnClick`,void 0);try{e.s(`pkt-header-user-menu`)(l)}catch{console.warn(`Forsøker å definere <pkt-header-user-menu>, men den er allerede definert`)}var u=`https://punkt-cdn.oslo.kommune.no/latest/logos/`,d=class extends n.t{constructor(...e){super(...e),this.searchPlaceholder=`Søk`,this.searchValue=``,this.mobileBreakpoint=768,this.tabletBreakpoint=1280,this.openedMenu=`none`,this.logOutButtonPlacement=`none`,this.position=`fixed`,this.scrollBehavior=`hide`,this.slotMenuVariant=`icon-only`,this.slotMenuText=`Meny`,this.hideLogo=!1,this.compact=!1,this.showSearch=!1,this.canChangeRepresentation=!1,this.hasLogOut=!1,this.isMobile=!1,this.isTablet=!1,this.openMenu=`none`,this.isHidden=!1,this.componentWidth=typeof window<`u`?window.innerWidth:0,this.alignSlotRight=!1,this.alignSearchRight=!1,this.headerRef=i.t(),this.userContainerRef=i.t(),this.slotContainerRef=i.t(),this.searchContainerRef=i.t(),this.slotContentRef=i.t(),this.searchMenuRef=i.t(),this.lastScrollPosition=0,this.savedScrollY=0,this.lastFocusedElement=null,this.shouldRestoreFocus=!1,this.handleScroll=()=>{if(!this.shouldHideOnScroll)return;let e=window.pageYOffset||document.documentElement.scrollTop;e<0||Math.abs(e-this.lastScrollPosition)<60||(this.isHidden=e>this.lastScrollPosition,this.lastScrollPosition=e)},this.handleClickOutside=e=>{let t=e.target;this.user&&this.openMenu===`user`&&!t.closest(`.pkt-header-service__user-container`)&&(this.openMenu=`none`),this.openMenu===`slot`&&!t.closest(`.pkt-header-service__slot-container`)&&(this.openMenu=`none`),this.openMenu===`search`&&!t.closest(`.pkt-header-service__search-container`)&&!t.closest(`.pkt-header-service__search-input`)&&(this.openMenu=`none`)},this.handleFocusOut=(e,t)=>{let n=e.relatedTarget,r;switch(t){case`user`:r=this.userContainerRef;break;case`slot`:r=this.slotContainerRef;break;case`search`:r=this.searchContainerRef;break;default:return}let i=r.value;i&&(!n||!i.contains(n))&&(this.openMenu=`none`)},this.handleEscapeKey=e=>{e.key===`Escape`&&this.openMenu!==`none`&&(e.preventDefault(),this.shouldRestoreFocus=!0,this.openMenu=`none`)}}connectedCallback(){super.connectedCallback(),this.setupScrollListener()}disconnectedCallback(){super.disconnectedCallback(),this.resizeObserver?.disconnect(),window.removeEventListener(`scroll`,this.handleScroll),this.unlockScroll()}firstUpdated(){this.setupResizeObserver()}updated(e){if(super.updated(e),e.has(`openedMenu`)&&this.openedMenu!==this.openMenu&&(this.openMenu=this.openedMenu),(e.has(`mobileBreakpoint`)||e.has(`tabletBreakpoint`))&&(this.updateIsMobile(),this.updateIsTablet()),e.has(`openMenu`)){let t=e.get(`openMenu`);this.openMenu!==`none`&&(t===`none`||t===void 0)?(document.addEventListener(`mousedown`,this.handleClickOutside),document.addEventListener(`keydown`,this.handleEscapeKey),(this.openMenu===`slot`||this.openMenu===`search`)&&requestAnimationFrame(()=>{this.checkDropdownAlignment(this.openMenu)})):this.openMenu===`none`&&t!==`none`&&(document.removeEventListener(`mousedown`,this.handleClickOutside),document.removeEventListener(`keydown`,this.handleEscapeKey),this.restoreFocus())}(e.has(`openMenu`)||e.has(`isMobile`))&&this.updateScrollLock()}setupResizeObserver(){let e=this.headerRef.value;e&&(this.componentWidth=e.offsetWidth,this.updateIsMobile(),this.updateIsTablet(),this.resizeObserver=new ResizeObserver(e=>{for(let t of e)t.borderBoxSize&&t.borderBoxSize.length>0?this.componentWidth=t.borderBoxSize[0].inlineSize:this.componentWidth=t.contentRect.width,this.updateIsMobile(),this.updateIsTablet()}),this.resizeObserver.observe(e))}updateIsMobile(){this.isMobile=this.componentWidth<this.mobileBreakpoint}updateIsTablet(){this.isTablet=this.componentWidth<this.tabletBreakpoint}updateScrollLock(){this.position===`fixed`&&this.isMobile&&this.openMenu!==`none`?this.lockScroll():this.unlockScroll()}lockScroll(){let e=document.body,t=document.documentElement;this.savedScrollY=window.scrollY||window.pageYOffset;let n=window.innerWidth-t.clientWidth;n>0&&(e.style.paddingRight=`${n}px`),e.style.position=`fixed`,e.style.top=`-${this.savedScrollY}px`,e.style.left=`0`,e.style.right=`0`,e.style.width=`100%`,e.style.overflow=`hidden`,t.classList.add(`is-scroll-locked`)}unlockScroll(){let e=document.body,t=document.documentElement;t.classList.contains(`is-scroll-locked`)&&(e.style.removeProperty(`position`),e.style.removeProperty(`top`),e.style.removeProperty(`left`),e.style.removeProperty(`right`),e.style.removeProperty(`width`),e.style.removeProperty(`overflow`),e.style.removeProperty(`padding-right`),t.classList.remove(`is-scroll-locked`),window.scrollTo({top:this.savedScrollY}))}setupScrollListener(){window.addEventListener(`scroll`,this.handleScroll)}restoreFocus(){this.shouldRestoreFocus&&this.lastFocusedElement&&document.contains(this.lastFocusedElement)&&this.lastFocusedElement.focus(),this.lastFocusedElement=null,this.shouldRestoreFocus=!1}checkDropdownAlignment(e){let t=e===`slot`?this.slotContainerRef:this.searchContainerRef,n=e===`slot`?this.slotContentRef:this.searchMenuRef;if(!t.value||!n.value||!this.isTablet||this.isMobile)return;let r=t.value.getBoundingClientRect(),i=n.value.offsetWidth,a=r.left+i>window.innerWidth;e===`slot`?this.alignSlotRight=a:this.alignSearchRight=a}handleMenuToggle(e){this.openMenu===`none`?(this.lastFocusedElement=document.activeElement,this.openMenu=e):this.openMenu=`none`}handleLogoClick(e){this.dispatchEvent(new CustomEvent(`logo-click`,{bubbles:!0,composed:!0,detail:{originalEvent:e}}))}handleServiceClick(e){this.dispatchEvent(new CustomEvent(`service-click`,{bubbles:!0,composed:!0,detail:{originalEvent:e}}))}handleLogout(){this.dispatchEvent(new CustomEvent(`log-out`,{bubbles:!0,composed:!0}))}handleSearch(e){this.dispatchEvent(new CustomEvent(`search`,{detail:{query:e},bubbles:!0,composed:!0}))}handleSearchChange(e){this.dispatchEvent(new CustomEvent(`search-change`,{detail:{query:e},bubbles:!0,composed:!0}))}handleSearchInputChange(e){let t=e.target.value;this.handleSearchChange(t)}handleSearchKeyDown(e){e.key===`Enter`&&this.handleSearch(e.target.value)}get formattedLastLoggedIn(){return c(this.user?.lastLoggedIn)}get isFixed(){return this.position===`fixed`}get shouldHideOnScroll(){return this.scrollBehavior===`hide`}get showLogoutInHeader(){return this.hasLogOut&&(this.logOutButtonPlacement===`header`||this.logOutButtonPlacement===`both`)}get showLogoutInUserMenu(){return this.hasLogOut&&(this.logOutButtonPlacement===`userMenu`||this.logOutButtonPlacement===`both`)}renderLogo(){if(this.hideLogo)return e.d;let t=e.p`
83
+ `}};e.n([e.o({type:Object})],l.prototype,`user`,void 0),e.n([e.o({type:String,attribute:`formatted-last-logged-in`})],l.prototype,`formattedLastLoggedIn`,void 0),e.n([e.o({type:Object})],l.prototype,`representing`,void 0),e.n([e.o({type:Array,attribute:`user-menu`})],l.prototype,`userMenu`,void 0),e.n([e.o({type:Boolean,attribute:`can-change-representation`,converter:a.t})],l.prototype,`canChangeRepresentation`,void 0),e.n([e.o({type:Boolean,attribute:`logout-on-click`,converter:a.t})],l.prototype,`logoutOnClick`,void 0);try{e.s(`pkt-header-user-menu`)(l)}catch{console.warn(`Forsøker å definere <pkt-header-user-menu>, men den er allerede definert`)}var u=`https://punkt-cdn.oslo.kommune.no/latest/logos/`,d=class extends n.t{constructor(...e){super(...e),this.searchPlaceholder=`Søk`,this.searchValue=``,this.mobileBreakpoint=768,this.tabletBreakpoint=1280,this.openedMenu=`none`,this.logOutButtonPlacement=`none`,this.position=`fixed`,this.scrollBehavior=`hide`,this.slotMenuVariant=`icon-only`,this.slotMenuText=`Meny`,this.hideLogo=!1,this.compact=!1,this.showSearch=!1,this.canChangeRepresentation=!1,this.hasLogOut=!1,this.isMobile=!1,this.isTablet=!1,this.openMenu=`none`,this.isHidden=!1,this.componentWidth=typeof window<`u`?window.innerWidth:0,this.alignSlotRight=!1,this.alignSearchRight=!1,this.headerRef=i.t(),this.userContainerRef=i.t(),this.slotContainerRef=i.t(),this.searchContainerRef=i.t(),this.slotContentRef=i.t(),this.searchMenuRef=i.t(),this.lastScrollPosition=0,this.savedScrollY=0,this.lastFocusedElement=null,this.shouldRestoreFocus=!1,this.handleScroll=()=>{if(!this.shouldHideOnScroll)return;let e=window.pageYOffset||document.documentElement.scrollTop;e<0||Math.abs(e-this.lastScrollPosition)<60||(this.isHidden=e>this.lastScrollPosition,this.lastScrollPosition=e)},this.handleClickOutside=e=>{let t=e.target;this.user&&this.openMenu===`user`&&!t.closest(`.pkt-header-service__user-container`)&&(this.openMenu=`none`),this.openMenu===`slot`&&!t.closest(`.pkt-header-service__slot-container`)&&(this.openMenu=`none`),this.openMenu===`search`&&!t.closest(`.pkt-header-service__search-container`)&&!t.closest(`.pkt-header-service__search-input`)&&(this.openMenu=`none`)},this.handleSlotContentClick=e=>{if(!this.isTablet||this.openMenu!==`slot`)return;let t=e.target.closest(`a[href], button, [role="link"], [role="button"], [role="menuitem"], [role="menuitemradio"], [role="menuitemcheckbox"]`);!t||!this.slotContentRef.value?.contains(t)||t.closest(`[data-pkt-header-keep-open]`)||t.disabled||t.getAttribute(`aria-disabled`)===`true`||(this.openMenu=`none`)},this.handleFocusOut=(e,t)=>{let n=e.relatedTarget,r;switch(t){case`user`:r=this.userContainerRef;break;case`slot`:r=this.slotContainerRef;break;case`search`:r=this.searchContainerRef;break;default:return}let i=r.value;i&&(!n||!i.contains(n))&&(this.openMenu=`none`)},this.handleEscapeKey=e=>{e.key===`Escape`&&this.openMenu!==`none`&&(e.preventDefault(),this.shouldRestoreFocus=!0,this.openMenu=`none`)}}connectedCallback(){super.connectedCallback(),this.setupScrollListener()}disconnectedCallback(){super.disconnectedCallback(),this.resizeObserver?.disconnect(),window.removeEventListener(`scroll`,this.handleScroll),this.unlockScroll()}firstUpdated(){this.setupResizeObserver()}updated(e){if(super.updated(e),e.has(`openedMenu`)&&this.openedMenu!==this.openMenu&&(this.openMenu=this.openedMenu),(e.has(`mobileBreakpoint`)||e.has(`tabletBreakpoint`))&&(this.updateIsMobile(),this.updateIsTablet()),e.has(`openMenu`)){let t=e.get(`openMenu`);this.openMenu!==`none`&&(t===`none`||t===void 0)?(document.addEventListener(`mousedown`,this.handleClickOutside),document.addEventListener(`keydown`,this.handleEscapeKey),(this.openMenu===`slot`||this.openMenu===`search`)&&requestAnimationFrame(()=>{this.checkDropdownAlignment(this.openMenu)})):this.openMenu===`none`&&t!==`none`&&(document.removeEventListener(`mousedown`,this.handleClickOutside),document.removeEventListener(`keydown`,this.handleEscapeKey),this.restoreFocus())}(e.has(`openMenu`)||e.has(`isMobile`))&&this.updateScrollLock()}setupResizeObserver(){let e=this.headerRef.value;e&&(this.componentWidth=e.offsetWidth,this.updateIsMobile(),this.updateIsTablet(),this.resizeObserver=new ResizeObserver(e=>{for(let t of e)t.borderBoxSize&&t.borderBoxSize.length>0?this.componentWidth=t.borderBoxSize[0].inlineSize:this.componentWidth=t.contentRect.width,this.updateIsMobile(),this.updateIsTablet()}),this.resizeObserver.observe(e))}updateIsMobile(){this.isMobile=this.componentWidth<this.mobileBreakpoint}updateIsTablet(){this.isTablet=this.componentWidth<this.tabletBreakpoint}updateScrollLock(){this.position===`fixed`&&this.isMobile&&this.openMenu!==`none`?this.lockScroll():this.unlockScroll()}lockScroll(){let e=document.body,t=document.documentElement;this.savedScrollY=window.scrollY||window.pageYOffset;let n=window.innerWidth-t.clientWidth;n>0&&(e.style.paddingRight=`${n}px`),e.style.position=`fixed`,e.style.top=`-${this.savedScrollY}px`,e.style.left=`0`,e.style.right=`0`,e.style.width=`100%`,e.style.overflow=`hidden`,t.classList.add(`is-scroll-locked`)}unlockScroll(){let e=document.body,t=document.documentElement;t.classList.contains(`is-scroll-locked`)&&(e.style.removeProperty(`position`),e.style.removeProperty(`top`),e.style.removeProperty(`left`),e.style.removeProperty(`right`),e.style.removeProperty(`width`),e.style.removeProperty(`overflow`),e.style.removeProperty(`padding-right`),t.classList.remove(`is-scroll-locked`),window.scrollTo({top:this.savedScrollY}))}setupScrollListener(){window.addEventListener(`scroll`,this.handleScroll)}restoreFocus(){this.shouldRestoreFocus&&this.lastFocusedElement&&document.contains(this.lastFocusedElement)&&this.lastFocusedElement.focus(),this.lastFocusedElement=null,this.shouldRestoreFocus=!1}checkDropdownAlignment(e){let t=e===`slot`?this.slotContainerRef:this.searchContainerRef,n=e===`slot`?this.slotContentRef:this.searchMenuRef;if(!t.value||!n.value||!this.isTablet||this.isMobile)return;let r=t.value.getBoundingClientRect(),i=n.value.offsetWidth,a=r.left+i>window.innerWidth;e===`slot`?this.alignSlotRight=a:this.alignSearchRight=a}handleMenuToggle(e){this.openMenu===`none`?(this.lastFocusedElement=document.activeElement,this.openMenu=e):this.openMenu=`none`}handleLogoClick(e){this.dispatchEvent(new CustomEvent(`logo-click`,{bubbles:!0,composed:!0,detail:{originalEvent:e}}))}handleServiceClick(e){this.dispatchEvent(new CustomEvent(`service-click`,{bubbles:!0,composed:!0,detail:{originalEvent:e}}))}handleLogout(){this.dispatchEvent(new CustomEvent(`log-out`,{bubbles:!0,composed:!0}))}handleSearch(e){this.dispatchEvent(new CustomEvent(`search`,{detail:{query:e},bubbles:!0,composed:!0}))}handleSearchChange(e){this.dispatchEvent(new CustomEvent(`search-change`,{detail:{query:e},bubbles:!0,composed:!0}))}handleSearchInputChange(e){let t=e.target.value;this.handleSearchChange(t)}handleSearchKeyDown(e){e.key===`Enter`&&this.handleSearch(e.target.value)}get formattedLastLoggedIn(){return c(this.user?.lastLoggedIn)}get isFixed(){return this.position===`fixed`}get shouldHideOnScroll(){return this.scrollBehavior===`hide`}get showLogoutInHeader(){return this.hasLogOut&&(this.logOutButtonPlacement===`header`||this.logOutButtonPlacement===`both`)}get showLogoutInUserMenu(){return this.hasLogOut&&(this.logOutButtonPlacement===`userMenu`||this.logOutButtonPlacement===`both`)}renderLogo(){if(this.hideLogo)return e.d;let t=e.p`
84
84
  <pkt-icon name="oslologo" aria-hidden="true" path=${u}></pkt-icon>
85
85
  `;return this.logoLink&&typeof this.logoLink==`string`?e.p`
86
86
  <span class="pkt-header-service__logo">
@@ -120,7 +120,11 @@ const e=require(`./element-CXAtr6Gu.cjs`),t=require(`./class-map-B8Ja0q7n.cjs`),
120
120
  </button>
121
121
  </span>
122
122
  `:e.p`
123
- <span class="pkt-header-service__service-name" translate="no" @click=${this.handleServiceClick}>
123
+ <span
124
+ class="pkt-header-service__service-name"
125
+ translate="no"
126
+ @click=${this.handleServiceClick}
127
+ >
124
128
  <span class="pkt-header-service__service-link">${this.serviceName}</span>
125
129
  </span>
126
130
  `:e.d}renderSlotContainer(){if(!this.hasSlotContent())return e.d;let r=t.t({"pkt-header-service__slot-container":!0,"is-open":this.openMenu===`slot`}),a=t.t({"pkt-header-service__slot-content":!0,"align-right":this.alignSlotRight});return e.p`
@@ -149,6 +153,7 @@ const e=require(`./element-CXAtr6Gu.cjs`),t=require(`./class-map-B8Ja0q7n.cjs`),
149
153
  id="mobile-slot-menu"
150
154
  role=${this.isTablet?`menu`:e.d}
151
155
  aria-label=${this.isTablet?`Meny`:e.d}
156
+ @click=${this.handleSlotContentClick}
152
157
  ${i.n(this.slotContentRef)}
153
158
  >
154
159
  ${n.n(this)}
@@ -39,6 +39,14 @@ var c = {
39
39
  description: "Posisjonen til ikonet i forhold til lenketeksten",
40
40
  type: ["left", "right"],
41
41
  category: "ui"
42
+ },
43
+ renderLink: {
44
+ name: "Egendefinert lenkekomponent",
45
+ description: "React: Funksjon for å rendre en egendefinert lenkekomponent (f.eks. Next.js Link eller React Router Link). Mottar et objekt med href, className, children og props. Standard er et vanlig <a>-element.",
46
+ type: "function",
47
+ required: !1,
48
+ category: "tech",
49
+ reactOnly: !0
42
50
  }
43
51
  },
44
52
  slots: { default: { description: "Innholdet i lenken" } }
@@ -1,4 +1,4 @@
1
- const e=require(`./element-CXAtr6Gu.cjs`),t=require(`./class-map-B8Ja0q7n.cjs`),n=require(`./element-with-slot-Cmxb9h4H.cjs`);require(`./icon-Dw6I0HDV.cjs`);var r={name:`pkt-link`,react:`PktLink`,"css-class":`pkt-link`,"dark-mode":!0,isElement:!0,props:{href:{name:`URL`,description:`URL til lenken`,type:`string`,default:`#`,category:`contents`},target:{name:`Mål`,description:`Mål for lenken`,type:[`_blank`,`_self`,`_parent`,`_top`],default:`_self`,category:`tech`},iconName:{name:`Ikon`,description:`Ikon som skal vises ved siden av lenketeksten`,type:`icon`,category:`ui`},iconPosition:{name:`Ikonposisjon`,description:`Posisjonen til ikonet i forhold til lenketeksten`,type:[`left`,`right`],category:`ui`}},slots:{default:{description:`Innholdet i lenken`}}},i=class extends n.t{constructor(...e){super(...e),this.href=r.props.href.default,this.iconName=void 0,this.iconPosition=void 0,this.external=!1,this.target=r.props.target.default}render(){return e.p`<a
1
+ const e=require(`./element-CXAtr6Gu.cjs`),t=require(`./class-map-B8Ja0q7n.cjs`),n=require(`./element-with-slot-Cmxb9h4H.cjs`);require(`./icon-Dw6I0HDV.cjs`);var r={name:`pkt-link`,react:`PktLink`,"css-class":`pkt-link`,"dark-mode":!0,isElement:!0,props:{href:{name:`URL`,description:`URL til lenken`,type:`string`,default:`#`,category:`contents`},target:{name:`Mål`,description:`Mål for lenken`,type:[`_blank`,`_self`,`_parent`,`_top`],default:`_self`,category:`tech`},iconName:{name:`Ikon`,description:`Ikon som skal vises ved siden av lenketeksten`,type:`icon`,category:`ui`},iconPosition:{name:`Ikonposisjon`,description:`Posisjonen til ikonet i forhold til lenketeksten`,type:[`left`,`right`],category:`ui`},renderLink:{name:`Egendefinert lenkekomponent`,description:`React: Funksjon for å rendre en egendefinert lenkekomponent (f.eks. Next.js Link eller React Router Link). Mottar et objekt med href, className, children og props. Standard er et vanlig <a>-element.`,type:`function`,required:!1,category:`tech`,reactOnly:!0}},slots:{default:{description:`Innholdet i lenken`}}},i=class extends n.t{constructor(...e){super(...e),this.href=r.props.href.default,this.iconName=void 0,this.iconPosition=void 0,this.external=!1,this.target=r.props.target.default}render(){return e.p`<a
2
2
  class=${t.t({"pkt-link":!0,"pkt-link--icon-left":!!this.iconName&&this.iconPosition===`left`||!!(this.iconName&&!this.iconPosition),"pkt-link--icon-right":!!this.iconName&&this.iconPosition===`right`,"pkt-link--external":this.external})}
3
3
  href=${this.href}
4
4
  .target=${this.target}
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./header-CjBip0zj.cjs`);exports.PktHeader=e.t,exports.PktHeaderService=e.n,exports.PktHeaderUserMenu=e.r,exports.formatLastLoggedIn=e.i;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./header-gOdqWZ-o.cjs`);exports.PktHeader=e.t,exports.PktHeaderService=e.n,exports.PktHeaderUserMenu=e.r,exports.formatLastLoggedIn=e.i;
@@ -1,2 +1,2 @@
1
- import { i as e, n as t, r as n, t as r } from "./header-DONTGbD9.js";
1
+ import { i as e, n as t, r as n, t as r } from "./header-BdxslVug.js";
2
2
  export { r as PktHeader, t as PktHeaderService, n as PktHeaderUserMenu, e as formatLastLoggedIn };
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./alert-D_45dWPn.cjs`),t=require(`./icon-Dw6I0HDV.cjs`),n=require(`./button-Dwv11n6R.cjs`),r=require(`./accordion-DaeWPWod.cjs`),i=require(`./backlink-C42-3OG3.cjs`),a=require(`./breadcrumbs-CkjeLh3U.cjs`),o=require(`./calendar-64LmbIdR.cjs`),s=require(`./card-C__IlsUa.cjs`),c=require(`./tag-CBFz0R9N.cjs`),l=require(`./heading-C40-NX0r.cjs`),u=require(`./combobox-x4tBGP3F.cjs`),d=require(`./header-CjBip0zj.cjs`),f=require(`./header-menu-CnW7nzmF.cjs`),p=require(`./datepicker-Bs95HYGc.cjs`),m=require(`./fileupload-BLto9H17.cjs`),h=require(`./helptext-DNLg43eI.cjs`),g=require(`./input-wrapper-Dhkt20WW.cjs`),_=require(`./consent-DVt6sMvB.cjs`),v=require(`./checkbox-DzMc0AJX.cjs`),y=require(`./modal-CrYHKOmr.cjs`),b=require(`./progressbar-DADdvDl5.cjs`),x=require(`./link-B5ur0Rym.cjs`),S=require(`./textinput-C_6kvf87.cjs`),C=require(`./linkcard-BIcCW-qw.cjs`),w=require(`./loader-Uap9qDsV.cjs`),T=require(`./messagebox-BqBxXK8c.cjs`),E=require(`./radiobutton-BfURufrZ.cjs`),D=require(`./tabs-DxQy8U-0.cjs`),O=require(`./textarea-M_S9WK7s.cjs`),k=require(`./select-DzZHv6Bz.cjs`),A=require(`./searchinput-BrxfRzez.cjs`),j=require(`./timepicker-WiYLAncb.cjs`);exports.PktAccordion=r.r,exports.PktAccordionItem=r.n,exports.PktAlert=e.n,exports.PktBackLink=i.n,exports.PktBreadcrumbs=a.t,exports.PktButton=n.n,exports.PktCalendar=o.n,exports.PktCard=s.n,exports.PktCheckbox=v.n,exports.PktCombobox=u.n,exports.PktConsent=_.n,exports.PktDateTags=p.a,exports.PktDatepicker=p.t,Object.defineProperty(exports,`PktFileUpload`,{enumerable:!0,get:function(){return m.n}}),exports.PktHeader=d.t,exports.PktHeaderMenu=f.n,exports.PktHeaderService=d.n,exports.PktHeaderUserMenu=d.r,exports.PktHeading=l.n,exports.PktHelptext=h.n,exports.PktIcon=t.n,exports.PktInputWrapper=g.n,exports.PktLink=x.n,exports.PktLinkCard=C.n,exports.PktLoader=w.n,exports.PktMessagebox=T.n,exports.PktModal=y.n,exports.PktProgressbar=b.n,exports.PktRadioButton=E.n,exports.PktRadiobutton=E.n,exports.PktSearchInput=A.n,exports.PktSelect=k.n,exports.PktTabItem=D.n,exports.PktTabs=D.r,exports.PktTag=c.n,exports.PktTextarea=O.n,exports.PktTextinput=S.n,exports.PktTimepicker=j.t;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./alert-D_45dWPn.cjs`),t=require(`./icon-Dw6I0HDV.cjs`),n=require(`./button-Dwv11n6R.cjs`),r=require(`./accordion-DaeWPWod.cjs`),i=require(`./backlink-C42-3OG3.cjs`),a=require(`./breadcrumbs-CkjeLh3U.cjs`),o=require(`./calendar-64LmbIdR.cjs`),s=require(`./card-C__IlsUa.cjs`),c=require(`./tag-CBFz0R9N.cjs`),l=require(`./heading-C40-NX0r.cjs`),u=require(`./combobox-x4tBGP3F.cjs`),d=require(`./header-gOdqWZ-o.cjs`),f=require(`./header-menu-CnW7nzmF.cjs`),p=require(`./datepicker-Bs95HYGc.cjs`),m=require(`./fileupload-BLto9H17.cjs`),h=require(`./helptext-DNLg43eI.cjs`),g=require(`./input-wrapper-Dhkt20WW.cjs`),_=require(`./consent-DVt6sMvB.cjs`),v=require(`./checkbox-DzMc0AJX.cjs`),y=require(`./modal-CrYHKOmr.cjs`),b=require(`./progressbar-DADdvDl5.cjs`),x=require(`./link-EZ0-lS3W.cjs`),S=require(`./textinput-C_6kvf87.cjs`),C=require(`./linkcard-BIcCW-qw.cjs`),w=require(`./loader-Uap9qDsV.cjs`),T=require(`./messagebox-BqBxXK8c.cjs`),E=require(`./radiobutton-BfURufrZ.cjs`),D=require(`./tabs-DxQy8U-0.cjs`),O=require(`./textarea-M_S9WK7s.cjs`),k=require(`./select-DzZHv6Bz.cjs`),A=require(`./searchinput-BrxfRzez.cjs`),j=require(`./timepicker-WiYLAncb.cjs`);exports.PktAccordion=r.r,exports.PktAccordionItem=r.n,exports.PktAlert=e.n,exports.PktBackLink=i.n,exports.PktBreadcrumbs=a.t,exports.PktButton=n.n,exports.PktCalendar=o.n,exports.PktCard=s.n,exports.PktCheckbox=v.n,exports.PktCombobox=u.n,exports.PktConsent=_.n,exports.PktDateTags=p.a,exports.PktDatepicker=p.t,Object.defineProperty(exports,`PktFileUpload`,{enumerable:!0,get:function(){return m.n}}),exports.PktHeader=d.t,exports.PktHeaderMenu=f.n,exports.PktHeaderService=d.n,exports.PktHeaderUserMenu=d.r,exports.PktHeading=l.n,exports.PktHelptext=h.n,exports.PktIcon=t.n,exports.PktInputWrapper=g.n,exports.PktLink=x.n,exports.PktLinkCard=C.n,exports.PktLoader=w.n,exports.PktMessagebox=T.n,exports.PktModal=y.n,exports.PktProgressbar=b.n,exports.PktRadioButton=E.n,exports.PktRadiobutton=E.n,exports.PktSearchInput=A.n,exports.PktSelect=k.n,exports.PktTabItem=D.n,exports.PktTabs=D.r,exports.PktTag=c.n,exports.PktTextarea=O.n,exports.PktTextinput=S.n,exports.PktTimepicker=j.t;
package/dist/pkt-index.js CHANGED
@@ -9,7 +9,7 @@ import { n as c } from "./card-5PydU247.js";
9
9
  import { n as l } from "./tag-CzlnHhho.js";
10
10
  import { n as u } from "./heading-3o4Dk0Wn.js";
11
11
  import { n as d } from "./combobox-D-DY7YcW.js";
12
- import { n as f, r as p, t as m } from "./header-DONTGbD9.js";
12
+ import { n as f, r as p, t as m } from "./header-BdxslVug.js";
13
13
  import { n as h } from "./header-menu-BU-ylGrJ.js";
14
14
  import { a as g, t as _ } from "./datepicker-DxkcKevq.js";
15
15
  import { n as v } from "./fileupload-bykWTtA6.js";
@@ -19,7 +19,7 @@ import { n as x } from "./consent-BFdURuBl.js";
19
19
  import { n as S } from "./checkbox-CC1X7fw4.js";
20
20
  import { n as C } from "./modal-CWgeT-RP.js";
21
21
  import { n as w } from "./progressbar-B0P_vmGD.js";
22
- import { n as T } from "./link-ClUNY__5.js";
22
+ import { n as T } from "./link-DauiNRMq.js";
23
23
  import { n as E } from "./textinput-CZrBM-Fj.js";
24
24
  import { n as D } from "./linkcard-DNJm5FvA.js";
25
25
  import { n as O } from "./loader-gKdQpOOQ.js";
package/dist/pkt-link.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require(`./link-B5ur0Rym.cjs`);exports.PktLink=e.n,exports.default=e.t;
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require(`./link-EZ0-lS3W.cjs`);exports.PktLink=e.n,exports.default=e.t;
package/dist/pkt-link.js CHANGED
@@ -1,2 +1,2 @@
1
- import { n as e, t } from "./link-ClUNY__5.js";
1
+ import { n as e, t } from "./link-DauiNRMq.js";
2
2
  export { e as PktLink, t as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oslokommune/punkt-elements",
3
- "version": "16.24.1",
3
+ "version": "16.25.0",
4
4
  "description": "Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo",
5
5
  "homepage": "https://punkt.oslo.kommune.no",
6
6
  "author": "Team Designsystem, Oslo Origo",
@@ -79,5 +79,5 @@
79
79
  "url": "https://github.com/oslokommune/punkt/issues"
80
80
  },
81
81
  "license": "MIT",
82
- "gitHead": "f740327458813844b44a94fbb7a50b4036842883"
82
+ "gitHead": "d01de2b51e9c71b709202eb0d2fb3336e2932a20"
83
83
  }
@@ -401,4 +401,81 @@ describe('pkt-header-service', () => {
401
401
  }
402
402
  })
403
403
  })
404
+
405
+ describe('slot menu closes on intentional click', () => {
406
+ const isSlotOpen = (element: HTMLElement) =>
407
+ !!element.querySelector('.pkt-header-service__slot-container.is-open')
408
+
409
+ const clickSlotChild = async (element: HTMLElement, selector: string) => {
410
+ const target = element.querySelector(`.pkt-header-service__slot-content ${selector}`)
411
+ target?.dispatchEvent(new MouseEvent('click', { bubbles: true }))
412
+ await (element as CustomElementFor<'pkt-header-service'>).updateComplete
413
+ }
414
+
415
+ it('closes when clicking a link inside the menu', async () => {
416
+ const { element } = await createHeaderServiceTest({
417
+ 'service-name': 'Svc',
418
+ 'opened-menu': 'slot',
419
+ content: '<a href="#">Gå hit</a>',
420
+ })
421
+ expect(isSlotOpen(element)).toBe(true)
422
+ await clickSlotChild(element, 'a[href]')
423
+ expect(isSlotOpen(element)).toBe(false)
424
+ })
425
+
426
+ it('closes when clicking a button inside the menu', async () => {
427
+ const { element } = await createHeaderServiceTest({
428
+ 'service-name': 'Svc',
429
+ 'opened-menu': 'slot',
430
+ content: '<button type="button">Gjør noe</button>',
431
+ })
432
+ expect(isSlotOpen(element)).toBe(true)
433
+ await clickSlotChild(element, 'button')
434
+ expect(isSlotOpen(element)).toBe(false)
435
+ })
436
+
437
+ it('stays open when clicking a form input inside the menu', async () => {
438
+ const { element } = await createHeaderServiceTest({
439
+ 'service-name': 'Svc',
440
+ 'opened-menu': 'slot',
441
+ content: '<input type="text" aria-label="Filtrer" />',
442
+ })
443
+ expect(isSlotOpen(element)).toBe(true)
444
+ await clickSlotChild(element, 'input')
445
+ expect(isSlotOpen(element)).toBe(true)
446
+ })
447
+
448
+ it('stays open when clicking non-interactive content inside the menu', async () => {
449
+ const { element } = await createHeaderServiceTest({
450
+ 'service-name': 'Svc',
451
+ 'opened-menu': 'slot',
452
+ content: '<span>Bare tekst</span>',
453
+ })
454
+ expect(isSlotOpen(element)).toBe(true)
455
+ await clickSlotChild(element, 'span')
456
+ expect(isSlotOpen(element)).toBe(true)
457
+ })
458
+
459
+ it('stays open when clicking an element marked data-pkt-header-keep-open', async () => {
460
+ const { element } = await createHeaderServiceTest({
461
+ 'service-name': 'Svc',
462
+ 'opened-menu': 'slot',
463
+ content: '<button type="button" data-pkt-header-keep-open>Vis mer</button>',
464
+ })
465
+ expect(isSlotOpen(element)).toBe(true)
466
+ await clickSlotChild(element, 'button')
467
+ expect(isSlotOpen(element)).toBe(true)
468
+ })
469
+
470
+ it('stays open when clicking a disabled button inside the menu', async () => {
471
+ const { element } = await createHeaderServiceTest({
472
+ 'service-name': 'Svc',
473
+ 'opened-menu': 'slot',
474
+ content: '<button type="button" disabled>Utilgjengelig</button>',
475
+ })
476
+ expect(isSlotOpen(element)).toBe(true)
477
+ await clickSlotChild(element, 'button')
478
+ expect(isSlotOpen(element)).toBe(true)
479
+ })
480
+ })
404
481
  })
@@ -253,6 +253,24 @@ export class PktHeaderService extends PktElementWithSlot<IPktHeader> implements
253
253
  }
254
254
  }
255
255
 
256
+ // Close the slot menu when the user makes an intentional click inside it.
257
+ private handleSlotContentClick = (event: MouseEvent) => {
258
+ if (!this.isTablet || this.openMenu !== 'slot') return
259
+
260
+ const interactive = (event.target as HTMLElement).closest<HTMLElement>(
261
+ 'a[href], button, [role="link"], [role="button"], [role="menuitem"], [role="menuitemradio"], [role="menuitemcheckbox"]',
262
+ )
263
+ if (!interactive || !this.slotContentRef.value?.contains(interactive)) return
264
+ if (interactive.closest('[data-pkt-header-keep-open]')) return
265
+ if (
266
+ (interactive as HTMLButtonElement).disabled ||
267
+ interactive.getAttribute('aria-disabled') === 'true'
268
+ )
269
+ return
270
+
271
+ this.openMenu = 'none'
272
+ }
273
+
256
274
  private handleFocusOut = (event: FocusEvent, menuType: THeaderMenu) => {
257
275
  const relatedTarget = event.relatedTarget as HTMLElement | null
258
276
 
@@ -483,7 +501,11 @@ export class PktHeaderService extends PktElementWithSlot<IPktHeader> implements
483
501
 
484
502
  // No link - just render the text
485
503
  return html`
486
- <span class="pkt-header-service__service-name" translate="no" @click=${this.handleServiceClick}>
504
+ <span
505
+ class="pkt-header-service__service-name"
506
+ translate="no"
507
+ @click=${this.handleServiceClick}
508
+ >
487
509
  <span class="pkt-header-service__service-link">${this.serviceName}</span>
488
510
  </span>
489
511
  `
@@ -529,6 +551,7 @@ export class PktHeaderService extends PktElementWithSlot<IPktHeader> implements
529
551
  id="mobile-slot-menu"
530
552
  role=${this.isTablet ? 'menu' : nothing}
531
553
  aria-label=${this.isTablet ? 'Meny' : nothing}
554
+ @click=${this.handleSlotContentClick}
532
555
  ${ref(this.slotContentRef)}
533
556
  >
534
557
  ${slotContent(this)}