@ably/ui 17.7.4-dev.8763c7aa → 17.7.4-dev.c54fc584

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/core/Header.js CHANGED
@@ -1,2 +1,2 @@
1
- import React,{useState,useEffect,useRef,useMemo}from"react";import Icon from"./Icon";import cn from"./utils/cn";import Logo from"./Logo";import{componentMaxHeight,HEADER_BOTTOM_MARGIN,HEADER_HEIGHT}from"./utils/heights";import{HeaderLinks}from"./Header/HeaderLinks";import{throttle}from"es-toolkit/compat";import{COLLAPSE_TRIGGER_DISTANCE}from"./Notice/component";const FLEXIBLE_DESKTOP_CLASSES="hidden md:flex flex-1 items-center h-full";const MAX_MOBILE_MENU_WIDTH="560px";const Header=({className,isNoticeVisible=false,noticeHeight=0,searchBar,searchButton,logoHref,headerLinks,headerLinksClassName,headerCenterClassName,nav,mobileNav,sessionState,themedScrollpoints=[],searchButtonVisibility="all",location,logoBadge})=>{const[showMenu,setShowMenu]=useState(false);const[fadingOut,setFadingOut]=useState(false);const[bannerVisible,setBannerVisible]=useState(isNoticeVisible);const menuRef=useRef(null);const[scrollpointClasses,setScrollpointClasses]=useState(themedScrollpoints.length>0?themedScrollpoints[0].className:"");const headerStyle=useMemo(()=>({height:HEADER_HEIGHT,top:bannerVisible?`${noticeHeight}px`:"0"}),[bannerVisible,noticeHeight]);console.log("bannerVisible",bannerVisible);console.log("noticeHeight",noticeHeight);const headerClassName=useMemo(()=>cn("fixed left-0 top-0 w-full z-50 bg-neutral-000 dark:bg-neutral-1300 border-b border-neutral-300 dark:border-neutral-1000 transition-colors px-6 lg:px-16",scrollpointClasses,{"md:top-auto":bannerVisible}),[scrollpointClasses,bannerVisible]);const closeMenu=()=>{setFadingOut(true);setTimeout(()=>{setShowMenu(false);setFadingOut(false)},150)};useEffect(()=>{const handleNoticeClose=()=>{setBannerVisible(false)};document.addEventListener("notice-closed",handleNoticeClose);return()=>document.removeEventListener("notice-closed",handleNoticeClose)},[]);useEffect(()=>{const handleScroll=()=>{setBannerVisible(window.scrollY<=COLLAPSE_TRIGGER_DISTANCE&&isNoticeVisible);for(const scrollpoint of themedScrollpoints){const element=document.getElementById(scrollpoint.id);if(element){const rect=element.getBoundingClientRect();if(rect.top<=HEADER_HEIGHT&&rect.bottom>=HEADER_HEIGHT){setScrollpointClasses(scrollpoint.className);return}}}};const throttledHandleScroll=throttle(handleScroll,150);handleScroll();window.addEventListener("scroll",throttledHandleScroll);return()=>window.removeEventListener("scroll",throttledHandleScroll)},[themedScrollpoints,isNoticeVisible]);useEffect(()=>{const handleResize=()=>{if(window.innerWidth>=1040){setShowMenu(false)}};window.addEventListener("resize",handleResize);return()=>window.removeEventListener("resize",handleResize)},[]);useEffect(()=>{if(showMenu){document.body.classList.add("overflow-hidden")}else{document.body.classList.remove("overflow-hidden")}return()=>{document.body.classList.remove("overflow-hidden")}},[showMenu]);useEffect(()=>{if(location&&showMenu){closeMenu()}},[location,showMenu]);const wrappedSearchButton=useMemo(()=>searchButton?React.createElement("div",{className:"text-neutral-1300 dark:text-neutral-000 flex items-center"},searchButton):null,[searchButton]);return React.createElement(React.Fragment,null,React.createElement("header",{role:"banner",className:headerClassName,style:headerStyle},React.createElement("div",{className:cn("flex items-center h-full",className)},React.createElement("nav",{className:"flex flex-1 h-full items-center"},["light","dark"].map(theme=>React.createElement(Logo,{key:theme,href:logoHref,theme:theme,badge:logoBadge,additionalLinkAttrs:{className:cn("h-full focus-base rounded mr-4 lg:mr-8",{"flex dark:hidden":theme==="light","hidden dark:flex":theme==="dark"})}})),React.createElement("div",{className:FLEXIBLE_DESKTOP_CLASSES},nav)),React.createElement("div",{className:"flex md:hidden flex-1 items-center justify-end gap-6 h-full"},searchButtonVisibility!=="desktop"?wrappedSearchButton:null,React.createElement("button",{className:"cursor-pointer focus-base rounded flex items-center p-0",onClick:()=>setShowMenu(!showMenu),"aria-expanded":showMenu,"aria-controls":"mobile-menu","aria-label":"Toggle menu"},React.createElement(Icon,{name:showMenu?"icon-gui-x-mark-outline":"icon-gui-bars-3-outline",additionalCSS:"text-neutral-1300 dark:text-neutral-000",size:"1.5rem"}))),searchBar?React.createElement("div",{className:cn(FLEXIBLE_DESKTOP_CLASSES,"justify-center",headerCenterClassName)},searchBar):null,React.createElement(HeaderLinks,{className:cn(FLEXIBLE_DESKTOP_CLASSES,headerLinksClassName),headerLinks:headerLinks,sessionState:sessionState,searchButton:wrappedSearchButton,searchButtonVisibility:searchButtonVisibility}))),showMenu?React.createElement(React.Fragment,null,React.createElement("div",{className:cn("fixed inset-0 bg-neutral-1300 dark:bg-neutral-1300 z-40",{"animate-[fade-in-ten-percent_150ms_ease-in-out_forwards]":!fadingOut,"animate-[fade-out-ten-percent_150ms_ease-in-out_forwards]":fadingOut}),onClick:closeMenu,onKeyDown:e=>e.key==="Escape"&&closeMenu(),role:"presentation"}),React.createElement("div",{id:"mobile-menu",className:"md:hidden fixed flex flex-col top-[4.75rem] overflow-y-hidden mx-3 right-0 w-[calc(100%-24px)] bg-neutral-000 dark:bg-neutral-1300 rounded-2xl ui-shadow-lg-medium z-50",style:{maxWidth:MAX_MOBILE_MENU_WIDTH,maxHeight:componentMaxHeight(HEADER_HEIGHT,HEADER_BOTTOM_MARGIN)},ref:menuRef,role:"navigation"},mobileNav,React.createElement(HeaderLinks,{headerLinks:headerLinks,sessionState:sessionState}))):null)};export default Header;
1
+ import React,{useState,useEffect,useRef,useMemo,useCallback}from"react";import Icon from"./Icon";import cn from"./utils/cn";import Logo from"./Logo";import{componentMaxHeight,HEADER_BOTTOM_MARGIN,HEADER_HEIGHT}from"./utils/heights";import{HeaderLinks}from"./Header/HeaderLinks";import{throttle}from"es-toolkit/compat";import{COLLAPSE_TRIGGER_DISTANCE}from"./Notice/component";const FLEXIBLE_DESKTOP_CLASSES="hidden md:flex flex-1 items-center h-full";const MAX_MOBILE_MENU_WIDTH="560px";const Header=({className,isNoticeBannerEnabled=false,noticeHeight=0,searchBar,searchButton,logoHref,headerLinks,headerLinksClassName,headerCenterClassName,nav,mobileNav,sessionState,themedScrollpoints=[],searchButtonVisibility="all",location,logoBadge})=>{const[showMenu,setShowMenu]=useState(false);const[fadingOut,setFadingOut]=useState(false);const[noticeBannerVisible,setNoticeBannerVisible]=useState(isNoticeBannerEnabled);const menuRef=useRef(null);const[scrollpointClasses,setScrollpointClasses]=useState(themedScrollpoints.length>0?themedScrollpoints[0].className:"");const headerStyle={height:HEADER_HEIGHT,top:noticeBannerVisible?`${noticeHeight}px`:"0"};const headerClassName=cn("fixed left-0 top-0 w-full z-50 bg-neutral-000 dark:bg-neutral-1300 border-b border-neutral-300 dark:border-neutral-1000 transition-all duration-300 ease-in-out px-6 lg:px-16",scrollpointClasses,{"md:top-auto":noticeBannerVisible});const closeMenu=()=>{setFadingOut(true);setTimeout(()=>{setShowMenu(false);setFadingOut(false)},150)};const handleNoticeClose=useCallback(()=>{setNoticeBannerVisible(false)},[]);useEffect(()=>{document.addEventListener("notice-closed",handleNoticeClose);return()=>document.removeEventListener("notice-closed",handleNoticeClose)},[handleNoticeClose]);useEffect(()=>{const handleScroll=()=>{const noticeElement=document.querySelector('[data-id="ui-notice"]');const isNoticeClosedToBeHidden=noticeElement?.classList.contains("ui-announcement-hidden");setNoticeBannerVisible(window.scrollY<=COLLAPSE_TRIGGER_DISTANCE&&isNoticeBannerEnabled&&!isNoticeClosedToBeHidden);for(const scrollpoint of themedScrollpoints){const element=document.getElementById(scrollpoint.id);if(element){const rect=element.getBoundingClientRect();if(rect.top<=HEADER_HEIGHT&&rect.bottom>=HEADER_HEIGHT){setScrollpointClasses(scrollpoint.className);return}}}};const throttledHandleScroll=throttle(handleScroll,100);handleScroll();window.addEventListener("scroll",throttledHandleScroll);return()=>window.removeEventListener("scroll",throttledHandleScroll)},[themedScrollpoints,isNoticeBannerEnabled]);useEffect(()=>{const handleResize=()=>{if(window.innerWidth>=1040){setShowMenu(false)}};window.addEventListener("resize",handleResize);return()=>window.removeEventListener("resize",handleResize)},[]);useEffect(()=>{if(showMenu){document.body.classList.add("overflow-hidden")}else{document.body.classList.remove("overflow-hidden")}return()=>{document.body.classList.remove("overflow-hidden")}},[showMenu]);useEffect(()=>{if(location&&showMenu){closeMenu()}},[location,showMenu]);const wrappedSearchButton=useMemo(()=>searchButton?React.createElement("div",{className:"text-neutral-1300 dark:text-neutral-000 flex items-center"},searchButton):null,[searchButton]);return React.createElement(React.Fragment,null,React.createElement("header",{role:"banner",style:headerStyle,className:headerClassName},React.createElement("div",{className:cn("flex items-center h-full",className)},React.createElement("nav",{className:"flex flex-1 h-full items-center"},["light","dark"].map(theme=>React.createElement(Logo,{key:theme,href:logoHref,theme:theme,badge:logoBadge,additionalLinkAttrs:{className:cn("h-full focus-base rounded mr-4 lg:mr-8",{"flex dark:hidden":theme==="light","hidden dark:flex":theme==="dark"})}})),React.createElement("div",{className:FLEXIBLE_DESKTOP_CLASSES},nav)),React.createElement("div",{className:"flex md:hidden flex-1 items-center justify-end gap-6 h-full"},searchButtonVisibility!=="desktop"?wrappedSearchButton:null,React.createElement("button",{className:"cursor-pointer focus-base rounded flex items-center p-0",onClick:()=>setShowMenu(!showMenu),"aria-expanded":showMenu,"aria-controls":"mobile-menu","aria-label":"Toggle menu"},React.createElement(Icon,{name:showMenu?"icon-gui-x-mark-outline":"icon-gui-bars-3-outline",additionalCSS:"text-neutral-1300 dark:text-neutral-000",size:"1.5rem"}))),searchBar?React.createElement("div",{className:cn(FLEXIBLE_DESKTOP_CLASSES,"justify-center",headerCenterClassName)},searchBar):null,React.createElement(HeaderLinks,{className:cn(FLEXIBLE_DESKTOP_CLASSES,headerLinksClassName),headerLinks:headerLinks,sessionState:sessionState,searchButton:wrappedSearchButton,searchButtonVisibility:searchButtonVisibility}))),showMenu?React.createElement(React.Fragment,null,React.createElement("div",{className:cn("fixed inset-0 bg-neutral-1300 dark:bg-neutral-1300 z-40",{"animate-[fade-in-ten-percent_150ms_ease-in-out_forwards]":!fadingOut,"animate-[fade-out-ten-percent_150ms_ease-in-out_forwards]":fadingOut}),onClick:closeMenu,onKeyDown:e=>e.key==="Escape"&&closeMenu(),role:"presentation"}),React.createElement("div",{id:"mobile-menu",className:"md:hidden fixed flex flex-col top-[4.75rem] overflow-y-hidden mx-3 right-0 w-[calc(100%-24px)] bg-neutral-000 dark:bg-neutral-1300 rounded-2xl ui-shadow-lg-medium z-50",style:{maxWidth:MAX_MOBILE_MENU_WIDTH,maxHeight:componentMaxHeight(HEADER_HEIGHT,HEADER_BOTTOM_MARGIN)},ref:menuRef,role:"navigation"},mobileNav,React.createElement(HeaderLinks,{headerLinks:headerLinks,sessionState:sessionState}))):null)};export default Header;
2
2
  //# sourceMappingURL=Header.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/Header.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, ReactNode, useMemo } from \"react\";\nimport Icon from \"./Icon\";\nimport cn from \"./utils/cn\";\nimport Logo from \"./Logo\";\nimport {\n componentMaxHeight,\n HEADER_BOTTOM_MARGIN,\n HEADER_HEIGHT,\n} from \"./utils/heights\";\nimport { HeaderLinks } from \"./Header/HeaderLinks\";\nimport { throttle } from \"es-toolkit/compat\";\nimport { Theme } from \"./styles/colors/types\";\nimport { COLLAPSE_TRIGGER_DISTANCE } from \"./Notice/component\";\n\nexport type ThemedScrollpoint = {\n id: string;\n className: string;\n};\n\n/**\n * Represents the state of the user session in the header.\n */\nexport type HeaderSessionState = {\n /**\n * Indicates if the user is signed in.\n */\n signedIn: boolean;\n\n /**\n * Information required to log out the user.\n */\n logOut: {\n /**\n * Token used for logging out.\n */\n token: string;\n\n /**\n * URL to log out the user.\n */\n href: string;\n };\n\n /**\n * Name of the user's account.\n */\n accountName: string;\n};\n\n/**\n * Props for the Header component.\n */\nexport type HeaderProps = {\n /**\n * Optional classnames to add to the header\n */\n className?: string;\n /**\n * Indicates if the notice banner is visible.\n */\n isNoticeVisible?: boolean;\n /**\n * Height of the notice banner in pixels.\n */\n noticeHeight?: number;\n /**\n * Optional search bar element.\n */\n searchBar?: ReactNode;\n\n /**\n * Optional search button element.\n */\n searchButton?: ReactNode;\n\n /**\n * URL for the logo link.\n */\n logoHref?: string;\n\n /**\n * Array of header links.\n */\n headerLinks?: {\n /**\n * URL for the link.\n */\n href: string;\n\n /**\n * Label for the link.\n */\n label: string;\n\n /**\n * Indicates if the link should open in a new tab.\n */\n external?: boolean;\n }[];\n\n /**\n * Optional classname for styling the header links container.\n */\n headerLinksClassName?: string;\n\n /**\n * Optional classname for styling the header center container.\n */\n headerCenterClassName?: string;\n\n /**\n * Optional desktop navigation element.\n */\n nav?: ReactNode;\n\n /**\n * Optional mobile navigation element.\n */\n mobileNav?: ReactNode;\n\n /**\n * State of the user session.\n */\n sessionState?: HeaderSessionState;\n\n /**\n * Array of themed scrollpoints. The header will change its appearance based on the scrollpoint in view.\n */\n themedScrollpoints?: ThemedScrollpoint[];\n\n /**\n * Visibility setting for the search button.\n * - \"all\": Visible on all devices.\n * - \"desktop\": Visible only on desktop devices.\n * - \"mobile\": Visible only on mobile devices.\n */\n searchButtonVisibility?: \"all\" | \"desktop\" | \"mobile\";\n\n /**\n * Optional location object to detect location changes.\n */\n location?: Location;\n\n /**\n * Optional badge text to display on the logo.\n */\n logoBadge?: string;\n};\n\nconst FLEXIBLE_DESKTOP_CLASSES = \"hidden md:flex flex-1 items-center h-full\";\n\n/**\n * Maximum width before the menu expanded into full width\n */\nconst MAX_MOBILE_MENU_WIDTH = \"560px\";\n\nconst Header: React.FC<HeaderProps> = ({\n className,\n isNoticeVisible = false,\n noticeHeight = 0,\n searchBar,\n searchButton,\n logoHref,\n headerLinks,\n headerLinksClassName,\n headerCenterClassName,\n nav,\n mobileNav,\n sessionState,\n themedScrollpoints = [],\n searchButtonVisibility = \"all\",\n location,\n logoBadge,\n}) => {\n const [showMenu, setShowMenu] = useState(false);\n const [fadingOut, setFadingOut] = useState(false);\n const [bannerVisible, setBannerVisible] = useState(isNoticeVisible);\n const menuRef = useRef<HTMLDivElement>(null);\n const [scrollpointClasses, setScrollpointClasses] = useState<string>(\n themedScrollpoints.length > 0 ? themedScrollpoints[0].className : \"\",\n );\n\n // Memoize header style to prevent unnecessary recalculations\n const headerStyle = useMemo(() => ({\n height: HEADER_HEIGHT,\n top: bannerVisible ? `${noticeHeight}px` : \"0\",\n }), [bannerVisible, noticeHeight]);\n\n console.log(\"bannerVisible\", bannerVisible);\n console.log(\"noticeHeight\", noticeHeight);\n\n // Memoize header className to prevent unnecessary class recalculations\n const headerClassName = useMemo(() => cn(\n \"fixed left-0 top-0 w-full z-50 bg-neutral-000 dark:bg-neutral-1300 border-b border-neutral-300 dark:border-neutral-1000 transition-colors px-6 lg:px-16\",\n scrollpointClasses,\n {\n \"md:top-auto\": bannerVisible,\n },\n ), [scrollpointClasses, bannerVisible]);\n\n const closeMenu = () => {\n setFadingOut(true);\n\n setTimeout(() => {\n setShowMenu(false);\n setFadingOut(false);\n }, 150);\n };\n\n useEffect(() => {\n const handleNoticeClose = () => {\n setBannerVisible(false);\n };\n\n document.addEventListener(\"notice-closed\", handleNoticeClose);\n return () =>\n document.removeEventListener(\"notice-closed\", handleNoticeClose);\n }, []);\n\n useEffect(() => {\n const handleScroll = () => {\n setBannerVisible(\n window.scrollY <= COLLAPSE_TRIGGER_DISTANCE && isNoticeVisible,\n );\n for (const scrollpoint of themedScrollpoints) {\n const element = document.getElementById(scrollpoint.id);\n if (element) {\n const rect = element.getBoundingClientRect();\n if (rect.top <= HEADER_HEIGHT && rect.bottom >= HEADER_HEIGHT) {\n setScrollpointClasses(scrollpoint.className);\n return;\n }\n }\n }\n };\n\n const throttledHandleScroll = throttle(handleScroll, 150);\n\n handleScroll();\n\n window.addEventListener(\"scroll\", throttledHandleScroll);\n return () => window.removeEventListener(\"scroll\", throttledHandleScroll);\n }, [themedScrollpoints, isNoticeVisible]);\n\n useEffect(() => {\n const handleResize = () => {\n if (window.innerWidth >= 1040) {\n setShowMenu(false);\n }\n };\n window.addEventListener(\"resize\", handleResize);\n return () => window.removeEventListener(\"resize\", handleResize);\n }, []);\n\n useEffect(() => {\n if (showMenu) {\n document.body.classList.add(\"overflow-hidden\");\n } else {\n document.body.classList.remove(\"overflow-hidden\");\n }\n\n // Cleanup on unmount\n return () => {\n document.body.classList.remove(\"overflow-hidden\");\n };\n }, [showMenu]);\n\n // Close menu when location changes\n useEffect(() => {\n if (location && showMenu) {\n closeMenu();\n }\n }, [location, showMenu]);\n\n const wrappedSearchButton = useMemo(\n () =>\n searchButton ? (\n <div className=\"text-neutral-1300 dark:text-neutral-000 flex items-center\">\n {searchButton}\n </div>\n ) : null,\n [searchButton],\n );\n\n return (\n <>\n <header\n role=\"banner\"\n className={headerClassName}\n style={headerStyle}\n >\n <div className={cn(\"flex items-center h-full\", className)}>\n <nav className=\"flex flex-1 h-full items-center\">\n {([\"light\", \"dark\"] as Theme[]).map((theme) => (\n <Logo\n key={theme}\n href={logoHref}\n theme={theme}\n badge={logoBadge}\n additionalLinkAttrs={{\n className: cn(\"h-full focus-base rounded mr-4 lg:mr-8\", {\n \"flex dark:hidden\": theme === \"light\",\n \"hidden dark:flex\": theme === \"dark\",\n }),\n }}\n />\n ))}\n <div className={FLEXIBLE_DESKTOP_CLASSES}>{nav}</div>\n </nav>\n <div className=\"flex md:hidden flex-1 items-center justify-end gap-6 h-full\">\n {searchButtonVisibility !== \"desktop\" ? wrappedSearchButton : null}\n <button\n className=\"cursor-pointer focus-base rounded flex items-center p-0\"\n onClick={() => setShowMenu(!showMenu)}\n aria-expanded={showMenu}\n aria-controls=\"mobile-menu\"\n aria-label=\"Toggle menu\"\n >\n <Icon\n name={\n showMenu\n ? \"icon-gui-x-mark-outline\"\n : \"icon-gui-bars-3-outline\"\n }\n additionalCSS=\"text-neutral-1300 dark:text-neutral-000\"\n size=\"1.5rem\"\n />\n </button>\n </div>\n {searchBar ? (\n <div\n className={cn(\n FLEXIBLE_DESKTOP_CLASSES,\n \"justify-center\",\n headerCenterClassName,\n )}\n >\n {searchBar}\n </div>\n ) : null}\n <HeaderLinks\n className={cn(FLEXIBLE_DESKTOP_CLASSES, headerLinksClassName)}\n headerLinks={headerLinks}\n sessionState={sessionState}\n searchButton={wrappedSearchButton}\n searchButtonVisibility={searchButtonVisibility}\n />\n </div>\n </header>\n {showMenu ? (\n <>\n <div\n className={cn(\n \"fixed inset-0 bg-neutral-1300 dark:bg-neutral-1300 z-40\",\n {\n \"animate-[fade-in-ten-percent_150ms_ease-in-out_forwards]\":\n !fadingOut,\n \"animate-[fade-out-ten-percent_150ms_ease-in-out_forwards]\":\n fadingOut,\n },\n )}\n onClick={closeMenu}\n onKeyDown={(e) => e.key === \"Escape\" && closeMenu()}\n role=\"presentation\"\n />\n <div\n id=\"mobile-menu\"\n className=\"md:hidden fixed flex flex-col top-[4.75rem] overflow-y-hidden mx-3 right-0 w-[calc(100%-24px)] bg-neutral-000 dark:bg-neutral-1300 rounded-2xl ui-shadow-lg-medium z-50\"\n style={{\n maxWidth: MAX_MOBILE_MENU_WIDTH,\n maxHeight: componentMaxHeight(\n HEADER_HEIGHT,\n HEADER_BOTTOM_MARGIN,\n ),\n }}\n ref={menuRef}\n role=\"navigation\"\n >\n {mobileNav}\n <HeaderLinks\n headerLinks={headerLinks}\n sessionState={sessionState}\n />\n </div>\n </>\n ) : null}\n </>\n );\n};\n\nexport default Header;\n"],"names":["React","useState","useEffect","useRef","useMemo","Icon","cn","Logo","componentMaxHeight","HEADER_BOTTOM_MARGIN","HEADER_HEIGHT","HeaderLinks","throttle","COLLAPSE_TRIGGER_DISTANCE","FLEXIBLE_DESKTOP_CLASSES","MAX_MOBILE_MENU_WIDTH","Header","className","isNoticeVisible","noticeHeight","searchBar","searchButton","logoHref","headerLinks","headerLinksClassName","headerCenterClassName","nav","mobileNav","sessionState","themedScrollpoints","searchButtonVisibility","location","logoBadge","showMenu","setShowMenu","fadingOut","setFadingOut","bannerVisible","setBannerVisible","menuRef","scrollpointClasses","setScrollpointClasses","length","headerStyle","height","top","console","log","headerClassName","closeMenu","setTimeout","handleNoticeClose","document","addEventListener","removeEventListener","handleScroll","window","scrollY","scrollpoint","element","getElementById","id","rect","getBoundingClientRect","bottom","throttledHandleScroll","handleResize","innerWidth","body","classList","add","remove","wrappedSearchButton","div","header","role","style","map","theme","key","href","badge","additionalLinkAttrs","button","onClick","aria-expanded","aria-controls","aria-label","name","additionalCSS","size","onKeyDown","e","maxWidth","maxHeight","ref"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/core/Header.tsx"],"sourcesContent":["import React, {\n useState,\n useEffect,\n useRef,\n ReactNode,\n useMemo,\n useCallback,\n} from \"react\";\nimport Icon from \"./Icon\";\nimport cn from \"./utils/cn\";\nimport Logo from \"./Logo\";\nimport {\n componentMaxHeight,\n HEADER_BOTTOM_MARGIN,\n HEADER_HEIGHT,\n} from \"./utils/heights\";\nimport { HeaderLinks } from \"./Header/HeaderLinks\";\nimport { throttle } from \"es-toolkit/compat\";\nimport { Theme } from \"./styles/colors/types\";\nimport { COLLAPSE_TRIGGER_DISTANCE } from \"./Notice/component\";\n\nexport type ThemedScrollpoint = {\n id: string;\n className: string;\n};\n\n/**\n * Represents the state of the user session in the header.\n */\nexport type HeaderSessionState = {\n /**\n * Indicates if the user is signed in.\n */\n signedIn: boolean;\n\n /**\n * Information required to log out the user.\n */\n logOut: {\n /**\n * Token used for logging out.\n */\n token: string;\n\n /**\n * URL to log out the user.\n */\n href: string;\n };\n\n /**\n * Name of the user's account.\n */\n accountName: string;\n};\n\n/**\n * Props for the Header component.\n */\nexport type HeaderProps = {\n /**\n * Optional classnames to add to the header\n */\n className?: string;\n /**\n * Indicates if the notice banner is enabled.\n */\n isNoticeBannerEnabled?: boolean;\n /**\n * Height of the notice banner in pixels.\n */\n noticeHeight?: number;\n /**\n * Optional search bar element.\n */\n searchBar?: ReactNode;\n\n /**\n * Optional search button element.\n */\n searchButton?: ReactNode;\n\n /**\n * URL for the logo link.\n */\n logoHref?: string;\n\n /**\n * Array of header links.\n */\n headerLinks?: {\n /**\n * URL for the link.\n */\n href: string;\n\n /**\n * Label for the link.\n */\n label: string;\n\n /**\n * Indicates if the link should open in a new tab.\n */\n external?: boolean;\n }[];\n\n /**\n * Optional classname for styling the header links container.\n */\n headerLinksClassName?: string;\n\n /**\n * Optional classname for styling the header center container.\n */\n headerCenterClassName?: string;\n\n /**\n * Optional desktop navigation element.\n */\n nav?: ReactNode;\n\n /**\n * Optional mobile navigation element.\n */\n mobileNav?: ReactNode;\n\n /**\n * State of the user session.\n */\n sessionState?: HeaderSessionState;\n\n /**\n * Array of themed scrollpoints. The header will change its appearance based on the scrollpoint in view.\n */\n themedScrollpoints?: ThemedScrollpoint[];\n\n /**\n * Visibility setting for the search button.\n * - \"all\": Visible on all devices.\n * - \"desktop\": Visible only on desktop devices.\n * - \"mobile\": Visible only on mobile devices.\n */\n searchButtonVisibility?: \"all\" | \"desktop\" | \"mobile\";\n\n /**\n * Optional location object to detect location changes.\n */\n location?: Location;\n\n /**\n * Optional badge text to display on the logo.\n */\n logoBadge?: string;\n};\n\nconst FLEXIBLE_DESKTOP_CLASSES = \"hidden md:flex flex-1 items-center h-full\";\n\n/**\n * Maximum width before the menu expanded into full width\n */\nconst MAX_MOBILE_MENU_WIDTH = \"560px\";\n\nconst Header: React.FC<HeaderProps> = ({\n className,\n isNoticeBannerEnabled = false,\n noticeHeight = 0,\n searchBar,\n searchButton,\n logoHref,\n headerLinks,\n headerLinksClassName,\n headerCenterClassName,\n nav,\n mobileNav,\n sessionState,\n themedScrollpoints = [],\n searchButtonVisibility = \"all\",\n location,\n logoBadge,\n}) => {\n const [showMenu, setShowMenu] = useState(false);\n const [fadingOut, setFadingOut] = useState(false);\n const [noticeBannerVisible, setNoticeBannerVisible] = useState(\n isNoticeBannerEnabled,\n );\n const menuRef = useRef<HTMLDivElement>(null);\n const [scrollpointClasses, setScrollpointClasses] = useState<string>(\n themedScrollpoints.length > 0 ? themedScrollpoints[0].className : \"\",\n );\n\n const headerStyle = {\n height: HEADER_HEIGHT,\n top: noticeBannerVisible ? `${noticeHeight}px` : \"0\",\n };\n\n const headerClassName = cn(\n \"fixed left-0 top-0 w-full z-50 bg-neutral-000 dark:bg-neutral-1300 border-b border-neutral-300 dark:border-neutral-1000 transition-all duration-300 ease-in-out px-6 lg:px-16\",\n scrollpointClasses,\n {\n \"md:top-auto\": noticeBannerVisible,\n },\n );\n\n const closeMenu = () => {\n setFadingOut(true);\n\n setTimeout(() => {\n setShowMenu(false);\n setFadingOut(false);\n }, 150);\n };\n\n const handleNoticeClose = useCallback(() => {\n setNoticeBannerVisible(false);\n }, []);\n\n useEffect(() => {\n document.addEventListener(\"notice-closed\", handleNoticeClose);\n return () =>\n document.removeEventListener(\"notice-closed\", handleNoticeClose);\n }, [handleNoticeClose]);\n\n useEffect(() => {\n const handleScroll = () => {\n const noticeElement = document.querySelector('[data-id=\"ui-notice\"]');\n const isNoticeClosedToBeHidden = noticeElement?.classList.contains(\n \"ui-announcement-hidden\",\n );\n setNoticeBannerVisible(\n window.scrollY <= COLLAPSE_TRIGGER_DISTANCE &&\n isNoticeBannerEnabled &&\n !isNoticeClosedToBeHidden,\n );\n for (const scrollpoint of themedScrollpoints) {\n const element = document.getElementById(scrollpoint.id);\n if (element) {\n const rect = element.getBoundingClientRect();\n if (rect.top <= HEADER_HEIGHT && rect.bottom >= HEADER_HEIGHT) {\n setScrollpointClasses(scrollpoint.className);\n return;\n }\n }\n }\n };\n\n const throttledHandleScroll = throttle(handleScroll, 100);\n\n handleScroll();\n\n window.addEventListener(\"scroll\", throttledHandleScroll);\n return () => window.removeEventListener(\"scroll\", throttledHandleScroll);\n }, [themedScrollpoints, isNoticeBannerEnabled]);\n\n useEffect(() => {\n const handleResize = () => {\n if (window.innerWidth >= 1040) {\n setShowMenu(false);\n }\n };\n window.addEventListener(\"resize\", handleResize);\n return () => window.removeEventListener(\"resize\", handleResize);\n }, []);\n\n useEffect(() => {\n if (showMenu) {\n document.body.classList.add(\"overflow-hidden\");\n } else {\n document.body.classList.remove(\"overflow-hidden\");\n }\n\n // Cleanup on unmount\n return () => {\n document.body.classList.remove(\"overflow-hidden\");\n };\n }, [showMenu]);\n\n // Close menu when location changes\n useEffect(() => {\n if (location && showMenu) {\n closeMenu();\n }\n }, [location, showMenu]);\n\n const wrappedSearchButton = useMemo(\n () =>\n searchButton ? (\n <div className=\"text-neutral-1300 dark:text-neutral-000 flex items-center\">\n {searchButton}\n </div>\n ) : null,\n [searchButton],\n );\n\n return (\n <>\n <header role=\"banner\" style={headerStyle} className={headerClassName}>\n <div className={cn(\"flex items-center h-full\", className)}>\n <nav className=\"flex flex-1 h-full items-center\">\n {([\"light\", \"dark\"] as Theme[]).map((theme) => (\n <Logo\n key={theme}\n href={logoHref}\n theme={theme}\n badge={logoBadge}\n additionalLinkAttrs={{\n className: cn(\"h-full focus-base rounded mr-4 lg:mr-8\", {\n \"flex dark:hidden\": theme === \"light\",\n \"hidden dark:flex\": theme === \"dark\",\n }),\n }}\n />\n ))}\n <div className={FLEXIBLE_DESKTOP_CLASSES}>{nav}</div>\n </nav>\n <div className=\"flex md:hidden flex-1 items-center justify-end gap-6 h-full\">\n {searchButtonVisibility !== \"desktop\" ? wrappedSearchButton : null}\n <button\n className=\"cursor-pointer focus-base rounded flex items-center p-0\"\n onClick={() => setShowMenu(!showMenu)}\n aria-expanded={showMenu}\n aria-controls=\"mobile-menu\"\n aria-label=\"Toggle menu\"\n >\n <Icon\n name={\n showMenu\n ? \"icon-gui-x-mark-outline\"\n : \"icon-gui-bars-3-outline\"\n }\n additionalCSS=\"text-neutral-1300 dark:text-neutral-000\"\n size=\"1.5rem\"\n />\n </button>\n </div>\n {searchBar ? (\n <div\n className={cn(\n FLEXIBLE_DESKTOP_CLASSES,\n \"justify-center\",\n headerCenterClassName,\n )}\n >\n {searchBar}\n </div>\n ) : null}\n <HeaderLinks\n className={cn(FLEXIBLE_DESKTOP_CLASSES, headerLinksClassName)}\n headerLinks={headerLinks}\n sessionState={sessionState}\n searchButton={wrappedSearchButton}\n searchButtonVisibility={searchButtonVisibility}\n />\n </div>\n </header>\n {showMenu ? (\n <>\n <div\n className={cn(\n \"fixed inset-0 bg-neutral-1300 dark:bg-neutral-1300 z-40\",\n {\n \"animate-[fade-in-ten-percent_150ms_ease-in-out_forwards]\":\n !fadingOut,\n \"animate-[fade-out-ten-percent_150ms_ease-in-out_forwards]\":\n fadingOut,\n },\n )}\n onClick={closeMenu}\n onKeyDown={(e) => e.key === \"Escape\" && closeMenu()}\n role=\"presentation\"\n />\n <div\n id=\"mobile-menu\"\n className=\"md:hidden fixed flex flex-col top-[4.75rem] overflow-y-hidden mx-3 right-0 w-[calc(100%-24px)] bg-neutral-000 dark:bg-neutral-1300 rounded-2xl ui-shadow-lg-medium z-50\"\n style={{\n maxWidth: MAX_MOBILE_MENU_WIDTH,\n maxHeight: componentMaxHeight(\n HEADER_HEIGHT,\n HEADER_BOTTOM_MARGIN,\n ),\n }}\n ref={menuRef}\n role=\"navigation\"\n >\n {mobileNav}\n <HeaderLinks\n headerLinks={headerLinks}\n sessionState={sessionState}\n />\n </div>\n </>\n ) : null}\n </>\n );\n};\n\nexport default Header;\n"],"names":["React","useState","useEffect","useRef","useMemo","useCallback","Icon","cn","Logo","componentMaxHeight","HEADER_BOTTOM_MARGIN","HEADER_HEIGHT","HeaderLinks","throttle","COLLAPSE_TRIGGER_DISTANCE","FLEXIBLE_DESKTOP_CLASSES","MAX_MOBILE_MENU_WIDTH","Header","className","isNoticeBannerEnabled","noticeHeight","searchBar","searchButton","logoHref","headerLinks","headerLinksClassName","headerCenterClassName","nav","mobileNav","sessionState","themedScrollpoints","searchButtonVisibility","location","logoBadge","showMenu","setShowMenu","fadingOut","setFadingOut","noticeBannerVisible","setNoticeBannerVisible","menuRef","scrollpointClasses","setScrollpointClasses","length","headerStyle","height","top","headerClassName","closeMenu","setTimeout","handleNoticeClose","document","addEventListener","removeEventListener","handleScroll","noticeElement","querySelector","isNoticeClosedToBeHidden","classList","contains","window","scrollY","scrollpoint","element","getElementById","id","rect","getBoundingClientRect","bottom","throttledHandleScroll","handleResize","innerWidth","body","add","remove","wrappedSearchButton","div","header","role","style","map","theme","key","href","badge","additionalLinkAttrs","button","onClick","aria-expanded","aria-controls","aria-label","name","additionalCSS","size","onKeyDown","e","maxWidth","maxHeight","ref"],"mappings":"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"}
