66
77import { getMetadata } from '../../scripts/aem.js' ;
88import { loadFragment } from '../fragment/fragment.js' ;
9+ import { getBlockContext } from '../../scripts/shared.js' ;
910
1011const DESKTOP = window . matchMedia ( '(min-width: 900px)' ) ;
11- const THEME_KEY = 'color-scheme ' ;
12+ const THEME_KEY = 'diyfire-theme ' ;
1213
1314function getNavPath ( ) {
1415 const meta = getMetadata ( 'nav' ) ;
@@ -72,7 +73,7 @@ function decorateMega(li) {
7273
7374 // Position dropdown: full viewport width, arrow under trigger
7475 const sync = ( ) => {
75- if ( ! document . body . contains ( li ) ) return ;
76+ if ( ! li . isConnected ) return ;
7677 const trigger = li . querySelector ( ':scope > p' ) ;
7778 const menu = li . querySelector ( ':scope > ul' ) ;
7879 if ( ! trigger || ! menu ) return ;
@@ -135,23 +136,22 @@ function initTheme(tools) {
135136 const get = ( ) => {
136137 try {
137138 const s = localStorage . getItem ( THEME_KEY ) ;
138- if ( s === 'light-scheme ' || s === 'dark-scheme ' ) return s ;
139+ if ( s === 'light' || s === 'dark' ) return s ;
139140 } catch ( e ) { /* ignore */ }
140- return matchMedia ( '(prefers-color-scheme: dark)' ) . matches ? 'dark-scheme ' : 'light-scheme ' ;
141+ return matchMedia ( '(prefers-color-scheme: dark)' ) . matches ? 'dark' : 'light' ;
141142 } ;
142143 const set = ( s ) => {
143- if ( s !== 'light-scheme' && s !== 'dark-scheme' ) return ;
144- document . body . classList . remove ( 'light-scheme' , 'dark-scheme' ) ;
145- document . body . classList . add ( s ) ;
144+ if ( s !== 'light' && s !== 'dark' ) return ;
146145 try { localStorage . setItem ( THEME_KEY , s ) ; } catch ( e ) { /* ignore */ }
146+ window . dispatchEvent ( new CustomEvent ( 'aem-theme-change' , { detail : { theme : s } } ) ) ;
147147 } ;
148148
149149 btn . classList . add ( 'nav-tool' ) ;
150150 btn . setAttribute ( 'role' , 'button' ) ;
151151 btn . setAttribute ( 'tabindex' , '0' ) ;
152- const updateLabel = ( ) => btn . setAttribute ( 'aria-label' , `Switch to ${ get ( ) === 'dark-scheme ' ? 'light' : 'dark' } mode` ) ;
152+ const updateLabel = ( ) => btn . setAttribute ( 'aria-label' , `Switch to ${ get ( ) === 'dark' ? 'light' : 'dark' } mode` ) ;
153153 const toggle = ( ) => {
154- set ( get ( ) === 'dark-scheme ' ? 'light-scheme ' : 'dark-scheme ' ) ;
154+ set ( get ( ) === 'dark' ? 'light' : 'dark' ) ;
155155 updateLabel ( ) ;
156156 } ;
157157 btn . addEventListener ( 'click' , toggle ) ;
@@ -311,7 +311,7 @@ function decorateLanguageMenu(menu) {
311311 } ) ;
312312}
313313
314- function initLanguage ( tools ) {
314+ function initLanguage ( tools , eventRoot ) {
315315 const globe = tools . querySelector ( '.icon-globe' ) ?. closest ( 'p, button, a, div' ) ;
316316 const menu = globe ? findLangMenu ( tools , globe ) : null ;
317317 if ( ! globe || ! menu ) return ;
@@ -340,16 +340,16 @@ function initLanguage(tools) {
340340 } ;
341341
342342 globe . addEventListener ( 'click' , ( e ) => { e . preventDefault ( ) ; toggle ( ) ; } ) ;
343- document . addEventListener ( 'click' , ( e ) => { if ( ! tools . contains ( e . target ) ) { menu . hidden = true ; globe . setAttribute ( 'aria-expanded' , 'false' ) ; } } ) ;
344- document . addEventListener ( 'keydown' , ( e ) => { if ( e . code === 'Escape' ) { menu . hidden = true ; globe . setAttribute ( 'aria-expanded' , 'false' ) ; } } ) ;
343+ eventRoot . addEventListener ( 'click' , ( e ) => { if ( ! tools . contains ( e . target ) ) { menu . hidden = true ; globe . setAttribute ( 'aria-expanded' , 'false' ) ; } } ) ;
344+ eventRoot . addEventListener ( 'keydown' , ( e ) => { if ( e . code === 'Escape' ) { menu . hidden = true ; globe . setAttribute ( 'aria-expanded' , 'false' ) ; } } ) ;
345345 menu . querySelectorAll ( 'a' ) . forEach ( ( a ) => a . addEventListener ( 'click' , ( ) => { menu . hidden = true ; globe . setAttribute ( 'aria-expanded' , 'false' ) ; } ) ) ;
346346
347347 decorateLanguageMenu ( menu ) ;
348348}
349349
350- function toggleMobile ( nav , open ) {
350+ function toggleMobile ( nav , open , body ) {
351351 const isOpen = open === undefined ? nav . getAttribute ( 'aria-expanded' ) !== 'true' : open ;
352- document . body . style . overflowY = isOpen && ! DESKTOP . matches ? 'hidden' : '' ;
352+ body . style . overflowY = isOpen && ! DESKTOP . matches ? 'hidden' : '' ;
353353 nav . setAttribute ( 'aria-expanded' , isOpen ) ;
354354 nav . querySelector ( '.nav-hamburger button' ) ?. setAttribute ( 'aria-label' , isOpen ? 'Close navigation' : 'Open navigation' ) ;
355355 nav . querySelectorAll ( '.nav-drop' ) . forEach ( ( d ) => d . setAttribute ( 'tabindex' , DESKTOP . matches ? '0' : '-1' ) ) ;
@@ -358,6 +358,8 @@ function toggleMobile(nav, open) {
358358const NAV_ITEMS = '.default-content-wrapper > ul > li' ;
359359
360360export default async function decorate ( block ) {
361+ const { body, eventRoot } = getBlockContext ( block ) ;
362+
361363 // Load nav content (skip if aem-embed already provided content)
362364 if ( block . textContent === '' ) {
363365 const fragment = await loadFragment ( getNavPath ( ) ) ;
@@ -406,17 +408,17 @@ export default async function decorate(block) {
406408 const hamburger = document . createElement ( 'div' ) ;
407409 hamburger . className = 'nav-hamburger' ;
408410 hamburger . innerHTML = '<button type="button" aria-controls="nav" aria-label="Open navigation"><span class="nav-hamburger-icon"></span></button>' ;
409- hamburger . onclick = ( ) => toggleMobile ( nav ) ;
411+ hamburger . onclick = ( ) => toggleMobile ( nav , undefined , body ) ;
410412
411- document . addEventListener ( 'click' , ( e ) => {
413+ eventRoot . addEventListener ( 'click' , ( e ) => {
412414 if ( ! DESKTOP . matches && nav . getAttribute ( 'aria-expanded' ) === 'true' && ! nav . contains ( e . target ) ) {
413- toggleMobile ( nav , false ) ;
415+ toggleMobile ( nav , false , body ) ;
414416 }
415417 } ) ;
416- document . addEventListener ( 'keydown' , ( e ) => {
418+ eventRoot . addEventListener ( 'keydown' , ( e ) => {
417419 if ( e . code !== 'Escape' ) return ;
418420 if ( ! DESKTOP . matches && nav . getAttribute ( 'aria-expanded' ) === 'true' ) {
419- toggleMobile ( nav , false ) ;
421+ toggleMobile ( nav , false , body ) ;
420422 } else if ( DESKTOP . matches && nav . querySelector ( '.nav-drop[aria-expanded="true"]' ) ) {
421423 collapseAll ( nav ) ;
422424 }
@@ -428,14 +430,14 @@ export default async function decorate(block) {
428430 wrapper . append ( nav ) ;
429431 block . append ( wrapper ) ;
430432
431- toggleMobile ( nav , false ) ;
433+ toggleMobile ( nav , false , body ) ;
432434 collapseAll ( nav ) ;
433- DESKTOP . addEventListener ( 'change' , ( ) => toggleMobile ( nav , false ) ) ;
435+ DESKTOP . addEventListener ( 'change' , ( ) => toggleMobile ( nav , false , body ) ) ;
434436
435437 if ( tools ) {
436438 initTheme ( tools ) ;
437439 initSearch ( tools ) ;
438- initLanguage ( tools ) ;
440+ initLanguage ( tools , eventRoot ) ;
439441 hydrateTranslateFromCookie ( ) ;
440442 }
441443
0 commit comments