package/core/Meganav.js CHANGED
@@ -1,2 +1,2 @@
1
- import React,{useEffect,useMemo}from"react";import Header from"./Header";import Flyout from"./Flyout";import{menuItemsForHeader}from"./Meganav/data";import{MeganavMobile}from"./Meganav/MeganavMobile";import Notice from"./Notice";import{HEADER_HEIGHT}from"./utils/heights";const Meganav=({sessionState,notice,theme,themedScrollpoints,onNoticeClose})=>{const[noticeHeight,setNoticeHeight]=React.useState(0);const memoizedNoticeHeight=useMemo(()=>{if(!notice){return 0}return noticeHeight},[notice,noticeHeight]);const mobileNavItems=useMemo(()=>menuItemsForHeader.filter(item=>!item.isHiddenMobile).map(({name,link,content})=>({name,link,content})),[]);const defaultThemedScrollpoints=[{id:"meganav",className:"ui-theme-light !bg-transparent !border-none"},{id:"meganav-theme-dark",className:"ui-theme-dark !bg-transparent !border-none"},{id:"main",className:"ui-theme-light bg-neutral-000 dark:bg-neutral-1300 border-b"},{id:"main-theme-dark",className:"ui-theme-dark bg-neutral-000 dark:bg-neutral-1300 border-b"}];useEffect(()=>{const observeNoticeResize=()=>{const noticeElement=document.querySelector('[data-id="ui-notice"]');if(noticeElement){setNoticeHeight(noticeElement.getBoundingClientRect().height)}else{setNoticeHeight(0)}};if(notice){setTimeout(observeNoticeResize,0)}observeNoticeResize();window.addEventListener("resize",observeNoticeResize);return()=>window.removeEventListener("resize",observeNoticeResize)},[notice]);return React.createElement(React.Fragment,null,React.createElement("div",{className:"absolute inset-0 w-full z-50",id:theme==="dark"?"meganav-theme-dark":"meganav","data-testid":"meganav",style:{height:HEADER_HEIGHT+memoizedNoticeHeight}},notice&&React.createElement(Notice,{...notice.props,config:notice.config,onClose:onNoticeClose}),React.createElement(Header,{className:"max-w-screen-xl mx-auto px-0 sm:px-8 md:px-10 lg:px-16",isNoticeVisible:!!notice,noticeHeight:memoizedNoticeHeight,nav:React.createElement(Flyout,{menuItems:menuItemsForHeader,className:"justify-left z-40",flyOutClassName:"flex justify-left",viewPortClassName:"ui-shadow-lg-medium border border-neutral-200 dark:border-neutral-1100 rounded-2xl -mt-1 bg-neutral-000 dark:bg-neutral-1300"}),mobileNav:React.createElement(MeganavMobile,{navItems:mobileNavItems}),headerLinks:[{href:"/contact",label:"Contact us"}],headerLinksClassName:"md:gap-x-6 ",sessionState:sessionState,themedScrollpoints:themedScrollpoints??defaultThemedScrollpoints})))};export default Meganav;
1
+ import React,{useEffect,useMemo}from"react";import Header from"./Header";import Flyout from"./Flyout";import{menuItemsForHeader}from"./Meganav/data";import{MeganavMobile}from"./Meganav/MeganavMobile";import Notice from"./Notice";import{HEADER_HEIGHT}from"./utils/heights";const Meganav=({sessionState,notice,theme,themedScrollpoints,onNoticeClose})=>{const[noticeHeight,setNoticeHeight]=React.useState(0);const finalNoticeHeight=notice?noticeHeight:0;const mobileNavItems=useMemo(()=>menuItemsForHeader.filter(item=>!item.isHiddenMobile).map(({name,link,content})=>({name,link,content})),[]);const defaultThemedScrollpoints=[{id:"meganav",className:"ui-theme-light !bg-transparent !border-none"},{id:"meganav-theme-dark",className:"ui-theme-dark !bg-transparent !border-none"},{id:"main",className:"ui-theme-light bg-neutral-000 dark:bg-neutral-1300 border-b"},{id:"main-theme-dark",className:"ui-theme-dark bg-neutral-000 dark:bg-neutral-1300 border-b"}];useEffect(()=>{if(!notice){setNoticeHeight(0);return}const noticeElement=document.querySelector('[data-id="ui-notice"]');if(!noticeElement)return;const updateNoticeHeight=()=>{setNoticeHeight(noticeElement.getBoundingClientRect().height)};const observer=new ResizeObserver(updateNoticeHeight);observer.observe(noticeElement);const timeoutId=setTimeout(updateNoticeHeight,0);window.addEventListener("resize",updateNoticeHeight);return()=>{clearTimeout(timeoutId);observer.disconnect();window.removeEventListener("resize",updateNoticeHeight)}},[notice]);return React.createElement(React.Fragment,null,React.createElement("div",{className:"absolute inset-0 w-full z-50",id:theme==="dark"?"meganav-theme-dark":"meganav","data-testid":"meganav",style:{height:HEADER_HEIGHT+finalNoticeHeight}},notice&&React.createElement(Notice,{...notice.props,config:notice.config,onClose:onNoticeClose}),React.createElement(Header,{className:"max-w-screen-xl mx-auto px-0 sm:px-8 md:px-10 lg:px-16",isNoticeBannerEnabled:!!notice,noticeHeight:finalNoticeHeight,nav:React.createElement(Flyout,{menuItems:menuItemsForHeader,className:"justify-left z-40",flyOutClassName:"flex justify-left",viewPortClassName:"ui-shadow-lg-medium border border-neutral-200 dark:border-neutral-1100 rounded-2xl -mt-1 bg-neutral-000 dark:bg-neutral-1300"}),mobileNav:React.createElement(MeganavMobile,{navItems:mobileNavItems}),headerLinks:[{href:"/contact",label:"Contact us"}],headerLinksClassName:"md:gap-x-6 ",sessionState:sessionState,themedScrollpoints:themedScrollpoints??defaultThemedScrollpoints})))};export default Meganav;
2
2
  //# sourceMappingURL=Meganav.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/Meganav.tsx"],"sourcesContent":["import React, { useEffect, useMemo } from \"react\";\nimport Header, { HeaderSessionState, ThemedScrollpoint } from \"./Header\";\nimport Flyout from \"./Flyout\";\nimport { menuItemsForHeader } from \"./Meganav/data\";\nimport { MeganavMobile } from \"./Meganav/MeganavMobile\";\nimport Notice from \"./Notice\";\nimport { HEADER_HEIGHT } from \"./utils/heights\";\n\nexport type MeganavNoticeBannerProps = {\n props: {\n title: string;\n bodyText: string;\n buttonLink: string;\n buttonLabel: string;\n closeBtn: boolean;\n };\n config: {\n cookieId: string;\n noticeId: string | number;\n options: {\n collapse: boolean;\n };\n };\n};\n\nexport type MeganavProps = {\n sessionState: HeaderSessionState;\n notice?: MeganavNoticeBannerProps;\n theme?: string;\n themedScrollpoints?: ThemedScrollpoint[];\n onNoticeClose?: () => void;\n};\n\nconst Meganav = ({\n sessionState,\n notice,\n theme,\n themedScrollpoints,\n onNoticeClose,\n}: MeganavProps) => {\n const [noticeHeight, setNoticeHeight] = React.useState(0);\n \n // Memoize notice height calculation when notice changes\n const memoizedNoticeHeight = useMemo(() => {\n if (!notice) {\n return 0;\n }\n return noticeHeight;\n }, [notice, noticeHeight]);\n const mobileNavItems = useMemo(\n () =>\n menuItemsForHeader\n .filter((item) => !item.isHiddenMobile)\n .map(({ name, link, content }) => ({ name, link, content })),\n [],\n );\n\n const defaultThemedScrollpoints = [\n {\n id: \"meganav\",\n className: \"ui-theme-light !bg-transparent !border-none\",\n },\n {\n id: \"meganav-theme-dark\",\n className: \"ui-theme-dark !bg-transparent !border-none\",\n },\n {\n id: \"main\",\n className: \"ui-theme-light bg-neutral-000 dark:bg-neutral-1300 border-b\",\n },\n {\n id: \"main-theme-dark\",\n className: \"ui-theme-dark bg-neutral-000 dark:bg-neutral-1300 border-b\",\n },\n ];\n\n useEffect(() => {\n const observeNoticeResize = () => {\n const noticeElement = document.querySelector('[data-id=\"ui-notice\"]');\n if (noticeElement) {\n setNoticeHeight(noticeElement.getBoundingClientRect().height);\n } else {\n setNoticeHeight(0);\n }\n };\n \n // Run immediately if notice exists\n if (notice) {\n // Small delay to ensure DOM is rendered\n setTimeout(observeNoticeResize, 0);\n }\n \n observeNoticeResize();\n window.addEventListener(\"resize\", observeNoticeResize);\n return () => window.removeEventListener(\"resize\", observeNoticeResize);\n }, [notice]); // Add notice as dependency\n\n return (\n <>\n <div\n className=\"absolute inset-0 w-full z-50\"\n id={theme === \"dark\" ? \"meganav-theme-dark\" : \"meganav\"}\n data-testid=\"meganav\"\n style={{ height: HEADER_HEIGHT + memoizedNoticeHeight }}\n >\n {notice && (\n <Notice\n {...notice.props}\n config={notice.config}\n onClose={onNoticeClose}\n />\n )}\n <Header\n className=\"max-w-screen-xl mx-auto px-0 sm:px-8 md:px-10 lg:px-16\"\n isNoticeVisible={!!notice}\n noticeHeight={memoizedNoticeHeight}\n nav={\n <Flyout\n menuItems={menuItemsForHeader}\n className=\"justify-left z-40\"\n flyOutClassName=\"flex justify-left\"\n viewPortClassName=\"ui-shadow-lg-medium border border-neutral-200 dark:border-neutral-1100 rounded-2xl -mt-1 bg-neutral-000 dark:bg-neutral-1300\"\n />\n }\n mobileNav={<MeganavMobile navItems={mobileNavItems} />}\n headerLinks={[{ href: \"/contact\", label: \"Contact us\" }]}\n headerLinksClassName=\"md:gap-x-6 \"\n sessionState={sessionState}\n themedScrollpoints={themedScrollpoints ?? defaultThemedScrollpoints}\n />\n </div>\n </>\n );\n};\n\nexport default Meganav;\n"],"names":["React","useEffect","useMemo","Header","Flyout","menuItemsForHeader","MeganavMobile","Notice","HEADER_HEIGHT","Meganav","sessionState","notice","theme","themedScrollpoints","onNoticeClose","noticeHeight","setNoticeHeight","useState","memoizedNoticeHeight","mobileNavItems","filter","item","isHiddenMobile","map","name","link","content","defaultThemedScrollpoints","id","className","observeNoticeResize","noticeElement","document","querySelector","getBoundingClientRect","height","setTimeout","window","addEventListener","removeEventListener","div","data-testid","style","props","config","onClose","isNoticeVisible","nav","menuItems","flyOutClassName","viewPortClassName","mobileNav","navItems","headerLinks","href","label","headerLinksClassName"],"mappings":"AAAA,OAAOA,OAASC,SAAS,CAAEC,OAAO,KAAQ,OAAQ,AAClD,QAAOC,WAAuD,UAAW,AACzE,QAAOC,WAAY,UAAW,AAC9B,QAASC,kBAAkB,KAAQ,gBAAiB,AACpD,QAASC,aAAa,KAAQ,yBAA0B,AACxD,QAAOC,WAAY,UAAW,AAC9B,QAASC,aAAa,KAAQ,iBAAkB,CA2BhD,MAAMC,QAAU,CAAC,CACfC,YAAY,CACZC,MAAM,CACNC,KAAK,CACLC,kBAAkB,CAClBC,aAAa,CACA,IACb,KAAM,CAACC,aAAcC,gBAAgB,CAAGhB,MAAMiB,QAAQ,CAAC,GAGvD,MAAMC,qBAAuBhB,QAAQ,KACnC,GAAI,CAACS,OAAQ,CACX,OAAO,CACT,CACA,OAAOI,YACT,EAAG,CAACJ,OAAQI,aAAa,EACzB,MAAMI,eAAiBjB,QACrB,IACEG,mBACGe,MAAM,CAAC,AAACC,MAAS,CAACA,KAAKC,cAAc,EACrCC,GAAG,CAAC,CAAC,CAAEC,IAAI,CAAEC,IAAI,CAAEC,OAAO,CAAE,GAAM,CAAA,CAAEF,KAAMC,KAAMC,OAAQ,CAAA,GAC7D,EAAE,EAGJ,MAAMC,0BAA4B,CAChC,CACEC,GAAI,UACJC,UAAW,6CACb,EACA,CACED,GAAI,qBACJC,UAAW,4CACb,EACA,CACED,GAAI,OACJC,UAAW,6DACb,EACA,CACED,GAAI,kBACJC,UAAW,4DACb,EACD,CAED5B,UAAU,KACR,MAAM6B,oBAAsB,KAC1B,MAAMC,cAAgBC,SAASC,aAAa,CAAC,yBAC7C,GAAIF,cAAe,CACjBf,gBAAgBe,cAAcG,qBAAqB,GAAGC,MAAM,CAC9D,KAAO,CACLnB,gBAAgB,EAClB,CACF,EAGA,GAAIL,OAAQ,CAEVyB,WAAWN,oBAAqB,EAClC,CAEAA,sBACAO,OAAOC,gBAAgB,CAAC,SAAUR,qBAClC,MAAO,IAAMO,OAAOE,mBAAmB,CAAC,SAAUT,oBACpD,EAAG,CAACnB,OAAO,EAEX,OACE,wCACE,oBAAC6B,OACCX,UAAU,+BACVD,GAAIhB,QAAU,OAAS,qBAAuB,UAC9C6B,cAAY,UACZC,MAAO,CAAEP,OAAQ3B,cAAgBU,oBAAqB,GAErDP,QACC,oBAACJ,QACE,GAAGI,OAAOgC,KAAK,CAChBC,OAAQjC,OAAOiC,MAAM,CACrBC,QAAS/B,gBAGb,oBAACX,QACC0B,UAAU,yDACViB,gBAAiB,CAAC,CAACnC,OACnBI,aAAcG,qBACd6B,IACE,oBAAC3C,QACC4C,UAAW3C,mBACXwB,UAAU,oBACVoB,gBAAgB,oBAChBC,kBAAkB,iIAGtBC,UAAW,oBAAC7C,eAAc8C,SAAUjC,iBACpCkC,YAAa,CAAC,CAAEC,KAAM,WAAYC,MAAO,YAAa,EAAE,CACxDC,qBAAqB,cACrB9C,aAAcA,aACdG,mBAAoBA,oBAAsBc,6BAKpD,CAEA,gBAAelB,OAAQ"}
1
+ {"version":3,"sources":["../../src/core/Meganav.tsx"],"sourcesContent":["import React, { useEffect, useMemo } from \"react\";\nimport Header, { HeaderSessionState, ThemedScrollpoint } from \"./Header\";\nimport Flyout from \"./Flyout\";\nimport { menuItemsForHeader } from \"./Meganav/data\";\nimport { MeganavMobile } from \"./Meganav/MeganavMobile\";\nimport Notice from \"./Notice\";\nimport { HEADER_HEIGHT } from \"./utils/heights\";\n\nexport type MeganavNoticeBannerProps = {\n props: {\n title: string;\n bodyText: string;\n buttonLink: string;\n buttonLabel: string;\n closeBtn: boolean;\n };\n config: {\n cookieId: string;\n noticeId: string | number;\n options: {\n collapse: boolean;\n };\n };\n};\n\nexport type MeganavProps = {\n sessionState: HeaderSessionState;\n notice?: MeganavNoticeBannerProps;\n theme?: string;\n themedScrollpoints?: ThemedScrollpoint[];\n onNoticeClose?: () => void;\n};\n\nconst Meganav = ({\n sessionState,\n notice,\n theme,\n themedScrollpoints,\n onNoticeClose,\n}: MeganavProps) => {\n const [noticeHeight, setNoticeHeight] = React.useState(0);\n\n const finalNoticeHeight = notice ? noticeHeight : 0;\n\n const mobileNavItems = useMemo(\n () =>\n menuItemsForHeader\n .filter((item) => !item.isHiddenMobile)\n .map(({ name, link, content }) => ({ name, link, content })),\n [],\n );\n\n const defaultThemedScrollpoints = [\n {\n id: \"meganav\",\n className: \"ui-theme-light !bg-transparent !border-none\",\n },\n {\n id: \"meganav-theme-dark\",\n className: \"ui-theme-dark !bg-transparent !border-none\",\n },\n {\n id: \"main\",\n className: \"ui-theme-light bg-neutral-000 dark:bg-neutral-1300 border-b\",\n },\n {\n id: \"main-theme-dark\",\n className: \"ui-theme-dark bg-neutral-000 dark:bg-neutral-1300 border-b\",\n },\n ];\n\n useEffect(() => {\n if (!notice) {\n setNoticeHeight(0);\n return;\n }\n\n const noticeElement = document.querySelector('[data-id=\"ui-notice\"]');\n if (!noticeElement) return;\n\n const updateNoticeHeight = () => {\n setNoticeHeight(noticeElement.getBoundingClientRect().height);\n };\n\n const observer = new ResizeObserver(updateNoticeHeight);\n observer.observe(noticeElement);\n\n const timeoutId = setTimeout(updateNoticeHeight, 0);\n window.addEventListener(\"resize\", updateNoticeHeight);\n\n return () => {\n clearTimeout(timeoutId);\n observer.disconnect();\n window.removeEventListener(\"resize\", updateNoticeHeight);\n };\n }, [notice]);\n\n return (\n <>\n <div\n className=\"absolute inset-0 w-full z-50\"\n id={theme === \"dark\" ? \"meganav-theme-dark\" : \"meganav\"}\n data-testid=\"meganav\"\n style={{ height: HEADER_HEIGHT + finalNoticeHeight }}\n >\n {notice && (\n <Notice\n {...notice.props}\n config={notice.config}\n onClose={onNoticeClose}\n />\n )}\n <Header\n className=\"max-w-screen-xl mx-auto px-0 sm:px-8 md:px-10 lg:px-16\"\n isNoticeBannerEnabled={!!notice}\n noticeHeight={finalNoticeHeight}\n nav={\n <Flyout\n menuItems={menuItemsForHeader}\n className=\"justify-left z-40\"\n flyOutClassName=\"flex justify-left\"\n viewPortClassName=\"ui-shadow-lg-medium border border-neutral-200 dark:border-neutral-1100 rounded-2xl -mt-1 bg-neutral-000 dark:bg-neutral-1300\"\n />\n }\n mobileNav={<MeganavMobile navItems={mobileNavItems} />}\n headerLinks={[{ href: \"/contact\", label: \"Contact us\" }]}\n headerLinksClassName=\"md:gap-x-6 \"\n sessionState={sessionState}\n themedScrollpoints={themedScrollpoints ?? defaultThemedScrollpoints}\n />\n </div>\n </>\n );\n};\n\nexport default Meganav;\n"],"names":["React","useEffect","useMemo","Header","Flyout","menuItemsForHeader","MeganavMobile","Notice","HEADER_HEIGHT","Meganav","sessionState","notice","theme","themedScrollpoints","onNoticeClose","noticeHeight","setNoticeHeight","useState","finalNoticeHeight","mobileNavItems","filter","item","isHiddenMobile","map","name","link","content","defaultThemedScrollpoints","id","className","noticeElement","document","querySelector","updateNoticeHeight","getBoundingClientRect","height","observer","ResizeObserver","observe","timeoutId","setTimeout","window","addEventListener","clearTimeout","disconnect","removeEventListener","div","data-testid","style","props","config","onClose","isNoticeBannerEnabled","nav","menuItems","flyOutClassName","viewPortClassName","mobileNav","navItems","headerLinks","href","label","headerLinksClassName"],"mappings":"AAAA,OAAOA,OAASC,SAAS,CAAEC,OAAO,KAAQ,OAAQ,AAClD,QAAOC,WAAuD,UAAW,AACzE,QAAOC,WAAY,UAAW,AAC9B,QAASC,kBAAkB,KAAQ,gBAAiB,AACpD,QAASC,aAAa,KAAQ,yBAA0B,AACxD,QAAOC,WAAY,UAAW,AAC9B,QAASC,aAAa,KAAQ,iBAAkB,CA2BhD,MAAMC,QAAU,CAAC,CACfC,YAAY,CACZC,MAAM,CACNC,KAAK,CACLC,kBAAkB,CAClBC,aAAa,CACA,IACb,KAAM,CAACC,aAAcC,gBAAgB,CAAGhB,MAAMiB,QAAQ,CAAC,GAEvD,MAAMC,kBAAoBP,OAASI,aAAe,EAElD,MAAMI,eAAiBjB,QACrB,IACEG,mBACGe,MAAM,CAAC,AAACC,MAAS,CAACA,KAAKC,cAAc,EACrCC,GAAG,CAAC,CAAC,CAAEC,IAAI,CAAEC,IAAI,CAAEC,OAAO,CAAE,GAAM,CAAA,CAAEF,KAAMC,KAAMC,OAAQ,CAAA,GAC7D,EAAE,EAGJ,MAAMC,0BAA4B,CAChC,CACEC,GAAI,UACJC,UAAW,6CACb,EACA,CACED,GAAI,qBACJC,UAAW,4CACb,EACA,CACED,GAAI,OACJC,UAAW,6DACb,EACA,CACED,GAAI,kBACJC,UAAW,4DACb,EACD,CAED5B,UAAU,KACR,GAAI,CAACU,OAAQ,CACXK,gBAAgB,GAChB,MACF,CAEA,MAAMc,cAAgBC,SAASC,aAAa,CAAC,yBAC7C,GAAI,CAACF,cAAe,OAEpB,MAAMG,mBAAqB,KACzBjB,gBAAgBc,cAAcI,qBAAqB,GAAGC,MAAM,CAC9D,EAEA,MAAMC,SAAW,IAAIC,eAAeJ,oBACpCG,SAASE,OAAO,CAACR,eAEjB,MAAMS,UAAYC,WAAWP,mBAAoB,GACjDQ,OAAOC,gBAAgB,CAAC,SAAUT,oBAElC,MAAO,KACLU,aAAaJ,WACbH,SAASQ,UAAU,GACnBH,OAAOI,mBAAmB,CAAC,SAAUZ,mBACvC,CACF,EAAG,CAACtB,OAAO,EAEX,OACE,wCACE,oBAACmC,OACCjB,UAAU,+BACVD,GAAIhB,QAAU,OAAS,qBAAuB,UAC9CmC,cAAY,UACZC,MAAO,CAAEb,OAAQ3B,cAAgBU,iBAAkB,GAElDP,QACC,oBAACJ,QACE,GAAGI,OAAOsC,KAAK,CAChBC,OAAQvC,OAAOuC,MAAM,CACrBC,QAASrC,gBAGb,oBAACX,QACC0B,UAAU,yDACVuB,sBAAuB,CAAC,CAACzC,OACzBI,aAAcG,kBACdmC,IACE,oBAACjD,QACCkD,UAAWjD,mBACXwB,UAAU,oBACV0B,gBAAgB,oBAChBC,kBAAkB,iIAGtBC,UAAW,oBAACnD,eAAcoD,SAAUvC,iBACpCwC,YAAa,CAAC,CAAEC,KAAM,WAAYC,MAAO,YAAa,EAAE,CACxDC,qBAAqB,cACrBpD,aAAcA,aACdG,mBAAoBA,oBAAsBc,6BAKpD,CAEA,gBAAelB,OAAQ"}
@@ -1,6 +1,6 @@
1
1
  @layer components {
2
2
  .ui-announcement {
3
- @apply font-sans transition-all duration-100 ease-in-out;
3
+ @apply font-sans transition-[max-height,transform,opacity] duration-300 ease-in-out;
4
4
  }
5
5
 
6
6
  .ui-announcement-visible {
@@ -1,2 +1,2 @@
1
- import Cookie from"js-cookie";import{throttle}from"es-toolkit/compat";import{queryId}from"../dom-query";import{FLASH_DATA_ID}from"../Flash";const COOKIE_EXPIRY=90;export const COLLAPSE_TRIGGER_DISTANCE=5;const SCROLL_LISTENER_THROTTLE=100;const RESIZE_LISTENER_THROTTLE=100;const isMdViewport=()=>!window.matchMedia(`(min-width: 65rem)`).matches;const adjustFlashMargin=open=>{const flash=queryId(FLASH_DATA_ID);if(flash){flash.style.marginTop=open?`4rem`:null}};const hideOnMobile=bannerContainer=>{if(isMdViewport()){bannerContainer.style.display="none"}else{bannerContainer.style.display=null}};const hideNotice=bannerContainer=>{bannerContainer.classList.remove("ui-announcement-visible");bannerContainer.classList.add("ui-announcement-hidden");adjustFlashMargin(false)};const showNotice=bannerContainer=>{bannerContainer.classList.remove("ui-announcement-hidden");bannerContainer.classList.add("ui-announcement-visible");adjustFlashMargin(true)};const setupRememberClosed=(cookieId,noticeId)=>{const cookie=Cookie.get(cookieId)||"";Cookie.set(cookieId,`${cookie.replace(`${noticeId},`,"")+noticeId},`,{expires:COOKIE_EXPIRY})};const hasBeenClosedBefore=(cookieId,noticeId)=>(Cookie.get(cookieId)||"").includes(noticeId);const setupNoticeCollapse=bannerContainer=>{const scrollTop=window.scrollY;if(scrollTop>COLLAPSE_TRIGGER_DISTANCE){hideNotice(bannerContainer)}const listener=throttle(()=>{const scrollTop=window.scrollY;if(scrollTop>COLLAPSE_TRIGGER_DISTANCE){hideNotice(bannerContainer)}else if(bannerContainer.classList.contains("ui-announcement-hidden")){showNotice(bannerContainer)}},SCROLL_LISTENER_THROTTLE);document.addEventListener("scroll",listener);return()=>document.removeEventListener("scroll",listener)};const setupCloseBtn=(bannerContainer,cookieId,noticeId,collapseUnmountListeners)=>{const closeBtn=bannerContainer.querySelector("button");if(!closeBtn)return()=>{};const listener=()=>{if(cookieId&&noticeId)setupRememberClosed(cookieId,noticeId);hideNotice(bannerContainer);collapseUnmountListeners()};closeBtn.addEventListener("click",listener);return()=>document.removeEventListener("click",listener)};const resizeHandler=bannerContainer=>{const handler=throttle(()=>{hideOnMobile(bannerContainer)},RESIZE_LISTENER_THROTTLE);window.addEventListener("resize",handler);return()=>window.removeEventListener("resize",handler)};const Notice=({bannerContainer,cookieId,noticeId,options})=>{if(typeof window==="undefined")return()=>{};if(!bannerContainer){console.warn("A Notice component was initited but no notice container was found.");return()=>{}}if(hasBeenClosedBefore(cookieId,noticeId))return()=>{};hideOnMobile(bannerContainer);showNotice(bannerContainer);const opts={collapse:true,...options};const collapseUnmountListeners=opts.collapse?setupNoticeCollapse(bannerContainer):()=>{};const closeBtnUnmountListeners=setupCloseBtn(bannerContainer,cookieId,noticeId,collapseUnmountListeners);const resizeUnmountListener=resizeHandler(bannerContainer);return()=>{[closeBtnUnmountListeners,collapseUnmountListeners,resizeUnmountListener].forEach(unmount=>unmount())}};export default Notice;
1
+ import Cookie from"js-cookie";import{throttle}from"es-toolkit/compat";import{queryId}from"../dom-query";import{FLASH_DATA_ID}from"../Flash";const COOKIE_EXPIRY=90;export const COLLAPSE_TRIGGER_DISTANCE=5;const SCROLL_LISTENER_THROTTLE=100;const RESIZE_LISTENER_THROTTLE=100;const isMdViewport=()=>!window.matchMedia(`(min-width: 65rem)`).matches;const adjustFlashMargin=open=>{const flash=queryId(FLASH_DATA_ID);if(flash){flash.style.marginTop=open?`4rem`:null}};const hideOnMobile=bannerContainer=>{if(isMdViewport()){bannerContainer.style.display="none"}else{bannerContainer.style.display=null}};const hideNotice=bannerContainer=>{bannerContainer.classList.remove("ui-announcement-visible");bannerContainer.classList.add("ui-announcement-hidden");adjustFlashMargin(false)};const showNotice=bannerContainer=>{bannerContainer.classList.remove("ui-announcement-hidden");bannerContainer.classList.add("ui-announcement-visible");adjustFlashMargin(true)};const setupRememberClosed=(cookieId,noticeId)=>{const cookie=Cookie.get(cookieId)||"";Cookie.set(cookieId,`${cookie.replace(`${noticeId},`,"")+noticeId},`,{expires:COOKIE_EXPIRY})};const hasBeenClosedBefore=(cookieId,noticeId)=>(Cookie.get(cookieId)||"").includes(noticeId);const setupNoticeCollapse=bannerContainer=>{const scrollTop=window.scrollY;if(scrollTop>COLLAPSE_TRIGGER_DISTANCE){hideNotice(bannerContainer)}const listener=throttle(()=>{const scrollTop=window.scrollY;if(scrollTop>COLLAPSE_TRIGGER_DISTANCE){hideNotice(bannerContainer)}else if(bannerContainer.classList.contains("ui-announcement-hidden")){showNotice(bannerContainer)}},SCROLL_LISTENER_THROTTLE);document.addEventListener("scroll",listener);return()=>document.removeEventListener("scroll",listener)};const setupCloseBtn=(bannerContainer,cookieId,noticeId,collapseUnmountListeners)=>{const closeBtn=bannerContainer.querySelector("button");if(!closeBtn)return()=>{};const listener=()=>{if(cookieId&&noticeId)setupRememberClosed(cookieId,noticeId);hideNotice(bannerContainer);collapseUnmountListeners()};closeBtn.addEventListener("click",listener);return()=>closeBtn.removeEventListener("click",listener)};const resizeHandler=bannerContainer=>{const handler=throttle(()=>{hideOnMobile(bannerContainer)},RESIZE_LISTENER_THROTTLE);window.addEventListener("resize",handler);return()=>window.removeEventListener("resize",handler)};const Notice=({bannerContainer,cookieId,noticeId,options})=>{if(typeof window==="undefined")return()=>{};if(!bannerContainer){console.warn("A Notice component was initited but no notice container was found.");return()=>{}}if(hasBeenClosedBefore(cookieId,noticeId))return()=>{};hideOnMobile(bannerContainer);showNotice(bannerContainer);const opts={collapse:true,...options};const collapseUnmountListeners=opts.collapse?setupNoticeCollapse(bannerContainer):()=>{};const closeBtnUnmountListeners=setupCloseBtn(bannerContainer,cookieId,noticeId,collapseUnmountListeners);const resizeUnmountListener=resizeHandler(bannerContainer);return()=>{[closeBtnUnmountListeners,collapseUnmountListeners,resizeUnmountListener].forEach(unmount=>unmount())}};export default Notice;
2
2
  //# sourceMappingURL=component.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/Notice/component.js"],"sourcesContent":["import Cookie from \"js-cookie\";\nimport { throttle } from \"es-toolkit/compat\";\n\nimport { queryId } from \"../dom-query\";\nimport { FLASH_DATA_ID } from \"../Flash\";\n\nconst COOKIE_EXPIRY = 90;\nexport const COLLAPSE_TRIGGER_DISTANCE = 5;\nconst SCROLL_LISTENER_THROTTLE = 100;\nconst RESIZE_LISTENER_THROTTLE = 100;\n\nconst isMdViewport = () => !window.matchMedia(`(min-width: 65rem)`).matches;\n\nconst adjustFlashMargin = (open) => {\n // HACK ALERT\n // Add margin to flashes when opening the notice.\n // Flashes are react components and this notice needs to work as a view-component and react component.\n // We could do this with redux but then we potentially update state on every scroll event, which\n // even with debounce will deplate our frame budget.\n\n const flash = queryId(FLASH_DATA_ID);\n\n if (flash) {\n flash.style.marginTop = open ? `4rem` : null;\n }\n};\n\nconst hideOnMobile = (bannerContainer) => {\n if (isMdViewport()) {\n bannerContainer.style.display = \"none\";\n } else {\n bannerContainer.style.display = null;\n }\n};\n\nconst hideNotice = (bannerContainer) => {\n bannerContainer.classList.remove(\"ui-announcement-visible\");\n bannerContainer.classList.add(\"ui-announcement-hidden\");\n\n adjustFlashMargin(false);\n};\n\nconst showNotice = (bannerContainer) => {\n bannerContainer.classList.remove(\"ui-announcement-hidden\");\n bannerContainer.classList.add(\"ui-announcement-visible\");\n\n adjustFlashMargin(true);\n};\n\nconst setupRememberClosed = (cookieId, noticeId) => {\n const cookie = Cookie.get(cookieId) || \"\";\n\n Cookie.set(cookieId, `${cookie.replace(`${noticeId},`, \"\") + noticeId},`, {\n expires: COOKIE_EXPIRY,\n });\n};\n\nconst hasBeenClosedBefore = (cookieId, noticeId) =>\n (Cookie.get(cookieId) || \"\").includes(noticeId);\n\nconst setupNoticeCollapse = (bannerContainer) => {\n const scrollTop = window.scrollY;\n\n if (scrollTop > COLLAPSE_TRIGGER_DISTANCE) {\n hideNotice(bannerContainer);\n }\n\n const listener = throttle(() => {\n const scrollTop = window.scrollY;\n\n if (scrollTop > COLLAPSE_TRIGGER_DISTANCE) {\n hideNotice(bannerContainer);\n } else if (bannerContainer.classList.contains(\"ui-announcement-hidden\")) {\n showNotice(bannerContainer);\n }\n }, SCROLL_LISTENER_THROTTLE);\n\n document.addEventListener(\"scroll\", listener);\n\n return () => document.removeEventListener(\"scroll\", listener);\n};\n\nconst setupCloseBtn = (\n bannerContainer,\n cookieId,\n noticeId,\n collapseUnmountListeners,\n) => {\n const closeBtn = bannerContainer.querySelector(\"button\");\n\n if (!closeBtn) return () => {};\n\n const listener = () => {\n if (cookieId && noticeId) setupRememberClosed(cookieId, noticeId);\n\n hideNotice(bannerContainer);\n collapseUnmountListeners();\n };\n\n closeBtn.addEventListener(\"click\", listener);\n\n return () => document.removeEventListener(\"click\", listener);\n};\n\nconst resizeHandler = (bannerContainer) => {\n const handler = throttle(() => {\n hideOnMobile(bannerContainer);\n }, RESIZE_LISTENER_THROTTLE);\n\n window.addEventListener(\"resize\", handler);\n\n return () => window.removeEventListener(\"resize\", handler);\n};\n\nconst Notice = ({ bannerContainer, cookieId, noticeId, options }) => {\n if (typeof window === \"undefined\") return () => {};\n\n if (!bannerContainer) {\n console.warn(\n \"A Notice component was initited but no notice container was found.\",\n );\n return () => {};\n }\n\n if (hasBeenClosedBefore(cookieId, noticeId)) return () => {};\n\n hideOnMobile(bannerContainer);\n showNotice(bannerContainer);\n\n const opts = { collapse: true, ...options };\n\n const collapseUnmountListeners = opts.collapse\n ? setupNoticeCollapse(bannerContainer)\n : () => {};\n\n const closeBtnUnmountListeners = setupCloseBtn(\n bannerContainer,\n cookieId,\n noticeId,\n collapseUnmountListeners,\n );\n\n const resizeUnmountListener = resizeHandler(bannerContainer);\n\n return () => {\n [\n closeBtnUnmountListeners,\n collapseUnmountListeners,\n resizeUnmountListener,\n ].forEach((unmount) => unmount());\n };\n};\n\nexport default Notice;\n"],"names":["Cookie","throttle","queryId","FLASH_DATA_ID","COOKIE_EXPIRY","COLLAPSE_TRIGGER_DISTANCE","SCROLL_LISTENER_THROTTLE","RESIZE_LISTENER_THROTTLE","isMdViewport","window","matchMedia","matches","adjustFlashMargin","open","flash","style","marginTop","hideOnMobile","bannerContainer","display","hideNotice","classList","remove","add","showNotice","setupRememberClosed","cookieId","noticeId","cookie","get","set","replace","expires","hasBeenClosedBefore","includes","setupNoticeCollapse","scrollTop","scrollY","listener","contains","document","addEventListener","removeEventListener","setupCloseBtn","collapseUnmountListeners","closeBtn","querySelector","resizeHandler","handler","Notice","options","console","warn","opts","collapse","closeBtnUnmountListeners","resizeUnmountListener","forEach","unmount"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/core/Notice/component.js"],"sourcesContent":["import Cookie from \"js-cookie\";\nimport { throttle } from \"es-toolkit/compat\";\n\nimport { queryId } from \"../dom-query\";\nimport { FLASH_DATA_ID } from \"../Flash\";\n\nconst COOKIE_EXPIRY = 90;\nexport const COLLAPSE_TRIGGER_DISTANCE = 5;\nconst SCROLL_LISTENER_THROTTLE = 100;\nconst RESIZE_LISTENER_THROTTLE = 100;\n\nconst isMdViewport = () => !window.matchMedia(`(min-width: 65rem)`).matches;\n\nconst adjustFlashMargin = (open) => {\n // HACK ALERT\n // Add margin to flashes when opening the notice.\n // Flashes are react components and this notice needs to work as a view-component and react component.\n // We could do this with redux but then we potentially update state on every scroll event, which\n // even with debounce will deplate our frame budget.\n\n const flash = queryId(FLASH_DATA_ID);\n\n if (flash) {\n flash.style.marginTop = open ? `4rem` : null;\n }\n};\n\nconst hideOnMobile = (bannerContainer) => {\n if (isMdViewport()) {\n bannerContainer.style.display = \"none\";\n } else {\n bannerContainer.style.display = null;\n }\n};\n\nconst hideNotice = (bannerContainer) => {\n bannerContainer.classList.remove(\"ui-announcement-visible\");\n bannerContainer.classList.add(\"ui-announcement-hidden\");\n\n adjustFlashMargin(false);\n};\n\nconst showNotice = (bannerContainer) => {\n bannerContainer.classList.remove(\"ui-announcement-hidden\");\n bannerContainer.classList.add(\"ui-announcement-visible\");\n\n adjustFlashMargin(true);\n};\n\nconst setupRememberClosed = (cookieId, noticeId) => {\n const cookie = Cookie.get(cookieId) || \"\";\n\n Cookie.set(cookieId, `${cookie.replace(`${noticeId},`, \"\") + noticeId},`, {\n expires: COOKIE_EXPIRY,\n });\n};\n\nconst hasBeenClosedBefore = (cookieId, noticeId) =>\n (Cookie.get(cookieId) || \"\").includes(noticeId);\n\nconst setupNoticeCollapse = (bannerContainer) => {\n const scrollTop = window.scrollY;\n\n if (scrollTop > COLLAPSE_TRIGGER_DISTANCE) {\n hideNotice(bannerContainer);\n }\n\n const listener = throttle(() => {\n const scrollTop = window.scrollY;\n\n if (scrollTop > COLLAPSE_TRIGGER_DISTANCE) {\n hideNotice(bannerContainer);\n } else if (bannerContainer.classList.contains(\"ui-announcement-hidden\")) {\n showNotice(bannerContainer);\n }\n }, SCROLL_LISTENER_THROTTLE);\n\n document.addEventListener(\"scroll\", listener);\n\n return () => document.removeEventListener(\"scroll\", listener);\n};\n\nconst setupCloseBtn = (\n bannerContainer,\n cookieId,\n noticeId,\n collapseUnmountListeners,\n) => {\n const closeBtn = bannerContainer.querySelector(\"button\");\n\n if (!closeBtn) return () => {};\n\n const listener = () => {\n if (cookieId && noticeId) setupRememberClosed(cookieId, noticeId);\n\n hideNotice(bannerContainer);\n collapseUnmountListeners();\n };\n\n closeBtn.addEventListener(\"click\", listener);\n\n return () => closeBtn.removeEventListener(\"click\", listener);\n};\n\nconst resizeHandler = (bannerContainer) => {\n const handler = throttle(() => {\n hideOnMobile(bannerContainer);\n }, RESIZE_LISTENER_THROTTLE);\n\n window.addEventListener(\"resize\", handler);\n\n return () => window.removeEventListener(\"resize\", handler);\n};\n\nconst Notice = ({ bannerContainer, cookieId, noticeId, options }) => {\n if (typeof window === \"undefined\") return () => {};\n\n if (!bannerContainer) {\n console.warn(\n \"A Notice component was initited but no notice container was found.\",\n );\n return () => {};\n }\n\n if (hasBeenClosedBefore(cookieId, noticeId)) return () => {};\n\n hideOnMobile(bannerContainer);\n showNotice(bannerContainer);\n\n const opts = { collapse: true, ...options };\n\n const collapseUnmountListeners = opts.collapse\n ? setupNoticeCollapse(bannerContainer)\n : () => {};\n\n const closeBtnUnmountListeners = setupCloseBtn(\n bannerContainer,\n cookieId,\n noticeId,\n collapseUnmountListeners,\n );\n\n const resizeUnmountListener = resizeHandler(bannerContainer);\n\n return () => {\n [\n closeBtnUnmountListeners,\n collapseUnmountListeners,\n resizeUnmountListener,\n ].forEach((unmount) => unmount());\n };\n};\n\nexport default Notice;\n"],"names":["Cookie","throttle","queryId","FLASH_DATA_ID","COOKIE_EXPIRY","COLLAPSE_TRIGGER_DISTANCE","SCROLL_LISTENER_THROTTLE","RESIZE_LISTENER_THROTTLE","isMdViewport","window","matchMedia","matches","adjustFlashMargin","open","flash","style","marginTop","hideOnMobile","bannerContainer","display","hideNotice","classList","remove","add","showNotice","setupRememberClosed","cookieId","noticeId","cookie","get","set","replace","expires","hasBeenClosedBefore","includes","setupNoticeCollapse","scrollTop","scrollY","listener","contains","document","addEventListener","removeEventListener","setupCloseBtn","collapseUnmountListeners","closeBtn","querySelector","resizeHandler","handler","Notice","options","console","warn","opts","collapse","closeBtnUnmountListeners","resizeUnmountListener","forEach","unmount"],"mappings":"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"}
package/core/Notice.js CHANGED
@@ -1,2 +1,2 @@
1
- import React,{useEffect,useRef}from"react";import DOMPurify from"dompurify";import Icon from"./Icon";import cn from"./utils/cn.js";import NoticeScripts from"./Notice/component.js";import useRailsUjsLinks from"./hooks/use-rails-ujs-hooks";const defaultTextColor="text-neutral-1300 dark:text-neutral-000";const contentWrapperClasses="w-full pr-2 ui-text-p4 self-center";const ContentWrapper=({buttonLink,textColor=defaultTextColor,children})=>buttonLink?React.createElement("a",{href:buttonLink,className:cn(contentWrapperClasses,textColor)},children):React.createElement("div",{className:cn(contentWrapperClasses,textColor)},children);const Notice=({buttonLink,buttonLabel,bodyText,title,config,closeBtn,bgColor="bg-orange-100 dark:bg-orange-1100",textColor=defaultTextColor,onClose})=>{const contentRef=useRef(null);useRailsUjsLinks(contentRef);useEffect(()=>{NoticeScripts({bannerContainer:document.querySelector('[data-id="ui-notice"]'),cookieId:config?.cookieId,noticeId:config?.noticeId,options:{collapse:config?.options?.collapse||false}})},[config?.cookieId,config?.noticeId,config?.options?.collapse]);const safeContent=DOMPurify.sanitize(bodyText??"",{ALLOWED_TAGS:["a"],ALLOWED_ATTR:["href","data-method"],ALLOWED_URI_REGEXP:/^\/[^/]/});return React.createElement("div",{className:cn("ui-announcement ui-announcement-visible relative z-[60]",bgColor,textColor),"data-id":"ui-notice"},React.createElement("div",{className:"ui-grid-px py-4 max-w-screen-xl mx-auto flex items-start"},React.createElement(ContentWrapper,{buttonLink:buttonLink??"#"},React.createElement("strong",{className:"font-bold whitespace-nowrap pr-1"},title),React.createElement("span",{ref:contentRef,className:"pr-1",dangerouslySetInnerHTML:{__html:safeContent}}),buttonLabel&&React.createElement("span",{className:"cursor-pointer whitespace-nowrap text-gui-blue-default-light dark:text-gui-blue-default-dark"},buttonLabel)),closeBtn&&React.createElement("button",{type:"button",className:"ml-auto h-5 w-5 border-none bg-none self-baseline",onClick:()=>{document.dispatchEvent(new CustomEvent("notice-closed"));onClose?.()}},React.createElement(Icon,{name:"icon-gui-x-mark-outline",size:"1.25rem",color:textColor}))))};export default Notice;
1
+ import React,{useEffect,useRef,useState}from"react";import DOMPurify from"dompurify";import Icon from"./Icon";import cn from"./utils/cn.js";import NoticeScripts from"./Notice/component.js";import useRailsUjsLinks from"./hooks/use-rails-ujs-hooks";const defaultTextColor="text-neutral-1300 dark:text-neutral-000";const contentWrapperClasses="w-full pr-2 ui-text-p4 self-center";const ContentWrapper=({buttonLink,textColor=defaultTextColor,children})=>buttonLink?React.createElement("a",{href:buttonLink,className:cn(contentWrapperClasses,textColor)},children):React.createElement("div",{className:cn(contentWrapperClasses,textColor)},children);const Notice=({buttonLink,buttonLabel,bodyText,title,config,closeBtn,bgColor="bg-orange-100 dark:bg-orange-1100",textColor=defaultTextColor,onClose})=>{const contentRef=useRef(null);const[isClosing,setIsClosing]=useState(false);useRailsUjsLinks(contentRef);useEffect(()=>{const cleanup=NoticeScripts({bannerContainer:document.querySelector('[data-id="ui-notice"]'),cookieId:config?.cookieId,noticeId:config?.noticeId,options:{collapse:config?.options?.collapse||false}});return cleanup},[config?.cookieId,config?.noticeId,config?.options?.collapse]);const safeContent=DOMPurify.sanitize(bodyText??"",{ALLOWED_TAGS:["a"],ALLOWED_ATTR:["href","data-method"],ALLOWED_URI_REGEXP:/^\/[^/]/});return React.createElement("div",{className:cn("ui-announcement relative z-[60]",isClosing?"ui-announcement-hidden max-h-0 -translate-y-full opacity-0 overflow-hidden":"ui-announcement-visible",bgColor,textColor),"data-id":"ui-notice"},React.createElement("div",{className:"ui-grid-px py-4 max-w-screen-xl mx-auto flex items-start"},React.createElement(ContentWrapper,{buttonLink:buttonLink??"#"},React.createElement("strong",{className:"font-bold whitespace-nowrap pr-1"},title),React.createElement("span",{ref:contentRef,className:"pr-1",dangerouslySetInnerHTML:{__html:safeContent}}),buttonLabel&&React.createElement("span",{className:"cursor-pointer whitespace-nowrap text-gui-blue-default-light dark:text-gui-blue-default-dark"},buttonLabel)),closeBtn&&React.createElement("button",{type:"button",className:"ml-auto h-5 w-5 border-none bg-none self-baseline outline-none focus:outline-none focus:ring-0 focus:border-transparent",onClick:()=>{setIsClosing(true);setTimeout(()=>{document.dispatchEvent(new CustomEvent("notice-closed"));onClose?.()},300)}},React.createElement(Icon,{name:"icon-gui-x-mark-outline",size:"1.25rem",color:textColor}))))};export default Notice;
2
2
  //# sourceMappingURL=Notice.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/Notice.tsx"],"sourcesContent":["import React, { ReactNode, useEffect, useRef } from \"react\";\nimport DOMPurify from \"dompurify\";\n\nimport { ColorClass, ColorThemeSet } from \"./styles/colors/types\";\nimport Icon from \"./Icon\";\nimport cn from \"./utils/cn.js\";\nimport NoticeScripts from \"./Notice/component.js\";\nimport useRailsUjsLinks from \"./hooks/use-rails-ujs-hooks\";\n\ntype ContentWrapperProps = {\n buttonLink: string;\n children: ReactNode;\n textColor?: ColorClass | ColorThemeSet;\n};\n\n// TODO(jamiehenson):\n// This type is a bit messed up currently due to the NoticeScripts import being interpreted as NoticeProps.\n// Plan is to TS-ify the JS assets too, so this can be rectified then. The NoticeScripts-oriented props are\n// the ones after the line break.\nexport type NoticeProps = {\n buttonLink?: string;\n buttonLabel?: string;\n bodyText?: string;\n title?: string;\n closeBtn?: boolean;\n config?: {\n options: {\n collapse: boolean;\n };\n noticeId: string | number;\n cookieId: string;\n };\n bgColor?: string;\n textColor?: ColorClass | ColorThemeSet;\n onClose?: () => void;\n\n bannerContainer?: Element | null;\n cookieId?: string;\n noticeId?: string;\n options?: { collapse: boolean };\n};\n\nconst defaultTextColor = \"text-neutral-1300 dark:text-neutral-000\";\n\nconst contentWrapperClasses = \"w-full pr-2 ui-text-p4 self-center\";\n\nconst ContentWrapper = ({\n buttonLink,\n textColor = defaultTextColor,\n children,\n}: ContentWrapperProps) =>\n buttonLink ? (\n <a href={buttonLink} className={cn(contentWrapperClasses, textColor)}>\n {children}\n </a>\n ) : (\n <div className={cn(contentWrapperClasses, textColor)}>{children}</div>\n );\n\nconst Notice = ({\n buttonLink,\n buttonLabel,\n bodyText,\n title,\n config,\n closeBtn,\n bgColor = \"bg-orange-100 dark:bg-orange-1100\",\n textColor = defaultTextColor,\n onClose,\n}: NoticeProps) => {\n const contentRef = useRef<HTMLSpanElement>(null);\n useRailsUjsLinks(contentRef);\n\n useEffect(() => {\n NoticeScripts({\n bannerContainer: document.querySelector('[data-id=\"ui-notice\"]'),\n cookieId: config?.cookieId,\n noticeId: config?.noticeId,\n options: {\n collapse: config?.options?.collapse || false,\n },\n });\n }, [config?.cookieId, config?.noticeId, config?.options?.collapse]);\n\n const safeContent = DOMPurify.sanitize(bodyText ?? \"\", {\n ALLOWED_TAGS: [\"a\"],\n ALLOWED_ATTR: [\"href\", \"data-method\"],\n ALLOWED_URI_REGEXP: /^\\/[^/]/,\n });\n\n return (\n <div\n className={cn(\n \"ui-announcement ui-announcement-visible relative z-[60]\",\n bgColor,\n textColor,\n )}\n data-id=\"ui-notice\"\n >\n <div className=\"ui-grid-px py-4 max-w-screen-xl mx-auto flex items-start\">\n <ContentWrapper buttonLink={buttonLink ?? \"#\"}>\n <strong className=\"font-bold whitespace-nowrap pr-1\">{title}</strong>\n <span\n ref={contentRef}\n className=\"pr-1\"\n dangerouslySetInnerHTML={{\n __html: safeContent,\n }}\n ></span>\n {buttonLabel && (\n <span className=\"cursor-pointer whitespace-nowrap text-gui-blue-default-light dark:text-gui-blue-default-dark\">\n {buttonLabel}\n </span>\n )}\n </ContentWrapper>\n\n {closeBtn && (\n <button\n type=\"button\"\n className=\"ml-auto h-5 w-5 border-none bg-none self-baseline\"\n onClick={() => {\n document.dispatchEvent(new CustomEvent(\"notice-closed\"));\n onClose?.();\n }}\n >\n <Icon\n name=\"icon-gui-x-mark-outline\"\n size=\"1.25rem\"\n color={textColor}\n />\n </button>\n )}\n </div>\n </div>\n );\n};\n\nexport default Notice;\n"],"names":["React","useEffect","useRef","DOMPurify","Icon","cn","NoticeScripts","useRailsUjsLinks","defaultTextColor","contentWrapperClasses","ContentWrapper","buttonLink","textColor","children","a","href","className","div","Notice","buttonLabel","bodyText","title","config","closeBtn","bgColor","onClose","contentRef","bannerContainer","document","querySelector","cookieId","noticeId","options","collapse","safeContent","sanitize","ALLOWED_TAGS","ALLOWED_ATTR","ALLOWED_URI_REGEXP","data-id","strong","span","ref","dangerouslySetInnerHTML","__html","button","type","onClick","dispatchEvent","CustomEvent","name","size","color"],"mappings":"AAAA,OAAOA,OAAoBC,SAAS,CAAEC,MAAM,KAAQ,OAAQ,AAC5D,QAAOC,cAAe,WAAY,AAGlC,QAAOC,SAAU,QAAS,AAC1B,QAAOC,OAAQ,eAAgB,AAC/B,QAAOC,kBAAmB,uBAAwB,AAClD,QAAOC,qBAAsB,6BAA8B,CAmC3D,MAAMC,iBAAmB,0CAEzB,MAAMC,sBAAwB,qCAE9B,MAAMC,eAAiB,CAAC,CACtBC,UAAU,CACVC,UAAYJ,gBAAgB,CAC5BK,QAAQ,CACY,GACpBF,WACE,oBAACG,KAAEC,KAAMJ,WAAYK,UAAWX,GAAGI,sBAAuBG,YACvDC,UAGH,oBAACI,OAAID,UAAWX,GAAGI,sBAAuBG,YAAaC,UAG3D,MAAMK,OAAS,CAAC,CACdP,UAAU,CACVQ,WAAW,CACXC,QAAQ,CACRC,KAAK,CACLC,MAAM,CACNC,QAAQ,CACRC,QAAU,mCAAmC,CAC7CZ,UAAYJ,gBAAgB,CAC5BiB,OAAO,CACK,IACZ,MAAMC,WAAaxB,OAAwB,MAC3CK,iBAAiBmB,YAEjBzB,UAAU,KACRK,cAAc,CACZqB,gBAAiBC,SAASC,aAAa,CAAC,yBACxCC,SAAUR,QAAQQ,SAClBC,SAAUT,QAAQS,SAClBC,QAAS,CACPC,SAAUX,QAAQU,SAASC,UAAY,KACzC,CACF,EACF,EAAG,CAACX,QAAQQ,SAAUR,QAAQS,SAAUT,QAAQU,SAASC,SAAS,EAElE,MAAMC,YAAc/B,UAAUgC,QAAQ,CAACf,UAAY,GAAI,CACrDgB,aAAc,CAAC,IAAI,CACnBC,aAAc,CAAC,OAAQ,cAAc,CACrCC,mBAAoB,SACtB,GAEA,OACE,oBAACrB,OACCD,UAAWX,GACT,0DACAmB,QACAZ,WAEF2B,UAAQ,aAER,oBAACtB,OAAID,UAAU,4DACb,oBAACN,gBAAeC,WAAYA,YAAc,KACxC,oBAAC6B,UAAOxB,UAAU,oCAAoCK,OACtD,oBAACoB,QACCC,IAAKhB,WACLV,UAAU,OACV2B,wBAAyB,CACvBC,OAAQV,WACV,IAEDf,aACC,oBAACsB,QAAKzB,UAAU,gGACbG,cAKNI,UACC,oBAACsB,UACCC,KAAK,SACL9B,UAAU,oDACV+B,QAAS,KACPnB,SAASoB,aAAa,CAAC,IAAIC,YAAY,kBACvCxB,WACF,GAEA,oBAACrB,MACC8C,KAAK,0BACLC,KAAK,UACLC,MAAOxC,cAOrB,CAEA,gBAAeM,MAAO"}
1
+ {"version":3,"sources":["../../src/core/Notice.tsx"],"sourcesContent":["import React, { ReactNode, useEffect, useRef, useState } from \"react\";\nimport DOMPurify from \"dompurify\";\n\nimport { ColorClass, ColorThemeSet } from \"./styles/colors/types\";\nimport Icon from \"./Icon\";\nimport cn from \"./utils/cn.js\";\nimport NoticeScripts from \"./Notice/component.js\";\nimport useRailsUjsLinks from \"./hooks/use-rails-ujs-hooks\";\n\ntype ContentWrapperProps = {\n buttonLink: string;\n children: ReactNode;\n textColor?: ColorClass | ColorThemeSet;\n};\n\n// TODO(jamiehenson):\n// This type is a bit messed up currently due to the NoticeScripts import being interpreted as NoticeProps.\n// Plan is to TS-ify the JS assets too, so this can be rectified then. The NoticeScripts-oriented props are\n// the ones after the line break.\nexport type NoticeProps = {\n buttonLink?: string;\n buttonLabel?: string;\n bodyText?: string;\n title?: string;\n closeBtn?: boolean;\n config?: {\n options: {\n collapse: boolean;\n };\n noticeId: string | number;\n cookieId: string;\n };\n bgColor?: string;\n textColor?: ColorClass | ColorThemeSet;\n onClose?: () => void;\n\n bannerContainer?: Element | null;\n cookieId?: string;\n noticeId?: string;\n options?: { collapse: boolean };\n};\n\nconst defaultTextColor = \"text-neutral-1300 dark:text-neutral-000\";\n\nconst contentWrapperClasses = \"w-full pr-2 ui-text-p4 self-center\";\n\nconst ContentWrapper = ({\n buttonLink,\n textColor = defaultTextColor,\n children,\n}: ContentWrapperProps) =>\n buttonLink ? (\n <a href={buttonLink} className={cn(contentWrapperClasses, textColor)}>\n {children}\n </a>\n ) : (\n <div className={cn(contentWrapperClasses, textColor)}>{children}</div>\n );\n\nconst Notice = ({\n buttonLink,\n buttonLabel,\n bodyText,\n title,\n config,\n closeBtn,\n bgColor = \"bg-orange-100 dark:bg-orange-1100\",\n textColor = defaultTextColor,\n onClose,\n}: NoticeProps) => {\n const contentRef = useRef<HTMLSpanElement>(null);\n const [isClosing, setIsClosing] = useState(false);\n useRailsUjsLinks(contentRef);\n\n useEffect(() => {\n const cleanup = NoticeScripts({\n bannerContainer: document.querySelector('[data-id=\"ui-notice\"]'),\n cookieId: config?.cookieId,\n noticeId: config?.noticeId,\n options: {\n collapse: config?.options?.collapse || false,\n },\n });\n\n return cleanup;\n }, [config?.cookieId, config?.noticeId, config?.options?.collapse]);\n\n const safeContent = DOMPurify.sanitize(bodyText ?? \"\", {\n ALLOWED_TAGS: [\"a\"],\n ALLOWED_ATTR: [\"href\", \"data-method\"],\n ALLOWED_URI_REGEXP: /^\\/[^/]/,\n });\n\n // have to add the style classes here as src/core/Notice/component.css is not being properly imported or distributed when ably-ui is used as a package.\n return (\n <div\n className={cn(\n \"ui-announcement relative z-[60]\",\n isClosing\n ? \"ui-announcement-hidden max-h-0 -translate-y-full opacity-0 overflow-hidden\"\n : \"ui-announcement-visible\",\n bgColor,\n textColor,\n )}\n data-id=\"ui-notice\"\n >\n <div className=\"ui-grid-px py-4 max-w-screen-xl mx-auto flex items-start\">\n <ContentWrapper buttonLink={buttonLink ?? \"#\"}>\n <strong className=\"font-bold whitespace-nowrap pr-1\">{title}</strong>\n <span\n ref={contentRef}\n className=\"pr-1\"\n dangerouslySetInnerHTML={{\n __html: safeContent,\n }}\n ></span>\n {buttonLabel && (\n <span className=\"cursor-pointer whitespace-nowrap text-gui-blue-default-light dark:text-gui-blue-default-dark\">\n {buttonLabel}\n </span>\n )}\n </ContentWrapper>\n\n {closeBtn && (\n <button\n type=\"button\"\n className=\"ml-auto h-5 w-5 border-none bg-none self-baseline outline-none focus:outline-none focus:ring-0 focus:border-transparent\"\n onClick={() => {\n setIsClosing(true);\n setTimeout(() => {\n document.dispatchEvent(new CustomEvent(\"notice-closed\"));\n onClose?.();\n }, 300);\n }}\n >\n <Icon\n name=\"icon-gui-x-mark-outline\"\n size=\"1.25rem\"\n color={textColor}\n />\n </button>\n )}\n </div>\n </div>\n );\n};\n\nexport default Notice;\n"],"names":["React","useEffect","useRef","useState","DOMPurify","Icon","cn","NoticeScripts","useRailsUjsLinks","defaultTextColor","contentWrapperClasses","ContentWrapper","buttonLink","textColor","children","a","href","className","div","Notice","buttonLabel","bodyText","title","config","closeBtn","bgColor","onClose","contentRef","isClosing","setIsClosing","cleanup","bannerContainer","document","querySelector","cookieId","noticeId","options","collapse","safeContent","sanitize","ALLOWED_TAGS","ALLOWED_ATTR","ALLOWED_URI_REGEXP","data-id","strong","span","ref","dangerouslySetInnerHTML","__html","button","type","onClick","setTimeout","dispatchEvent","CustomEvent","name","size","color"],"mappings":"AAAA,OAAOA,OAAoBC,SAAS,CAAEC,MAAM,CAAEC,QAAQ,KAAQ,OAAQ,AACtE,QAAOC,cAAe,WAAY,AAGlC,QAAOC,SAAU,QAAS,AAC1B,QAAOC,OAAQ,eAAgB,AAC/B,QAAOC,kBAAmB,uBAAwB,AAClD,QAAOC,qBAAsB,6BAA8B,CAmC3D,MAAMC,iBAAmB,0CAEzB,MAAMC,sBAAwB,qCAE9B,MAAMC,eAAiB,CAAC,CACtBC,UAAU,CACVC,UAAYJ,gBAAgB,CAC5BK,QAAQ,CACY,GACpBF,WACE,oBAACG,KAAEC,KAAMJ,WAAYK,UAAWX,GAAGI,sBAAuBG,YACvDC,UAGH,oBAACI,OAAID,UAAWX,GAAGI,sBAAuBG,YAAaC,UAG3D,MAAMK,OAAS,CAAC,CACdP,UAAU,CACVQ,WAAW,CACXC,QAAQ,CACRC,KAAK,CACLC,MAAM,CACNC,QAAQ,CACRC,QAAU,mCAAmC,CAC7CZ,UAAYJ,gBAAgB,CAC5BiB,OAAO,CACK,IACZ,MAAMC,WAAazB,OAAwB,MAC3C,KAAM,CAAC0B,UAAWC,aAAa,CAAG1B,SAAS,OAC3CK,iBAAiBmB,YAEjB1B,UAAU,KACR,MAAM6B,QAAUvB,cAAc,CAC5BwB,gBAAiBC,SAASC,aAAa,CAAC,yBACxCC,SAAUX,QAAQW,SAClBC,SAAUZ,QAAQY,SAClBC,QAAS,CACPC,SAAUd,QAAQa,SAASC,UAAY,KACzC,CACF,GAEA,OAAOP,OACT,EAAG,CAACP,QAAQW,SAAUX,QAAQY,SAAUZ,QAAQa,SAASC,SAAS,EAElE,MAAMC,YAAclC,UAAUmC,QAAQ,CAAClB,UAAY,GAAI,CACrDmB,aAAc,CAAC,IAAI,CACnBC,aAAc,CAAC,OAAQ,cAAc,CACrCC,mBAAoB,SACtB,GAGA,OACE,oBAACxB,OACCD,UAAWX,GACT,kCACAsB,UACI,6EACA,0BACJH,QACAZ,WAEF8B,UAAQ,aAER,oBAACzB,OAAID,UAAU,4DACb,oBAACN,gBAAeC,WAAYA,YAAc,KACxC,oBAACgC,UAAO3B,UAAU,oCAAoCK,OACtD,oBAACuB,QACCC,IAAKnB,WACLV,UAAU,OACV8B,wBAAyB,CACvBC,OAAQV,WACV,IAEDlB,aACC,oBAACyB,QAAK5B,UAAU,gGACbG,cAKNI,UACC,oBAACyB,UACCC,KAAK,SACLjC,UAAU,0HACVkC,QAAS,KACPtB,aAAa,MACbuB,WAAW,KACTpB,SAASqB,aAAa,CAAC,IAAIC,YAAY,kBACvC5B,WACF,EAAG,IACL,GAEA,oBAACrB,MACCkD,KAAK,0BACLC,KAAK,UACLC,MAAO5C,cAOrB,CAEA,gBAAeM,MAAO"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/remote-blogs-posts.js"],"sourcesContent":["/* global __ENABLE_FETCH_WITH_CREDENTIALS__ */\n\nimport { isJsonResponse } from \"./remote-data-util\";\n\nconst fetchBlogPosts = async (store, blogUrl) => {\n try {\n if (!blogUrl) {\n console.log(\n `Skipping fetching blog posts, invalid blogUrl: \"${blogUrl}\"`,\n );\n return;\n }\n\n const options = {\n headers: {\n accept: \"application/json\",\n },\n cache: \"no-cache\",\n };\n\n if (__ENABLE_FETCH_WITH_CREDENTIALS__) {\n options.credentials = \"include\";\n }\n\n const res = await fetch(blogUrl, options);\n\n if (isJsonResponse(res.headers.get(\"content-type\"))) {\n const payload = await res.json();\n store.dispatch({ type: \"blog/loaded\", payload });\n } else {\n throw new Error(\"Blog posts url is not serving json\");\n }\n } catch (e) {\n console.warn(\"Could not fetch blog posts due to error:\", e);\n }\n};\n\nconst initialState = { recent: null };\n\nconst REDUCER_KEY = \"blogPosts\";\n\nconst reducerBlogPosts = {\n [REDUCER_KEY]: (state = initialState, action) => {\n switch (action.type) {\n case \"blog/loaded\":\n return { ...state, recent: action.payload };\n default:\n return state;\n }\n },\n};\n\nconst selectRecentBlogPosts = (store) => store.getState()[REDUCER_KEY]?.recent;\n\nexport { fetchBlogPosts, reducerBlogPosts, selectRecentBlogPosts };\n"],"names":["isJsonResponse","fetchBlogPosts","store","blogUrl","console","log","options","headers","accept","cache","credentials","res","fetch","get","payload","json","dispatch","type","Error","e","warn","initialState","recent","REDUCER_KEY","reducerBlogPosts","state","action","selectRecentBlogPosts","getState"],"mappings":"AAEA,OAASA,cAAc,KAAQ,oBAAqB,CAEpD,MAAMC,eAAiB,MAAOC,MAAOC,WACnC,GAAI,CACF,GAAI,CAACA,QAAS,CACZC,QAAQC,GAAG,CACT,CAAC,gDAAgD,EAAEF,QAAQ,CAAC,CAAC,EAE/D,MACF,CAEA,MAAMG,QAAU,CACdC,QAAS,CACPC,OAAQ,kBACV,EACAC,MAAO,UACT,EAEA,SAAuC,CACrCH,QAAQI,WAAW,CAAG,SACxB,CAEA,MAAMC,IAAM,MAAMC,MAAMT,QAASG,SAEjC,GAAIN,eAAeW,IAAIJ,OAAO,CAACM,GAAG,CAAC,iBAAkB,CACnD,MAAMC,QAAU,MAAMH,IAAII,IAAI,GAC9Bb,MAAMc,QAAQ,CAAC,CAAEC,KAAM,cAAeH,OAAQ,EAChD,KAAO,CACL,MAAM,IAAII,MAAM,qCAClB,CACF,CAAE,MAAOC,EAAG,CACVf,QAAQgB,IAAI,CAAC,2CAA4CD,EAC3D,CACF,EAEA,MAAME,aAAe,CAAEC,OAAQ,IAAK,EAEpC,MAAMC,YAAc,YAEpB,MAAMC,iBAAmB,CACvB,CAACD,YAAY,CAAE,CAACE,MAAQJ,YAAY,CAAEK,UACpC,OAAQA,OAAOT,IAAI,EACjB,IAAK,cACH,MAAO,CAAE,GAAGQ,KAAK,CAAEH,OAAQI,OAAOZ,OAAO,AAAC,CAC5C,SACE,OAAOW,KACX,CACF,CACF,EAEA,MAAME,sBAAwB,AAACzB,OAAUA,MAAM0B,QAAQ,EAAE,CAACL,YAAY,EAAED,MAExE,QAASrB,cAAc,CAAEuB,gBAAgB,CAAEG,qBAAqB,CAAG"}
1
+ {"version":3,"sources":["../../src/core/remote-blogs-posts.js"],"sourcesContent":["/* global __ENABLE_FETCH_WITH_CREDENTIALS__ */\n\nimport { isJsonResponse } from \"./remote-data-util\";\n\nconst fetchBlogPosts = async (store, blogUrl) => {\n try {\n if (!blogUrl) {\n console.log(\n `Skipping fetching blog posts, invalid blogUrl: \"${blogUrl}\"`,\n );\n return;\n }\n\n const options = {\n headers: {\n accept: \"application/json\",\n },\n cache: \"no-cache\",\n };\n\n if (__ENABLE_FETCH_WITH_CREDENTIALS__) {\n options.credentials = \"include\";\n }\n\n const res = await fetch(blogUrl, options);\n\n if (isJsonResponse(res.headers.get(\"content-type\"))) {\n const payload = await res.json();\n store.dispatch({ type: \"blog/loaded\", payload });\n } else {\n throw new Error(\"Blog posts url is not serving json\");\n }\n } catch (e) {\n console.warn(\"Could not fetch blog posts due to error:\", e);\n }\n};\n\nconst initialState = { recent: null };\n\nconst REDUCER_KEY = \"blogPosts\";\n\nconst reducerBlogPosts = {\n [REDUCER_KEY]: (state = initialState, action) => {\n switch (action.type) {\n case \"blog/loaded\":\n return { ...state, recent: action.payload };\n default:\n return state;\n }\n },\n};\n\nconst selectRecentBlogPosts = (store) => store.getState()[REDUCER_KEY]?.recent;\n\nexport { fetchBlogPosts, reducerBlogPosts, selectRecentBlogPosts };\n"],"names":["isJsonResponse","fetchBlogPosts","store","blogUrl","console","log","options","headers","accept","cache","credentials","res","fetch","get","payload","json","dispatch","type","Error","e","warn","initialState","recent","REDUCER_KEY","reducerBlogPosts","state","action","selectRecentBlogPosts","getState"],"mappings":"AAEA,OAASA,cAAc,KAAQ,oBAAqB,CAEpD,MAAMC,eAAiB,MAAOC,MAAOC,WACnC,GAAI,CACF,GAAI,CAACA,QAAS,CACZC,QAAQC,GAAG,CACT,CAAC,gDAAgD,EAAEF,QAAQ,CAAC,CAAC,EAE/D,MACF,CAEA,MAAMG,QAAU,CACdC,QAAS,CACPC,OAAQ,kBACV,EACAC,MAAO,UACT,EAEA,GAWJ,MAX2C,CACrCH,QAAQI,WAAW,CAAG,SACxB,CAEA,MAAMC,IAAM,MAAMC,MAAMT,QAASG,SAEjC,GAAIN,eAAeW,IAAIJ,OAAO,CAACM,GAAG,CAAC,iBAAkB,CACnD,MAAMC,QAAU,MAAMH,IAAII,IAAI,GAC9Bb,MAAMc,QAAQ,CAAC,CAAEC,KAAM,cAAeH,OAAQ,EAChD,KAAO,CACL,MAAM,IAAII,MAAM,qCAClB,CACF,CAAE,MAAOC,EAAG,CACVf,QAAQgB,IAAI,CAAC,2CAA4CD,EAC3D,CACF,EAEA,MAAME,aAAe,CAAEC,OAAQ,IAAK,EAEpC,MAAMC,YAAc,YAEpB,MAAMC,iBAAmB,CACvB,CAACD,YAAY,CAAE,CAACE,MAAQJ,YAAY,CAAEK,UACpC,OAAQA,OAAOT,IAAI,EACjB,IAAK,cACH,MAAO,CAAE,GAAGQ,KAAK,CAAEH,OAAQI,OAAOZ,OAAO,AAAC,CAC5C,SACE,OAAOW,KACX,CACF,CACF,EAEA,MAAME,sBAAwB,AAACzB,OAAUA,MAAM0B,QAAQ,EAAE,CAACL,YAAY,EAAED,MAExE,QAASrB,cAAc,CAAEuB,gBAAgB,CAAEG,qBAAqB,CAAG"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/remote-session-data.js"],"sourcesContent":["/* global __ENABLE_FETCH_WITH_CREDENTIALS__ */\n\n// Fetches current users session data\n// Assumes an authenticated session, so will only work when used on ably.com/ably.io\n\nimport { isJsonResponse } from \"./remote-data-util\";\n\nconst NOT_FOUND_ERROR_CODE = \"not-found\";\n\nconst fetchSessionData = async (store, sessionUrl) => {\n const sessionLoaded = (payload = {}) =>\n store.dispatch({ type: \"session/loaded\", payload });\n\n try {\n if (!sessionUrl) {\n console.log(\n `Skipping fetching session, invalid sessionUrl: \"${sessionUrl}\"`,\n );\n sessionLoaded();\n return;\n }\n\n const options = {\n headers: {\n accept: \"application/json\",\n },\n cache: \"no-cache\",\n };\n\n if (__ENABLE_FETCH_WITH_CREDENTIALS__) {\n options.credentials = \"include\";\n }\n\n const res = await fetch(sessionUrl, options);\n const jsonResponse = isJsonResponse(res.headers.get(\"content-type\"));\n\n if (!jsonResponse) {\n throw new Error(\"Session endpoint is not serving json\");\n }\n\n const payload = await res.json();\n\n if (payload.error === NOT_FOUND_ERROR_CODE) {\n sessionLoaded();\n } else {\n sessionLoaded(payload);\n }\n } catch (e) {\n sessionLoaded();\n console.warn(\"Could not fetch session data due to error:\", e);\n }\n};\n\nconst initialState = { data: null };\n\nconst REDUCER_KEY = \"session\";\n\nconst reducerSessionData = {\n [REDUCER_KEY]: (state = initialState, action) => {\n switch (action.type) {\n case \"session/loaded\":\n return { ...state, data: action.payload };\n default:\n return state;\n }\n },\n};\n\nconst selectSessionData = (store) => store.getState()[REDUCER_KEY]?.data;\n\nexport { fetchSessionData, reducerSessionData, selectSessionData };\n"],"names":["isJsonResponse","NOT_FOUND_ERROR_CODE","fetchSessionData","store","sessionUrl","sessionLoaded","payload","dispatch","type","console","log","options","headers","accept","cache","credentials","res","fetch","jsonResponse","get","Error","json","error","e","warn","initialState","data","REDUCER_KEY","reducerSessionData","state","action","selectSessionData","getState"],"mappings":"AAKA,OAASA,cAAc,KAAQ,oBAAqB,CAEpD,MAAMC,qBAAuB,YAE7B,MAAMC,iBAAmB,MAAOC,MAAOC,cACrC,MAAMC,cAAgB,CAACC,QAAU,CAAC,CAAC,GACjCH,MAAMI,QAAQ,CAAC,CAAEC,KAAM,iBAAkBF,OAAQ,GAEnD,GAAI,CACF,GAAI,CAACF,WAAY,CACfK,QAAQC,GAAG,CACT,CAAC,gDAAgD,EAAEN,WAAW,CAAC,CAAC,EAElEC,gBACA,MACF,CAEA,MAAMM,QAAU,CACdC,QAAS,CACPC,OAAQ,kBACV,EACAC,MAAO,UACT,EAEA,GA0BwB,MA1Be,CACrCH,QAAQI,WAAW,CAAG,SACxB,CAEA,MAAMC,IAAM,MAAMC,MAAMb,WAAYO,SACpC,MAAMO,aAAelB,eAAegB,IAAIJ,OAAO,CAACO,GAAG,CAAC,iBAEpD,GAAI,CAACD,aAAc,CACjB,MAAM,IAAIE,MAAM,uCAClB,CAEA,MAAMd,QAAU,MAAMU,IAAIK,IAAI,GAE9B,GAAIf,QAAQgB,KAAK,GAAKrB,qBAAsB,CAC1CI,eACF,KAAO,CACLA,cAAcC,QAChB,CACF,CAAE,MAAOiB,EAAG,CACVlB,gBACAI,QAAQe,IAAI,CAAC,6CAA8CD,EAC7D,CACF,EAEA,MAAME,aAAe,CAAEC,KAAM,IAAK,EAElC,MAAMC,YAAc,UAEpB,MAAMC,mBAAqB,CACzB,CAACD,YAAY,CAAE,CAACE,MAAQJ,YAAY,CAAEK,UACpC,OAAQA,OAAOtB,IAAI,EACjB,IAAK,iBACH,MAAO,CAAE,GAAGqB,KAAK,CAAEH,KAAMI,OAAOxB,OAAO,AAAC,CAC1C,SACE,OAAOuB,KACX,CACF,CACF,EAEA,MAAME,kBAAoB,AAAC5B,OAAUA,MAAM6B,QAAQ,EAAE,CAACL,YAAY,EAAED,IAEpE,QAASxB,gBAAgB,CAAE0B,kBAAkB,CAAEG,iBAAiB,CAAG"}
1
+ {"version":3,"sources":["../../src/core/remote-session-data.js"],"sourcesContent":["/* global __ENABLE_FETCH_WITH_CREDENTIALS__ */\n\n// Fetches current users session data\n// Assumes an authenticated session, so will only work when used on ably.com/ably.io\n\nimport { isJsonResponse } from \"./remote-data-util\";\n\nconst NOT_FOUND_ERROR_CODE = \"not-found\";\n\nconst fetchSessionData = async (store, sessionUrl) => {\n const sessionLoaded = (payload = {}) =>\n store.dispatch({ type: \"session/loaded\", payload });\n\n try {\n if (!sessionUrl) {\n console.log(\n `Skipping fetching session, invalid sessionUrl: \"${sessionUrl}\"`,\n );\n sessionLoaded();\n return;\n }\n\n const options = {\n headers: {\n accept: \"application/json\",\n },\n cache: \"no-cache\",\n };\n\n if (__ENABLE_FETCH_WITH_CREDENTIALS__) {\n options.credentials = \"include\";\n }\n\n const res = await fetch(sessionUrl, options);\n const jsonResponse = isJsonResponse(res.headers.get(\"content-type\"));\n\n if (!jsonResponse) {\n throw new Error(\"Session endpoint is not serving json\");\n }\n\n const payload = await res.json();\n\n if (payload.error === NOT_FOUND_ERROR_CODE) {\n sessionLoaded();\n } else {\n sessionLoaded(payload);\n }\n } catch (e) {\n sessionLoaded();\n console.warn(\"Could not fetch session data due to error:\", e);\n }\n};\n\nconst initialState = { data: null };\n\nconst REDUCER_KEY = \"session\";\n\nconst reducerSessionData = {\n [REDUCER_KEY]: (state = initialState, action) => {\n switch (action.type) {\n case \"session/loaded\":\n return { ...state, data: action.payload };\n default:\n return state;\n }\n },\n};\n\nconst selectSessionData = (store) => store.getState()[REDUCER_KEY]?.data;\n\nexport { fetchSessionData, reducerSessionData, selectSessionData };\n"],"names":["isJsonResponse","NOT_FOUND_ERROR_CODE","fetchSessionData","store","sessionUrl","sessionLoaded","payload","dispatch","type","console","log","options","headers","accept","cache","credentials","res","fetch","jsonResponse","get","Error","json","error","e","warn","initialState","data","REDUCER_KEY","reducerSessionData","state","action","selectSessionData","getState"],"mappings":"AAKA,OAASA,cAAc,KAAQ,oBAAqB,CAEpD,MAAMC,qBAAuB,YAE7B,MAAMC,iBAAmB,MAAOC,MAAOC,cACrC,MAAMC,cAAgB,CAACC,QAAU,CAAC,CAAC,GACjCH,MAAMI,QAAQ,CAAC,CAAEC,KAAM,iBAAkBF,OAAQ,GAEnD,GAAI,CACF,GAAI,CAACF,WAAY,CACfK,QAAQC,GAAG,CACT,CAAC,gDAAgD,EAAEN,WAAW,CAAC,CAAC,EAElEC,gBACA,MACF,CAEA,MAAMM,QAAU,CACdC,QAAS,CACPC,OAAQ,kBACV,EACAC,MAAO,UACT,EAEA,GACkB,MADqB,CACrCH,QAAQI,WAAW,CAAG,SACxB,CAEA,MAAMC,IAAM,MAAMC,MAAMb,WAAYO,SACpC,MAAMO,aAAelB,eAAegB,IAAIJ,OAAO,CAACO,GAAG,CAAC,iBAEpD,GAAI,CAACD,aAAc,CACjB,MAAM,IAAIE,MAAM,uCAClB,CAEA,MAAMd,QAAU,MAAMU,IAAIK,IAAI,GAE9B,GAAIf,QAAQgB,KAAK,GAAKrB,qBAAsB,CAC1CI,eACF,KAAO,CACLA,cAAcC,QAChB,CACF,CAAE,MAAOiB,EAAG,CACVlB,gBACAI,QAAQe,IAAI,CAAC,6CAA8CD,EAC7D,CACF,EAEA,MAAME,aAAe,CAAEC,KAAM,IAAK,EAElC,MAAMC,YAAc,UAEpB,MAAMC,mBAAqB,CACzB,CAACD,YAAY,CAAE,CAACE,MAAQJ,YAAY,CAAEK,UACpC,OAAQA,OAAOtB,IAAI,EACjB,IAAK,iBACH,MAAO,CAAE,GAAGqB,KAAK,CAAEH,KAAMI,OAAOxB,OAAO,AAAC,CAC1C,SACE,OAAOuB,KACX,CACF,CACF,EAEA,MAAME,kBAAoB,AAAC5B,OAAUA,MAAM6B,QAAQ,EAAE,CAACL,YAAY,EAAED,IAEpE,QAASxB,gBAAgB,CAAE0B,kBAAkB,CAAEG,iBAAiB,CAAG"}
package/index.d.ts CHANGED
@@ -760,9 +760,9 @@ export type HeaderProps = {
760
760
  */
761
761
  className?: string;
762
762
  /**
763
- * Indicates if the notice banner is visible.
763
+ * Indicates if the notice banner is enabled.
764
764
  */
765
- isNoticeVisible?: boolean;
765
+ isNoticeBannerEnabled?: boolean;
766
766
  /**
767
767
  * Height of the notice banner in pixels.
768
768
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ably/ui",
3
- "version": "17.7.4-dev.8763c7aa",
3
+ "version": "17.7.4-dev.c54fc584",
4
4
  "description": "Home of the Ably design system library ([design.ably.com](https://design.ably.com)). It provides a showcase, development/test environment and a publishing pipeline for different distributables.",
5
5
  "repository": {
6
6
  "type": "git",