@lifesg/react-design-system 4.0.0-alpha.10 → 4.0.0-alpha.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/accordion/accordion-item.js +1 -1
  2. package/accordion/accordion-item.js.map +1 -1
  3. package/accordion/types.d.ts +7 -0
  4. package/cjs/accordion/accordion-item.js +1 -1
  5. package/cjs/accordion/accordion-item.js.map +1 -1
  6. package/cjs/file-download/file-download.js +1 -1
  7. package/cjs/file-download/file-download.js.map +1 -1
  8. package/cjs/file-download/file-list-card/file-list-card.js +1 -1
  9. package/cjs/file-download/file-list-card/file-list-card.js.map +1 -1
  10. package/cjs/file-download/file-list-card/file-list-card.styles.js +1 -1
  11. package/cjs/file-download/file-list-card/file-list-card.styles.js.map +1 -1
  12. package/cjs/file-download/file-list-card/file-list-card.styles_lzbqkk.css +18 -0
  13. package/cjs/file-upload/helper.js +1 -1
  14. package/cjs/file-upload/helper.js.map +1 -1
  15. package/cjs/footer/footer-disclaimer-links-data.js +1 -1
  16. package/cjs/footer/footer-disclaimer-links-data.js.map +1 -1
  17. package/cjs/footer/footer.styles.js +1 -1
  18. package/cjs/footer/footer.styles.js.map +1 -1
  19. package/{footer/footer.styles_1msorhc.css → cjs/footer/footer.styles_14hnlcq.css} +4 -4
  20. package/cjs/fullscreen-image-carousel/fullscreen-image-carousel.js +1 -1
  21. package/cjs/fullscreen-image-carousel/fullscreen-image-carousel.js.map +1 -1
  22. package/cjs/index.js +1 -1
  23. package/cjs/masthead/masthead.js +1 -1
  24. package/cjs/masthead/masthead.js.map +1 -1
  25. package/cjs/masthead/sgds-day.css +519 -59
  26. package/cjs/masthead/sgds-night.css +513 -53
  27. package/cjs/modal-v2/modal-v2.js.map +1 -1
  28. package/cjs/modal-v2/slots/card.js +1 -1
  29. package/cjs/modal-v2/slots/card.js.map +1 -1
  30. package/cjs/modal-v2/slots/slot-styles.js +1 -1
  31. package/cjs/modal-v2/slots/slot-styles.js.map +1 -1
  32. package/cjs/modal-v2/slots/slot-styles_ayb9il.css +33 -0
  33. package/cjs/navbar/menu.js +1 -1
  34. package/cjs/navbar/menu.js.map +1 -1
  35. package/cjs/navbar/menu.styles.js +1 -1
  36. package/cjs/navbar/menu.styles.js.map +1 -1
  37. package/{navbar/menu.styles_gdpqc.css → cjs/navbar/menu.styles_zkjexa.css} +1 -1
  38. package/cjs/navbar/navbar-items.js +1 -1
  39. package/cjs/navbar/navbar-items.js.map +1 -1
  40. package/cjs/navbar/navbar-items.styles.js +1 -1
  41. package/cjs/navbar/navbar-items.styles.js.map +1 -1
  42. package/cjs/navbar/{navbar-items.styles_1b1zx.css → navbar-items.styles_1klnd8i.css} +3 -3
  43. package/cjs/navbar/navbar-logo-data.js +1 -1
  44. package/cjs/navbar/navbar-logo-data.js.map +1 -1
  45. package/cjs/theme/index.js +1 -1
  46. package/cjs/theme/theme-provider/breakpoint.js +1 -1
  47. package/cjs/theme/theme-provider/breakpoint.js.map +1 -1
  48. package/cjs/theme/theme-provider/hooks.js +1 -1
  49. package/cjs/theme/theme-provider/hooks.js.map +1 -1
  50. package/cjs/theme/theme-provider/index.js +1 -1
  51. package/cjs/theme/theme-provider/index.js.map +1 -1
  52. package/cjs/theme/types.js +1 -1
  53. package/cjs/theme/types.js.map +1 -1
  54. package/docs/component-catalog.json +1 -1
  55. package/file-download/file-download.d.ts +1 -1
  56. package/file-download/file-download.js +1 -1
  57. package/file-download/file-download.js.map +1 -1
  58. package/file-download/file-list-card/file-list-card.d.ts +1 -1
  59. package/file-download/file-list-card/file-list-card.js +1 -1
  60. package/file-download/file-list-card/file-list-card.js.map +1 -1
  61. package/file-download/file-list-card/file-list-card.styles.d.ts +2 -0
  62. package/file-download/file-list-card/file-list-card.styles.js +1 -1
  63. package/file-download/file-list-card/file-list-card.styles.js.map +1 -1
  64. package/file-download/file-list-card/file-list-card.styles_lzbqkk.css +18 -0
  65. package/file-download/file-list-card/types.d.ts +1 -0
  66. package/file-download/types.d.ts +13 -0
  67. package/file-upload/helper.d.ts +30 -0
  68. package/file-upload/helper.js +1 -1
  69. package/file-upload/helper.js.map +1 -1
  70. package/footer/footer-disclaimer-links-data.js +1 -1
  71. package/footer/footer-disclaimer-links-data.js.map +1 -1
  72. package/footer/footer.styles.js +1 -1
  73. package/footer/footer.styles.js.map +1 -1
  74. package/{cjs/footer/footer.styles_1msorhc.css → footer/footer.styles_14hnlcq.css} +4 -4
  75. package/fullscreen-image-carousel/fullscreen-image-carousel.d.ts +1 -1
  76. package/fullscreen-image-carousel/fullscreen-image-carousel.js +1 -1
  77. package/fullscreen-image-carousel/fullscreen-image-carousel.js.map +1 -1
  78. package/fullscreen-image-carousel/types.d.ts +37 -0
  79. package/index.js +1 -1
  80. package/masthead/masthead.js +1 -1
  81. package/masthead/masthead.js.map +1 -1
  82. package/masthead/sgds-day.css +519 -59
  83. package/masthead/sgds-night.css +513 -53
  84. package/modal-v2/modal-v2.d.ts +2 -2
  85. package/modal-v2/modal-v2.js.map +1 -1
  86. package/modal-v2/slots/card.js +1 -1
  87. package/modal-v2/slots/card.js.map +1 -1
  88. package/modal-v2/slots/slot-styles.d.ts +4 -0
  89. package/modal-v2/slots/slot-styles.js +1 -1
  90. package/modal-v2/slots/slot-styles.js.map +1 -1
  91. package/modal-v2/slots/slot-styles_ayb9il.css +33 -0
  92. package/modal-v2/types.d.ts +5 -0
  93. package/navbar/menu.d.ts +2 -1
  94. package/navbar/menu.js +1 -1
  95. package/navbar/menu.js.map +1 -1
  96. package/navbar/menu.styles.js +1 -1
  97. package/navbar/menu.styles.js.map +1 -1
  98. package/{cjs/navbar/menu.styles_gdpqc.css → navbar/menu.styles_zkjexa.css} +1 -1
  99. package/navbar/navbar-items.js +1 -1
  100. package/navbar/navbar-items.js.map +1 -1
  101. package/navbar/navbar-items.styles.js +1 -1
  102. package/navbar/navbar-items.styles.js.map +1 -1
  103. package/navbar/{navbar-items.styles_1b1zx.css → navbar-items.styles_1klnd8i.css} +3 -3
  104. package/navbar/navbar-logo-data.js +1 -1
  105. package/navbar/navbar-logo-data.js.map +1 -1
  106. package/package.json +2 -1
  107. package/theme/index.js +1 -1
  108. package/theme/styles/sportsg-orange.css +779 -0
  109. package/theme/styles/vica.css +840 -0
  110. package/theme/styles/websg.css +840 -0
  111. package/theme/styles/wise.css +840 -0
  112. package/theme/styles/wogaa.css +840 -0
  113. package/theme/theme-provider/breakpoint.js +1 -1
  114. package/theme/theme-provider/breakpoint.js.map +1 -1
  115. package/theme/theme-provider/hooks.d.ts +1 -0
  116. package/theme/theme-provider/hooks.js +1 -1
  117. package/theme/theme-provider/hooks.js.map +1 -1
  118. package/theme/theme-provider/index.js +1 -1
  119. package/theme/theme-provider/index.js.map +1 -1
  120. package/theme/theme-provider/preset.d.ts +2 -0
  121. package/theme/theme-provider/types.d.ts +8 -1
  122. package/theme/types.d.ts +9 -1
  123. package/theme/types.js +1 -1
  124. package/theme/types.js.map +1 -1
  125. package/cjs/file-download/file-list-card/file-list-card.styles_18j2gut.css +0 -16
  126. package/cjs/modal-v2/slots/slot-styles_10ut1v7.css +0 -30
  127. package/file-download/file-list-card/file-list-card.styles_18j2gut.css +0 -16
  128. package/modal-v2/slots/slot-styles_10ut1v7.css +0 -30
@@ -1,2 +1,2 @@
1
- import{__rest as e}from"../_virtual/_tslib.js";import{jsx as i,jsxs as t,Fragment as l}from"react/jsx-runtime";import{ChevronLeftIcon as r,ChevronRightIcon as o,MagnifierPlusIcon as a,MagnifierMinusIcon as n,CrossIcon as s}from"@lifesg/react-icons";import{BinIcon as d}from"@lifesg/react-icons/bin";import{clearAnnouncer as c,announce as m}from"@react-aria/live-announcer";import u from"clsx";import{forwardRef as h,useState as v,useRef as p,useMemo as f,useCallback as g,useImperativeHandle as b,useEffect as N}from"react";import{TransformWrapper as j,TransformComponent as x}from"react-zoom-pan-pinch";import{ModalV2 as k}from"../modal-v2/modal-v2.js";import{ClickableIcon as y}from"../shared/clickable-icon/clickable-icon.js";import{useStateCallback as w}from"../shared/hooks/use-state-callback.js";import{ImagePlaceholder as C}from"../shared/image-placeholder/image-placeholder.js";import"../theme/theme-provider/index.js";import{formatUnitValue as I}from"../theme/utils/css-variable.js";import"../theme/theme-provider/context.js";import"../theme/tokens/border.js";import"../theme/tokens/colour.js";import"../theme/tokens/font.js";import"../theme/tokens/media-query.js";import{useApplyStyle as T}from"../theme/utils/use-apply-styles.js";import"../theme/utils/use-media-query.js";import{Typography as $}from"../typography/index.js";import"../util/calendar-helper.js";import"../external/dayjs/dayjs.min.js";import"../util/simple-id-generator.js";import"../util/string-helper.js";import{useEventListener as B}from"../util/use-event-listener.js";import{tokens as S,carouselModalContent as A,imageGalleryContainer as L,imageGalleryWrapper as D,imageGallerySwipe as M,iconButton as z,arrowButton as X,arrowButtonLeft as Z,arrowButtonRight as O,boxChip as R,chip as W,topActionButtons as q,iconButtonError as E,imageGallerySlides as P,imageGallerySlide as V,focusableImageRegion as _,slidePlaceholderImage as F,slideImage as H,thumbnailContainer as G,thumbnailWrapper as J,thumbnailItemContainer as K,thumbnailItem as Q,thumbnailImage as U,fileInfoFileName as Y,fileInfoFileSize as ee,fileInfoTextWrapper as ie,fileInfoTextWrapperCentered as te}from"./fullscreen-image-carousel.styles.js";import{StatefulImage as le}from"./stateful-image.js";const re=e=>!!e&&"custom"===e.type,oe=(h,oe)=>{var ae,{items:ne,initialActiveItemIndex:se,hideThumbnail:de=!1,hideNavigation:ce=!1,hideCounter:me=!1,hideMagnifier:ue=!1,onDelete:he,onClose:ve,insets:pe,show:fe}=h,ge=e(h,["items","initialActiveItemIndex","hideThumbnail","hideNavigation","hideCounter","hideMagnifier","onDelete","onClose","insets","show"]);const[be,Ne]=w(null!=se?se:0),[je,xe]=v({}),[ke,ye]=v(1),[we,Ce]=v(),[Ie,Te]=v(),$e=p(null),Be=p([]),Se=p([]),Ae=p(null),Le=p(null),De=p(null),Me=p(null),ze=p(null),Xe=we&&Ie?we-Ie:0,Ze=ne[be],Oe=ne.some((e=>{var i;return re(e)&&!!(null===(i=e.itemLabel)||void 0===i?void 0:i.trim())})),Re=Oe?"item":"image",We=f((()=>ne.some((e=>{var i,t;return(null===(i=e.fileName)||void 0===i?void 0:i.trim())||(null===(t=e.fileSize)||void 0===t?void 0:t.trim())}))),[ne]);T(Le,{[S.topActionButtons.insetTop]:I(null==pe?void 0:pe.top,"px"),[S.topActionButtons.insetLeft]:I(null==pe?void 0:pe.left,"px"),[S.topActionButtons.insetRight]:I(null==pe?void 0:pe.right,"px")}),T(De,{[S.arrowButton.insetLeft]:I(null==pe?void 0:pe.left,"px")}),T(Me,{[S.arrowButton.insetRight]:I(null==pe?void 0:pe.right,"px")}),T(ze,{[S.thumbnailContainer.insetBottom]:I(null==pe?void 0:pe.bottom,"px")});const qe=g((e=>{var i,t;const l=ne[e],r=Oe?"Item":"Image",o=re(l)?(null===(i=l.itemLabel)||void 0===i?void 0:i.trim())||"":(null===(t=l.alt)||void 0===t?void 0:t.trim())||"",a=`${r} ${e+1} of ${ne.length}.`;return o?`${o}. ${a}`:a}),[ne,Oe]);b(oe,(()=>({currentItemIndex:be,setCurrentItem:He,goToPrevItem:_e,goToNextItem:Fe}))),B("keydown",(function(e){"ArrowRight"===e.key?Fe():"ArrowLeft"===e.key?_e():"Escape"===e.key&&(null==ve||ve())}),"document"),N((()=>{var e;fe&&(null===(e=Ae.current)||void 0===e||e.focus())}),[fe]),N((()=>{0!==ne.length?be>ne.length-1&&Ne(ne.length-1):Ne(0)}),[be,ne.length,Ne]),N((()=>{var e,i;null===(i=null===(e=Be.current)||void 0===e?void 0:e[be])||void 0===i||i.scrollIntoView({behavior:"smooth",inline:"center"}),ye(1)}),[be]);const Ee=e=>{ye(e.state.scale)};const Pe=({src:e,height:i,width:t})=>{xe((l=>Object.assign(Object.assign({},l),{[e]:{height:i,width:t}})))},Ve=()=>{if(!Ze||re(Ze))return;const e=je[Ze.src];if($e.current&&e){const{clientHeight:i,clientWidth:t}=$e.current,{width:l,height:r}=e,o=r/l<i/t;return l<t&&r<i?o?t/l:i/r:o?i/(r/(l/t)):t/(l/(r/i))}},_e=()=>{var e,i;null===(i=null===(e=Se.current)||void 0===e?void 0:e[be])||void 0===i||i.resetTransform(),Ne((e=>0===e?ne.length-1:e-1),(e=>{c("polite"),m(qe(e),"polite")}))},Fe=()=>{var e,i;null===(i=null===(e=Se.current)||void 0===e?void 0:e[be])||void 0===i||i.resetTransform(),Ne((e=>e===ne.length-1?0:e+1),(e=>{c("polite"),m(qe(e),"polite")}))},He=e=>{var i,t;null===(t=null===(i=Se.current)||void 0===i?void 0:i[be])||void 0===t||t.resetTransform(),Ne(e)};return i(k,Object.assign({},ge,{"data-testid":"image-carousel-modal","aria-label":Oe?"Carousel":"Image carousel",show:fe,disableInitialFocus:!0,children:t("div",{className:A,children:[t("div",{className:L,children:[t("div",{className:D,children:[i("div",{className:M,ref:$e,onTouchStart:e=>{ke<=1&&Ce(e.touches[0].clientX)},onTouchMove:e=>{!we||ke>1||Te(e.touches[0].clientX)},onTouchEnd:()=>{$e.current&&(Math.abs(Xe)>$e.current.offsetWidth/3&&(Xe>0?Fe():_e()),Ce(void 0),Te(void 0))},children:i("div",{className:P,style:{transform:`translateX(calc(${100*-be}% - ${Xe}px))`},children:ne.map(((e,t)=>{const l=t===be,r=Math.abs(t-be)<=1||0===be&&t===ne.length-1||be===ne.length-1&&0===t;return i("div",{className:V,"data-testid":"slide-item",children:i("div",{className:_,ref:l?Ae:null,tabIndex:l?0:-1,children:re(e)?r?e.renderContent():i(C,{className:F}):i(j,{ref:e=>Se.current[t]=e,panning:{disabled:ke<=1},initialScale:1,onZoom:Ee,onZoomStop:Ee,onWheel:Ee,children:i(x,{children:i(le,{className:H,src:e.src,alt:qe(t),placeholder:i(C,{className:F}),fit:"scale-down",retrieveImageDimension:!0,setDimension:Pe})})})})},t)}))})}),!ce&&t(l,{children:[i(y,{className:u(z,X,Z),ref:De,"aria-label":`Previous ${Re}`,"data-testid":"prev-btn",onClick:_e,children:i(r,{"aria-hidden":!0})}),i(y,{className:u(z,X,O),ref:Me,"aria-label":`Next ${Re}`,"data-testid":"forward-btn",onClick:Fe,children:i(o,{"aria-hidden":!0})})]}),!me&&i("div",{className:R,"aria-hidden":"true",children:i($.BodyXS,{className:W,weight:"semibold","data-testid":"carousel-counter",children:`${be+1}/${ne.length}`})})]}),!de&&i("div",{className:G,ref:ze,"aria-hidden":"true","data-testid":"thumbnail-container",children:i("div",{className:J,children:ne.map(((e,t)=>{var l;const r=re(e)?e.thumbnailSrc:null!==(l=e.thumbnailSrc)&&void 0!==l?l:e.src;return i("div",{className:K,children:i("div",{className:Q,"data-active":t===be,"data-testid":"thumbnail-item",onClick:()=>He(t),ref:e=>Be.current[t]=e,children:r?i(le,{className:U,src:r,alt:`Thumbnail ${t+1}`,fit:"cover"}):i(C,{className:F})})},t)}))})})]}),t("div",{className:q,ref:Le,"data-has-file-info":We,children:[We&&(()=>{const{fileName:e,fileSize:l}=null!=Ze?Ze:{},r=null==e?void 0:e.trim(),o=null==l?void 0:l.trim();return t("div",{className:u(ie,!o&&te),"aria-live":"polite","aria-atomic":"true","data-testid":"file-info-bar",children:[r&&i($.BodyBL,{className:Y,weight:"semibold","data-testid":"file-info-name",children:r}),o&&i($.BodyMD,{className:ee,"data-testid":"file-info-size",children:o})]})})(),!ue&&!re(Ze)&&i(y,{className:z,"aria-label":1===ke?"Zoom in":"Zoom out",onClick:()=>{var e,i,t,l;if(1===ke){const t=Ve();null===(i=null===(e=Se.current)||void 0===e?void 0:e[be])||void 0===i||i.centerView(t),ye(null!=t?t:1)}else ye(1),null===(l=null===(t=Se.current)||void 0===t?void 0:t[be])||void 0===l||l.resetTransform()},children:i(1===ke?a:n,{"aria-hidden":!0})}),he&&i(y,{className:u(z,E),"aria-label":`Delete ${re(Ze)&&(null===(ae=Ze.itemLabel)||void 0===ae?void 0:ae.trim())||"image"}`,"data-testid":"delete-btn",onClick:()=>{Ze&&he&&he(Ze,be)},children:i(d,{"aria-hidden":!0})}),i(y,{className:z,"aria-label":Oe?"Close carousel":"Close image carousel",onClick:ve,children:i(s,{"aria-hidden":!0})})]})]})}))},ae=h(oe);export{oe as Component,ae as FullscreenImageCarousel};
1
+ import{__rest as e}from"../_virtual/_tslib.js";import{jsx as i,jsxs as t,Fragment as l}from"react/jsx-runtime";import{ChevronLeftIcon as r,ChevronRightIcon as o,MagnifierPlusIcon as a,MagnifierMinusIcon as n,CrossIcon as s}from"@lifesg/react-icons";import{BinIcon as d}from"@lifesg/react-icons/bin";import{clearAnnouncer as c,announce as m}from"@react-aria/live-announcer";import u from"clsx";import{forwardRef as h,useState as v,useRef as p,useMemo as f,useCallback as g,useImperativeHandle as b,useEffect as N,cloneElement as j}from"react";import{TransformWrapper as k,TransformComponent as x}from"react-zoom-pan-pinch";import{ModalV2 as y}from"../modal-v2/modal-v2.js";import{ClickableIcon as C}from"../shared/clickable-icon/clickable-icon.js";import{useStateCallback as w}from"../shared/hooks/use-state-callback.js";import{ImagePlaceholder as I}from"../shared/image-placeholder/image-placeholder.js";import"../theme/theme-provider/index.js";import{formatUnitValue as T}from"../theme/utils/css-variable.js";import"../theme/theme-provider/context.js";import"../theme/tokens/border.js";import"../theme/tokens/colour.js";import"../theme/tokens/font.js";import"../theme/tokens/media-query.js";import{useApplyStyle as $}from"../theme/utils/use-apply-styles.js";import"../theme/utils/use-media-query.js";import{Typography as B}from"../typography/index.js";import"../util/calendar-helper.js";import"../external/dayjs/dayjs.min.js";import{mergeRefs as A}from"../util/merge-refs.js";import"../util/simple-id-generator.js";import"../util/string-helper.js";import{useEventListener as L}from"../util/use-event-listener.js";import{tokens as S,carouselModalContent as D,imageGalleryContainer as M,imageGalleryWrapper as R,imageGallerySwipe as z,iconButton as X,arrowButton as Z,arrowButtonLeft as O,arrowButtonRight as W,boxChip as q,chip as E,imageGallerySlides as P,imageGallerySlide as V,focusableImageRegion as _,slidePlaceholderImage as F,slideImage as H,thumbnailContainer as G,thumbnailWrapper as J,thumbnailItemContainer as K,thumbnailItem as Q,thumbnailImage as U,topActionButtons as Y,iconButtonError as ee,fileInfoFileName as ie,fileInfoFileSize as te,fileInfoTextWrapper as le,fileInfoTextWrapperCentered as re}from"./fullscreen-image-carousel.styles.js";import{StatefulImage as oe}from"./stateful-image.js";const ae=e=>!!e&&"custom"===e.type,ne=(h,ne)=>{var se,de,{items:ce,initialActiveItemIndex:me,hideThumbnail:ue=!1,hideNavigation:he=!1,hideCounter:ve=!1,hideMagnifier:pe=!1,customActions:fe,onDelete:ge,onClose:be,insets:Ne,topBarRef:je,show:ke}=h,xe=e(h,["items","initialActiveItemIndex","hideThumbnail","hideNavigation","hideCounter","hideMagnifier","customActions","onDelete","onClose","insets","topBarRef","show"]);const[ye,Ce]=w(null!=me?me:0),[we,Ie]=v({}),[Te,$e]=v(1),[Be,Ae]=v(),[Le,Se]=v(),De=p(null),Me=p([]),Re=p([]),ze=p(null),[Xe,Ze]=v(null),Oe=f((()=>({current:Xe})),[Xe]),We=f((()=>A(Ze,je)),[je]),qe=p(null),Ee=p(null),Pe=p(null),Ve=Be&&Le?Be-Le:0,_e=ce[ye],Fe=null!==(de=null!==(se=null==_e?void 0:_e.customActions)&&void 0!==se?se:fe)&&void 0!==de?de:[],He=ce.some((e=>{var i;return ae(e)&&!!(null===(i=e.itemLabel)||void 0===i?void 0:i.trim())})),Ge=He?"item":"image",Je=f((()=>ce.some((e=>{var i,t;return(null===(i=e.fileName)||void 0===i?void 0:i.trim())||(null===(t=e.fileSize)||void 0===t?void 0:t.trim())}))),[ce]);$(Oe,{[S.topActionButtons.insetTop]:T(null==Ne?void 0:Ne.top,"px"),[S.topActionButtons.insetLeft]:T(null==Ne?void 0:Ne.left,"px"),[S.topActionButtons.insetRight]:T(null==Ne?void 0:Ne.right,"px")}),$(qe,{[S.arrowButton.insetLeft]:T(null==Ne?void 0:Ne.left,"px")}),$(Ee,{[S.arrowButton.insetRight]:T(null==Ne?void 0:Ne.right,"px")}),$(Pe,{[S.thumbnailContainer.insetBottom]:T(null==Ne?void 0:Ne.bottom,"px")});const Ke=g((e=>{var i,t;const l=ce[e],r=He?"Item":"Image",o=ae(l)?(null===(i=l.itemLabel)||void 0===i?void 0:i.trim())||"":(null===(t=l.alt)||void 0===t?void 0:t.trim())||"",a=`${r} ${e+1} of ${ce.length}.`;return o?`${o}. ${a}`:a}),[ce,He]);b(ne,(()=>({currentItemIndex:ye,setCurrentItem:ri,goToPrevItem:ti,goToNextItem:li}))),L("keydown",(function(e){"ArrowRight"===e.key?li():"ArrowLeft"===e.key?ti():"Escape"===e.key&&(null==be||be())}),"document"),N((()=>{var e;ke&&(null===(e=ze.current)||void 0===e||e.focus())}),[ke]),N((()=>{0!==ce.length?ye>ce.length-1&&Ce(ce.length-1):Ce(0)}),[ye,ce.length,Ce]),N((()=>{var e,i;null===(i=null===(e=Me.current)||void 0===e?void 0:e[ye])||void 0===i||i.scrollIntoView({behavior:"smooth",inline:"center"}),$e(1)}),[ye]);const Qe=e=>{$e(e.state.scale)},Ue=()=>{_e&&ge&&ge(_e,ye)};const Ye=()=>{var e,i,t,l;if(1===Te){const t=ii();null===(i=null===(e=Re.current)||void 0===e?void 0:e[ye])||void 0===i||i.centerView(t),$e(null!=t?t:1)}else $e(1),null===(l=null===(t=Re.current)||void 0===t?void 0:t[ye])||void 0===l||l.resetTransform()},ei=({src:e,height:i,width:t})=>{Ie((l=>Object.assign(Object.assign({},l),{[e]:{height:i,width:t}})))},ii=()=>{if(!_e||ae(_e))return;const e=we[_e.src];if(De.current&&e){const{clientHeight:i,clientWidth:t}=De.current,{width:l,height:r}=e,o=r/l<i/t;return l<t&&r<i?o?t/l:i/r:o?i/(r/(l/t)):t/(l/(r/i))}},ti=()=>{var e,i;null===(i=null===(e=Re.current)||void 0===e?void 0:e[ye])||void 0===i||i.resetTransform(),Ce((e=>0===e?ce.length-1:e-1),(e=>{c("polite"),m(Ke(e),"polite")}))},li=()=>{var e,i;null===(i=null===(e=Re.current)||void 0===e?void 0:e[ye])||void 0===i||i.resetTransform(),Ce((e=>e===ce.length-1?0:e+1),(e=>{c("polite"),m(Ke(e),"polite")}))},ri=e=>{var i,t;null===(t=null===(i=Re.current)||void 0===i?void 0:i[ye])||void 0===t||t.resetTransform(),Ce(e)},oi=()=>{const{fileName:e,fileSize:l}=null!=_e?_e:{},r=null==e?void 0:e.trim(),o=null==l?void 0:l.trim();return t("div",{className:u(le,!o&&re),"aria-live":"polite","aria-atomic":"true","data-testid":"file-info-bar",children:[r&&i(B.BodyBL,{className:ie,weight:"semibold","data-testid":"file-info-name",children:r}),o&&i(B.BodyMD,{className:te,"data-testid":"file-info-size",children:o})]})};return i(y,Object.assign({},xe,{"data-testid":"image-carousel-modal","aria-label":He?"Carousel":"Image carousel",show:ke,disableInitialFocus:!0,children:t("div",{className:D,children:[t("div",{className:M,children:[t("div",{className:R,children:[i("div",{className:z,ref:De,onTouchStart:e=>{Te<=1&&Ae(e.touches[0].clientX)},onTouchMove:e=>{!Be||Te>1||Se(e.touches[0].clientX)},onTouchEnd:()=>{De.current&&(Math.abs(Ve)>De.current.offsetWidth/3&&(Ve>0?li():ti()),Ae(void 0),Se(void 0))},children:i("div",{className:P,style:{transform:`translateX(calc(${100*-ye}% - ${Ve}px))`},children:ce.map(((e,t)=>{const l=t===ye,r=Math.abs(t-ye)<=1||0===ye&&t===ce.length-1||ye===ce.length-1&&0===t;return i("div",{className:V,"data-testid":"slide-item",children:i("div",{className:_,ref:l?ze:null,tabIndex:l?0:-1,children:ae(e)?r?e.renderContent():i(I,{className:F}):i(k,{ref:e=>Re.current[t]=e,panning:{disabled:Te<=1},initialScale:1,onZoom:Qe,onZoomStop:Qe,onWheel:Qe,children:i(x,{children:i(oe,{className:H,src:e.src,alt:Ke(t),placeholder:i(I,{className:F}),fit:"scale-down",retrieveImageDimension:!0,setDimension:ei})})})})},t)}))})}),!he&&t(l,{children:[i(C,{className:u(X,Z,O),ref:qe,"aria-label":`Previous ${Ge}`,"data-testid":"prev-btn",onClick:ti,children:i(r,{"aria-hidden":!0})}),i(C,{className:u(X,Z,W),ref:Ee,"aria-label":`Next ${Ge}`,"data-testid":"forward-btn",onClick:li,children:i(o,{"aria-hidden":!0})})]}),!ve&&i("div",{className:q,"aria-hidden":"true",children:i(B.BodyXS,{className:E,weight:"semibold","data-testid":"carousel-counter",children:`${ye+1}/${ce.length}`})})]}),!ue&&i("div",{className:G,ref:Pe,"aria-hidden":"true","data-testid":"thumbnail-container",children:i("div",{className:J,children:ce.map(((e,t)=>{var l;const r=ae(e)?e.thumbnailSrc:null!==(l=e.thumbnailSrc)&&void 0!==l?l:e.src;return i("div",{className:K,children:i("div",{className:Q,"data-active":t===ye,"data-testid":"thumbnail-item",onClick:()=>ri(t),ref:e=>Me.current[t]=e,children:r?i(oe,{className:U,src:r,alt:`Thumbnail ${t+1}`,fit:"cover"}):i(I,{className:F})})},t)}))})})]}),(()=>{var e;return t("div",{className:Y,ref:We,"data-has-file-info":Je,children:[Je&&oi(),Fe.map(((e,t)=>i(C,{className:X,"aria-label":e.ariaLabel,"data-testid":e["data-testid"],onClick:()=>(e=>{_e&&e.onClick(_e,ye)})(e),children:j(e.icon,{"aria-hidden":!0})},t))),!pe&&!ae(_e)&&i(C,{className:X,"aria-label":1===Te?"Zoom in":"Zoom out",onClick:Ye,children:i(1===Te?a:n,{"aria-hidden":!0})}),ge&&i(C,{className:u(X,ee),"aria-label":`Delete ${ae(_e)&&(null===(e=_e.itemLabel)||void 0===e?void 0:e.trim())||"image"}`,"data-testid":"delete-btn",onClick:Ue,children:i(d,{"aria-hidden":!0})}),i(C,{className:X,"aria-label":He?"Close carousel":"Close image carousel",onClick:be,children:i(s,{"aria-hidden":!0})})]})})()]})}))},se=h(ne);export{ne as Component,se as FullscreenImageCarousel};
2
2
  //# sourceMappingURL=fullscreen-image-carousel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fullscreen-image-carousel.js","sources":["../../src/fullscreen-image-carousel/fullscreen-image-carousel.tsx"],"sourcesContent":["import {\n ChevronLeftIcon,\n ChevronRightIcon,\n CrossIcon,\n MagnifierMinusIcon,\n MagnifierPlusIcon,\n} from \"@lifesg/react-icons\";\nimport { BinIcon } from \"@lifesg/react-icons/bin\";\nimport { announce, clearAnnouncer } from \"@react-aria/live-announcer\";\nimport clsx from \"clsx\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type {\n ReactZoomPanPinchContentRef,\n ReactZoomPanPinchRef,\n} from \"react-zoom-pan-pinch\";\nimport { TransformComponent, TransformWrapper } from \"react-zoom-pan-pinch\";\n\nimport { ModalV2 } from \"../modal-v2\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport { useStateCallback } from \"../shared/hooks\";\nimport { ImagePlaceholder } from \"../shared/image-placeholder\";\nimport { formatUnitValue, useApplyStyle } from \"../theme\";\nimport { Typography } from \"../typography\";\nimport { useEventListener } from \"../util\";\nimport * as styles from \"./fullscreen-image-carousel.styles\";\nimport { StatefulImage } from \"./stateful-image\";\nimport type {\n FullscreenImageCarouselCustomItemProps,\n FullscreenImageCarouselItemProps,\n FullscreenImageCarouselProps,\n FullscreenImageCarouselRef,\n ImageDimension,\n} from \"./types\";\n\nconst isCustomItem = (\n item: FullscreenImageCarouselItemProps | undefined\n): item is FullscreenImageCarouselCustomItemProps =>\n !!item && item.type === \"custom\";\n\nexport const Component = (\n {\n items,\n initialActiveItemIndex,\n hideThumbnail = false,\n hideNavigation = false,\n hideCounter = false,\n hideMagnifier = false,\n onDelete,\n onClose,\n insets,\n show,\n ...otherProps\n }: FullscreenImageCarouselProps,\n ref: React.Ref<FullscreenImageCarouselRef>\n) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const [currentSlide, setCurrentSlide] = useStateCallback(\n initialActiveItemIndex ?? 0\n );\n const [imagesDimension, setImageDimension] = useState<\n Record<string, ImageDimension>\n >({});\n const [zoom, setZoom] = useState(1);\n const [startX, setStartX] = useState<number | undefined>();\n const [endX, setEndX] = useState<number | undefined>();\n const containerRef = useRef<HTMLDivElement>(null);\n const thumbnailRefs = useRef<(HTMLDivElement | null)[]>([]);\n const zoomRefs = useRef<(ReactZoomPanPinchContentRef | null)[]>([]);\n const imageRef = useRef<HTMLDivElement>(null);\n const topActionButtonsRef = useRef<HTMLDivElement>(null);\n const prevArrowButtonRef = useRef<HTMLButtonElement>(null);\n const nextArrowButtonRef = useRef<HTMLButtonElement>(null);\n const thumbnailContainerRef = useRef<HTMLDivElement>(null);\n const diff = startX && endX ? startX - endX : 0;\n const currentItem = items[currentSlide];\n const hasAnyItemLabel = items.some(\n (item) => isCustomItem(item) && !!item.itemLabel?.trim()\n );\n const carouselItemNoun = hasAnyItemLabel ? \"item\" : \"image\";\n const hasFileInfo = useMemo(\n () =>\n items.some(\n (item) => item.fileName?.trim() || item.fileSize?.trim()\n ),\n [items]\n );\n\n useApplyStyle(topActionButtonsRef, {\n [styles.tokens.topActionButtons.insetTop]: formatUnitValue(\n insets?.top,\n \"px\"\n ),\n [styles.tokens.topActionButtons.insetLeft]: formatUnitValue(\n insets?.left,\n \"px\"\n ),\n [styles.tokens.topActionButtons.insetRight]: formatUnitValue(\n insets?.right,\n \"px\"\n ),\n });\n\n useApplyStyle(prevArrowButtonRef, {\n [styles.tokens.arrowButton.insetLeft]: formatUnitValue(\n insets?.left,\n \"px\"\n ),\n });\n\n useApplyStyle(nextArrowButtonRef, {\n [styles.tokens.arrowButton.insetRight]: formatUnitValue(\n insets?.right,\n \"px\"\n ),\n });\n\n useApplyStyle(thumbnailContainerRef, {\n [styles.tokens.thumbnailContainer.insetBottom]: formatUnitValue(\n insets?.bottom,\n \"px\"\n ),\n });\n\n const getItemAriaLabel = useCallback(\n (index: number) => {\n const item = items[index];\n const itemTypeLabel = hasAnyItemLabel ? \"Item\" : \"Image\";\n const prefix = isCustomItem(item)\n ? item.itemLabel?.trim() || \"\"\n : item.alt?.trim() || \"\";\n const positionLabel = `${itemTypeLabel} ${index + 1} of ${\n items.length\n }.`;\n\n return prefix ? `${prefix}. ${positionLabel}` : positionLabel;\n },\n [items, hasAnyItemLabel]\n );\n\n useImperativeHandle<FullscreenImageCarouselRef, FullscreenImageCarouselRef>(\n ref,\n () => ({\n currentItemIndex: currentSlide,\n setCurrentItem: goToSlide,\n goToPrevItem: goToPrevSlide,\n goToNextItem: goToNextSlide,\n })\n );\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEventListener(\"keydown\", handleKeyDown, \"document\");\n\n useEffect(() => {\n if (show) {\n imageRef.current?.focus();\n }\n }, [show]);\n\n useEffect(() => {\n if (items.length === 0) {\n setCurrentSlide(0);\n return;\n }\n\n if (currentSlide > items.length - 1) {\n setCurrentSlide(items.length - 1);\n }\n }, [currentSlide, items.length, setCurrentSlide]);\n\n useEffect(() => {\n thumbnailRefs.current?.[currentSlide]?.scrollIntoView({\n behavior: \"smooth\",\n inline: \"center\",\n });\n setZoom(1);\n }, [currentSlide]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleTouchStart = (e: React.TouchEvent) => {\n if (zoom <= 1) setStartX(e.touches[0].clientX);\n };\n\n const handleTouchMove = (e: React.TouchEvent) => {\n if (!startX || zoom > 1) return;\n setEndX(e.touches[0].clientX);\n };\n\n const handleTouchEnd = () => {\n if (!containerRef.current) return;\n if (Math.abs(diff) > containerRef.current.offsetWidth / 3) {\n if (diff > 0) {\n goToNextSlide();\n } else {\n goToPrevSlide();\n }\n }\n setStartX(undefined);\n setEndX(undefined);\n };\n\n const handleZoom = (e: ReactZoomPanPinchRef) => {\n setZoom(e.state.scale);\n };\n\n const handleDelete = () => {\n if (currentItem && onDelete) {\n onDelete(currentItem, currentSlide);\n }\n };\n\n function handleKeyDown(e: KeyboardEvent) {\n if (e.key === \"ArrowRight\") {\n goToNextSlide();\n } else if (e.key === \"ArrowLeft\") {\n goToPrevSlide();\n } else if (e.key === \"Escape\") {\n onClose?.();\n }\n }\n\n const handleMagnifier = () => {\n if (zoom === 1) {\n const zoomRatio = getZoomRatio();\n zoomRefs.current?.[currentSlide]?.centerView(zoomRatio);\n setZoom(zoomRatio ?? 1);\n } else {\n setZoom(1);\n zoomRefs.current?.[currentSlide]?.resetTransform();\n }\n };\n\n const setDimension = ({\n src,\n height,\n width,\n }: {\n src: string;\n height: number;\n width: number;\n }) => {\n setImageDimension((oldState) => {\n return { ...oldState, [src]: { height, width } };\n });\n };\n\n const getZoomRatio = () => {\n if (!currentItem || isCustomItem(currentItem)) {\n return;\n }\n\n const imageDimension = imagesDimension[currentItem.src];\n\n if (containerRef.current && !!imageDimension) {\n const { clientHeight, clientWidth } = containerRef.current;\n const { width, height } = imageDimension;\n const isSmallImg = width < clientWidth && height < clientHeight;\n\n const isImgLandscapeRelativeToDevice =\n height / width < clientHeight / clientWidth;\n\n if (isSmallImg) {\n return isImgLandscapeRelativeToDevice\n ? clientWidth / width\n : clientHeight / height;\n }\n\n return isImgLandscapeRelativeToDevice\n ? clientHeight / (height / (width / clientWidth))\n : clientWidth / (width / (height / clientHeight));\n }\n };\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const goToPrevSlide = () => {\n zoomRefs.current?.[currentSlide]?.resetTransform();\n setCurrentSlide(\n (prev) => (prev === 0 ? items.length - 1 : prev - 1),\n (slide) => {\n clearAnnouncer(\"polite\");\n announce(getItemAriaLabel(slide), \"polite\");\n }\n );\n };\n\n const goToNextSlide = () => {\n zoomRefs.current?.[currentSlide]?.resetTransform();\n setCurrentSlide(\n (prev) => (prev === items.length - 1 ? 0 : prev + 1),\n (slide) => {\n clearAnnouncer(\"polite\");\n announce(getItemAriaLabel(slide), \"polite\");\n }\n );\n };\n\n const goToSlide = (index: number) => {\n zoomRefs.current?.[currentSlide]?.resetTransform();\n setCurrentSlide(index);\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderSlides = () => {\n return (\n <div\n className={styles.imageGallerySlides}\n style={{\n transform: `translateX(calc(${\n -currentSlide * 100\n }% - ${diff}px))`,\n }}\n >\n {items.map((item, index) => {\n const isActive = index === currentSlide;\n const isActiveOrAdjacent =\n Math.abs(index - currentSlide) <= 1 ||\n (currentSlide === 0 && index === items.length - 1) ||\n (currentSlide === items.length - 1 && index === 0);\n\n return (\n <div\n className={styles.imageGallerySlide}\n key={index}\n data-testid=\"slide-item\"\n >\n <div\n className={styles.focusableImageRegion}\n ref={isActive ? imageRef : null}\n tabIndex={isActive ? 0 : -1}\n >\n {isCustomItem(item) ? (\n isActiveOrAdjacent ? (\n item.renderContent()\n ) : (\n <ImagePlaceholder\n className={\n styles.slidePlaceholderImage\n }\n />\n )\n ) : (\n <TransformWrapper\n ref={(el) =>\n (zoomRefs.current[index] = el)\n }\n panning={{\n disabled: zoom <= 1,\n }}\n initialScale={1}\n onZoom={handleZoom}\n onZoomStop={handleZoom}\n onWheel={handleZoom}\n >\n <TransformComponent>\n <StatefulImage\n className={styles.slideImage}\n src={item.src}\n alt={getItemAriaLabel(index)}\n placeholder={\n <ImagePlaceholder\n className={\n styles.slidePlaceholderImage\n }\n />\n }\n fit=\"scale-down\"\n retrieveImageDimension\n setDimension={setDimension}\n />\n </TransformComponent>\n </TransformWrapper>\n )}\n </div>\n </div>\n );\n })}\n </div>\n );\n };\n\n const renderFileInfo = () => {\n const { fileName, fileSize } = currentItem ?? {};\n const trimmedName = fileName?.trim();\n const trimmedSize = fileSize?.trim();\n\n return (\n <div\n className={clsx(\n styles.fileInfoTextWrapper,\n !trimmedSize && styles.fileInfoTextWrapperCentered\n )}\n aria-live=\"polite\"\n aria-atomic=\"true\"\n data-testid=\"file-info-bar\"\n >\n {trimmedName && (\n <Typography.BodyBL\n className={styles.fileInfoFileName}\n weight=\"semibold\"\n data-testid=\"file-info-name\"\n >\n {trimmedName}\n </Typography.BodyBL>\n )}\n {trimmedSize && (\n <Typography.BodyMD\n className={styles.fileInfoFileSize}\n data-testid=\"file-info-size\"\n >\n {trimmedSize}\n </Typography.BodyMD>\n )}\n </div>\n );\n };\n\n const renderThumbnails = () => {\n return (\n <div\n className={styles.thumbnailContainer}\n ref={thumbnailContainerRef}\n aria-hidden=\"true\"\n data-testid=\"thumbnail-container\"\n >\n <div className={styles.thumbnailWrapper}>\n {items.map((item, index) => {\n const src = isCustomItem(item)\n ? item.thumbnailSrc\n : item.thumbnailSrc ?? item.src;\n return (\n <div\n className={styles.thumbnailItemContainer}\n key={index}\n >\n <div\n className={styles.thumbnailItem}\n data-active={index === currentSlide}\n data-testid=\"thumbnail-item\"\n onClick={() => goToSlide(index)}\n ref={(el) =>\n (thumbnailRefs.current[index] = el)\n }\n >\n {src ? (\n <StatefulImage\n className={styles.thumbnailImage}\n src={src}\n alt={`Thumbnail ${index + 1}`}\n fit=\"cover\"\n />\n ) : (\n <ImagePlaceholder\n className={\n styles.slidePlaceholderImage\n }\n />\n )}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n };\n\n return (\n <ModalV2\n {...otherProps}\n data-testid=\"image-carousel-modal\"\n aria-label={hasAnyItemLabel ? \"Carousel\" : \"Image carousel\"}\n show={show}\n disableInitialFocus\n >\n <div className={styles.carouselModalContent}>\n <div className={styles.imageGalleryContainer}>\n <div className={styles.imageGalleryWrapper}>\n <div\n className={styles.imageGallerySwipe}\n ref={containerRef}\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleTouchEnd}\n >\n {renderSlides()}\n </div>\n\n {!hideNavigation && (\n <>\n <ClickableIcon\n className={clsx(\n styles.iconButton,\n styles.arrowButton,\n styles.arrowButtonLeft\n )}\n ref={prevArrowButtonRef}\n aria-label={`Previous ${carouselItemNoun}`}\n data-testid=\"prev-btn\"\n onClick={goToPrevSlide}\n >\n <ChevronLeftIcon aria-hidden />\n </ClickableIcon>\n <ClickableIcon\n className={clsx(\n styles.iconButton,\n styles.arrowButton,\n styles.arrowButtonRight\n )}\n ref={nextArrowButtonRef}\n aria-label={`Next ${carouselItemNoun}`}\n data-testid=\"forward-btn\"\n onClick={goToNextSlide}\n >\n <ChevronRightIcon aria-hidden />\n </ClickableIcon>\n </>\n )}\n\n {!hideCounter && (\n <div className={styles.boxChip} aria-hidden=\"true\">\n <Typography.BodyXS\n className={styles.chip}\n weight=\"semibold\"\n data-testid=\"carousel-counter\"\n >{`${currentSlide + 1}/${\n items.length\n }`}</Typography.BodyXS>\n </div>\n )}\n </div>\n\n {!hideThumbnail && renderThumbnails()}\n </div>\n <div\n className={styles.topActionButtons}\n ref={topActionButtonsRef}\n data-has-file-info={hasFileInfo}\n >\n {hasFileInfo && renderFileInfo()}\n {!hideMagnifier && !isCustomItem(currentItem) && (\n <ClickableIcon\n className={styles.iconButton}\n aria-label={zoom === 1 ? \"Zoom in\" : \"Zoom out\"}\n onClick={handleMagnifier}\n >\n {zoom === 1 ? (\n <MagnifierPlusIcon aria-hidden />\n ) : (\n <MagnifierMinusIcon aria-hidden />\n )}\n </ClickableIcon>\n )}\n\n {onDelete && (\n <ClickableIcon\n className={clsx(\n styles.iconButton,\n styles.iconButtonError\n )}\n aria-label={`Delete ${\n (isCustomItem(currentItem) &&\n currentItem.itemLabel?.trim()) ||\n \"image\"\n }`}\n data-testid=\"delete-btn\"\n onClick={handleDelete}\n >\n <BinIcon aria-hidden />\n </ClickableIcon>\n )}\n\n <ClickableIcon\n className={styles.iconButton}\n aria-label={\n hasAnyItemLabel\n ? \"Close carousel\"\n : \"Close image carousel\"\n }\n onClick={onClose}\n >\n <CrossIcon aria-hidden />\n </ClickableIcon>\n </div>\n </div>\n </ModalV2>\n );\n};\n\n// @catalog\n/**\n * A fullscreen modal carousel for browsing images and custom media items.\n *\n * Use to present a collection of images or custom content in an overlay with\n * navigation controls, zoom support, and an optional thumbnail strip.\n * The top info bar is rendered only when at least one item provides some file metadata.\n * @keywords carousel, gallery, image, lightbox, media, overlay\n */\nexport const FullscreenImageCarousel = forwardRef<\n FullscreenImageCarouselRef,\n FullscreenImageCarouselProps\n>(Component);\n"],"names":["isCustomItem","item","type","Component","_a","ref","items","initialActiveItemIndex","hideThumbnail","hideNavigation","hideCounter","hideMagnifier","onDelete","onClose","insets","show","otherProps","__rest","currentSlide","setCurrentSlide","useStateCallback","imagesDimension","setImageDimension","useState","zoom","setZoom","startX","setStartX","endX","setEndX","containerRef","useRef","thumbnailRefs","zoomRefs","imageRef","topActionButtonsRef","prevArrowButtonRef","nextArrowButtonRef","thumbnailContainerRef","diff","currentItem","hasAnyItemLabel","some","itemLabel","trim","carouselItemNoun","hasFileInfo","useMemo","fileName","fileSize","_b","useApplyStyle","styles.tokens","topActionButtons","insetTop","formatUnitValue","top","insetLeft","left","insetRight","right","arrowButton","thumbnailContainer","insetBottom","bottom","getItemAriaLabel","useCallback","index","itemTypeLabel","prefix","alt","positionLabel","length","useImperativeHandle","currentItemIndex","setCurrentItem","goToSlide","goToPrevItem","goToPrevSlide","goToNextItem","goToNextSlide","useEventListener","e","key","useEffect","current","focus","scrollIntoView","behavior","inline","handleZoom","state","scale","setDimension","src","height","width","oldState","Object","assign","getZoomRatio","imageDimension","clientHeight","clientWidth","isImgLandscapeRelativeToDevice","resetTransform","prev","slide","clearAnnouncer","announce","_jsx","ModalV2","disableInitialFocus","_jsxs","className","styles.carouselModalContent","children","styles.imageGalleryContainer","styles.imageGalleryWrapper","styles.imageGallerySwipe","onTouchStart","touches","clientX","onTouchMove","onTouchEnd","Math","abs","offsetWidth","undefined","styles.imageGallerySlides","style","transform","map","isActive","isActiveOrAdjacent","styles.imageGallerySlide","styles.focusableImageRegion","tabIndex","renderContent","ImagePlaceholder","styles.slidePlaceholderImage","TransformWrapper","el","panning","disabled","initialScale","onZoom","onZoomStop","onWheel","TransformComponent","StatefulImage","styles.slideImage","placeholder","fit","retrieveImageDimension","_Fragment","ClickableIcon","clsx","styles.iconButton","styles.arrowButton","styles.arrowButtonLeft","onClick","ChevronLeftIcon","styles.arrowButtonRight","ChevronRightIcon","styles.boxChip","Typography","BodyXS","styles.chip","weight","styles.thumbnailContainer","styles.thumbnailWrapper","thumbnailSrc","styles.thumbnailItemContainer","styles.thumbnailItem","styles.thumbnailImage","styles.topActionButtons","trimmedName","trimmedSize","styles.fileInfoTextWrapper","styles.fileInfoTextWrapperCentered","BodyBL","styles.fileInfoFileName","BodyMD","styles.fileInfoFileSize","renderFileInfo","zoomRatio","centerView","_d","_c","MagnifierPlusIcon","MagnifierMinusIcon","styles.iconButtonError","BinIcon","CrossIcon","FullscreenImageCarousel","forwardRef"],"mappings":"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"}
1
+ {"version":3,"file":"fullscreen-image-carousel.js","sources":["../../src/fullscreen-image-carousel/fullscreen-image-carousel.tsx"],"sourcesContent":["import {\n ChevronLeftIcon,\n ChevronRightIcon,\n CrossIcon,\n MagnifierMinusIcon,\n MagnifierPlusIcon,\n} from \"@lifesg/react-icons\";\nimport { BinIcon } from \"@lifesg/react-icons/bin\";\nimport { announce, clearAnnouncer } from \"@react-aria/live-announcer\";\nimport clsx from \"clsx\";\nimport {\n cloneElement,\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type {\n ReactZoomPanPinchContentRef,\n ReactZoomPanPinchRef,\n} from \"react-zoom-pan-pinch\";\nimport { TransformComponent, TransformWrapper } from \"react-zoom-pan-pinch\";\n\nimport { ModalV2 } from \"../modal-v2\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport { useStateCallback } from \"../shared/hooks\";\nimport { ImagePlaceholder } from \"../shared/image-placeholder\";\nimport { formatUnitValue, useApplyStyle } from \"../theme\";\nimport { Typography } from \"../typography\";\nimport { mergeRefs, useEventListener } from \"../util\";\nimport * as styles from \"./fullscreen-image-carousel.styles\";\nimport { StatefulImage } from \"./stateful-image\";\nimport type {\n FullscreenImageCarouselCustomAction,\n FullscreenImageCarouselCustomItemProps,\n FullscreenImageCarouselItemProps,\n FullscreenImageCarouselProps,\n FullscreenImageCarouselRef,\n ImageDimension,\n} from \"./types\";\n\nconst isCustomItem = (\n item: FullscreenImageCarouselItemProps | undefined\n): item is FullscreenImageCarouselCustomItemProps =>\n !!item && item.type === \"custom\";\n\nexport const Component = (\n {\n items,\n initialActiveItemIndex,\n hideThumbnail = false,\n hideNavigation = false,\n hideCounter = false,\n hideMagnifier = false,\n customActions,\n onDelete,\n onClose,\n insets,\n topBarRef,\n show,\n ...otherProps\n }: FullscreenImageCarouselProps,\n ref: React.Ref<FullscreenImageCarouselRef>\n) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const [currentSlide, setCurrentSlide] = useStateCallback(\n initialActiveItemIndex ?? 0\n );\n const [imagesDimension, setImageDimension] = useState<\n Record<string, ImageDimension>\n >({});\n const [zoom, setZoom] = useState(1);\n const [startX, setStartX] = useState<number | undefined>();\n const [endX, setEndX] = useState<number | undefined>();\n const containerRef = useRef<HTMLDivElement>(null);\n const thumbnailRefs = useRef<(HTMLDivElement | null)[]>([]);\n const zoomRefs = useRef<(ReactZoomPanPinchContentRef | null)[]>([]);\n const imageRef = useRef<HTMLDivElement>(null);\n /*\n * The top bar's element is held in state rather than a ref so that its mount\n * causes a render. Overlay keeps its portal target in state and mounts these\n * children, so the layout effect below would otherwise run while a ref was\n * still null and never write the inset custom properties.\n */\n const [topActionButtons, setTopActionButtons] =\n useState<HTMLDivElement | null>(null);\n const topActionButtonsRef = useMemo(\n () => ({ current: topActionButtons }),\n [topActionButtons]\n );\n const mergedTopBarRef = useMemo(\n () => mergeRefs(setTopActionButtons, topBarRef),\n [topBarRef]\n );\n const prevArrowButtonRef = useRef<HTMLButtonElement>(null);\n const nextArrowButtonRef = useRef<HTMLButtonElement>(null);\n const thumbnailContainerRef = useRef<HTMLDivElement>(null);\n const diff = startX && endX ? startX - endX : 0;\n const currentItem = items[currentSlide];\n const resolvedCustomActions =\n currentItem?.customActions ?? customActions ?? [];\n const hasAnyItemLabel = items.some(\n (item) => isCustomItem(item) && !!item.itemLabel?.trim()\n );\n const carouselItemNoun = hasAnyItemLabel ? \"item\" : \"image\";\n const hasFileInfo = useMemo(\n () =>\n items.some(\n (item) => item.fileName?.trim() || item.fileSize?.trim()\n ),\n [items]\n );\n\n useApplyStyle(topActionButtonsRef, {\n [styles.tokens.topActionButtons.insetTop]: formatUnitValue(\n insets?.top,\n \"px\"\n ),\n [styles.tokens.topActionButtons.insetLeft]: formatUnitValue(\n insets?.left,\n \"px\"\n ),\n [styles.tokens.topActionButtons.insetRight]: formatUnitValue(\n insets?.right,\n \"px\"\n ),\n });\n\n useApplyStyle(prevArrowButtonRef, {\n [styles.tokens.arrowButton.insetLeft]: formatUnitValue(\n insets?.left,\n \"px\"\n ),\n });\n\n useApplyStyle(nextArrowButtonRef, {\n [styles.tokens.arrowButton.insetRight]: formatUnitValue(\n insets?.right,\n \"px\"\n ),\n });\n\n useApplyStyle(thumbnailContainerRef, {\n [styles.tokens.thumbnailContainer.insetBottom]: formatUnitValue(\n insets?.bottom,\n \"px\"\n ),\n });\n\n const getItemAriaLabel = useCallback(\n (index: number) => {\n const item = items[index];\n const itemTypeLabel = hasAnyItemLabel ? \"Item\" : \"Image\";\n const prefix = isCustomItem(item)\n ? item.itemLabel?.trim() || \"\"\n : item.alt?.trim() || \"\";\n const positionLabel = `${itemTypeLabel} ${index + 1} of ${\n items.length\n }.`;\n\n return prefix ? `${prefix}. ${positionLabel}` : positionLabel;\n },\n [items, hasAnyItemLabel]\n );\n\n useImperativeHandle<FullscreenImageCarouselRef, FullscreenImageCarouselRef>(\n ref,\n () => ({\n currentItemIndex: currentSlide,\n setCurrentItem: goToSlide,\n goToPrevItem: goToPrevSlide,\n goToNextItem: goToNextSlide,\n })\n );\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEventListener(\"keydown\", handleKeyDown, \"document\");\n\n useEffect(() => {\n if (show) {\n imageRef.current?.focus();\n }\n }, [show]);\n\n useEffect(() => {\n if (items.length === 0) {\n setCurrentSlide(0);\n return;\n }\n\n if (currentSlide > items.length - 1) {\n setCurrentSlide(items.length - 1);\n }\n }, [currentSlide, items.length, setCurrentSlide]);\n\n useEffect(() => {\n thumbnailRefs.current?.[currentSlide]?.scrollIntoView({\n behavior: \"smooth\",\n inline: \"center\",\n });\n setZoom(1);\n }, [currentSlide]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleTouchStart = (e: React.TouchEvent) => {\n if (zoom <= 1) setStartX(e.touches[0].clientX);\n };\n\n const handleTouchMove = (e: React.TouchEvent) => {\n if (!startX || zoom > 1) return;\n setEndX(e.touches[0].clientX);\n };\n\n const handleTouchEnd = () => {\n if (!containerRef.current) return;\n if (Math.abs(diff) > containerRef.current.offsetWidth / 3) {\n if (diff > 0) {\n goToNextSlide();\n } else {\n goToPrevSlide();\n }\n }\n setStartX(undefined);\n setEndX(undefined);\n };\n\n const handleZoom = (e: ReactZoomPanPinchRef) => {\n setZoom(e.state.scale);\n };\n\n const handleDelete = () => {\n if (currentItem && onDelete) {\n onDelete(currentItem, currentSlide);\n }\n };\n\n const handleCustomAction = (\n action: FullscreenImageCarouselCustomAction\n ) => {\n if (currentItem) {\n action.onClick(currentItem, currentSlide);\n }\n };\n\n function handleKeyDown(e: KeyboardEvent) {\n if (e.key === \"ArrowRight\") {\n goToNextSlide();\n } else if (e.key === \"ArrowLeft\") {\n goToPrevSlide();\n } else if (e.key === \"Escape\") {\n onClose?.();\n }\n }\n\n const handleMagnifier = () => {\n if (zoom === 1) {\n const zoomRatio = getZoomRatio();\n zoomRefs.current?.[currentSlide]?.centerView(zoomRatio);\n setZoom(zoomRatio ?? 1);\n } else {\n setZoom(1);\n zoomRefs.current?.[currentSlide]?.resetTransform();\n }\n };\n\n const setDimension = ({\n src,\n height,\n width,\n }: {\n src: string;\n height: number;\n width: number;\n }) => {\n setImageDimension((oldState) => {\n return { ...oldState, [src]: { height, width } };\n });\n };\n\n const getZoomRatio = () => {\n if (!currentItem || isCustomItem(currentItem)) {\n return;\n }\n\n const imageDimension = imagesDimension[currentItem.src];\n\n if (containerRef.current && !!imageDimension) {\n const { clientHeight, clientWidth } = containerRef.current;\n const { width, height } = imageDimension;\n const isSmallImg = width < clientWidth && height < clientHeight;\n\n const isImgLandscapeRelativeToDevice =\n height / width < clientHeight / clientWidth;\n\n if (isSmallImg) {\n return isImgLandscapeRelativeToDevice\n ? clientWidth / width\n : clientHeight / height;\n }\n\n return isImgLandscapeRelativeToDevice\n ? clientHeight / (height / (width / clientWidth))\n : clientWidth / (width / (height / clientHeight));\n }\n };\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const goToPrevSlide = () => {\n zoomRefs.current?.[currentSlide]?.resetTransform();\n setCurrentSlide(\n (prev) => (prev === 0 ? items.length - 1 : prev - 1),\n (slide) => {\n clearAnnouncer(\"polite\");\n announce(getItemAriaLabel(slide), \"polite\");\n }\n );\n };\n\n const goToNextSlide = () => {\n zoomRefs.current?.[currentSlide]?.resetTransform();\n setCurrentSlide(\n (prev) => (prev === items.length - 1 ? 0 : prev + 1),\n (slide) => {\n clearAnnouncer(\"polite\");\n announce(getItemAriaLabel(slide), \"polite\");\n }\n );\n };\n\n const goToSlide = (index: number) => {\n zoomRefs.current?.[currentSlide]?.resetTransform();\n setCurrentSlide(index);\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderSlides = () => {\n return (\n <div\n className={styles.imageGallerySlides}\n style={{\n transform: `translateX(calc(${\n -currentSlide * 100\n }% - ${diff}px))`,\n }}\n >\n {items.map((item, index) => {\n const isActive = index === currentSlide;\n const isActiveOrAdjacent =\n Math.abs(index - currentSlide) <= 1 ||\n (currentSlide === 0 && index === items.length - 1) ||\n (currentSlide === items.length - 1 && index === 0);\n\n return (\n <div\n className={styles.imageGallerySlide}\n key={index}\n data-testid=\"slide-item\"\n >\n <div\n className={styles.focusableImageRegion}\n ref={isActive ? imageRef : null}\n tabIndex={isActive ? 0 : -1}\n >\n {isCustomItem(item) ? (\n isActiveOrAdjacent ? (\n item.renderContent()\n ) : (\n <ImagePlaceholder\n className={\n styles.slidePlaceholderImage\n }\n />\n )\n ) : (\n <TransformWrapper\n ref={(el) =>\n (zoomRefs.current[index] = el)\n }\n panning={{\n disabled: zoom <= 1,\n }}\n initialScale={1}\n onZoom={handleZoom}\n onZoomStop={handleZoom}\n onWheel={handleZoom}\n >\n <TransformComponent>\n <StatefulImage\n className={styles.slideImage}\n src={item.src}\n alt={getItemAriaLabel(index)}\n placeholder={\n <ImagePlaceholder\n className={\n styles.slidePlaceholderImage\n }\n />\n }\n fit=\"scale-down\"\n retrieveImageDimension\n setDimension={setDimension}\n />\n </TransformComponent>\n </TransformWrapper>\n )}\n </div>\n </div>\n );\n })}\n </div>\n );\n };\n\n const renderFileInfo = () => {\n const { fileName, fileSize } = currentItem ?? {};\n const trimmedName = fileName?.trim();\n const trimmedSize = fileSize?.trim();\n\n return (\n <div\n className={clsx(\n styles.fileInfoTextWrapper,\n !trimmedSize && styles.fileInfoTextWrapperCentered\n )}\n aria-live=\"polite\"\n aria-atomic=\"true\"\n data-testid=\"file-info-bar\"\n >\n {trimmedName && (\n <Typography.BodyBL\n className={styles.fileInfoFileName}\n weight=\"semibold\"\n data-testid=\"file-info-name\"\n >\n {trimmedName}\n </Typography.BodyBL>\n )}\n {trimmedSize && (\n <Typography.BodyMD\n className={styles.fileInfoFileSize}\n data-testid=\"file-info-size\"\n >\n {trimmedSize}\n </Typography.BodyMD>\n )}\n </div>\n );\n };\n\n const renderThumbnails = () => {\n return (\n <div\n className={styles.thumbnailContainer}\n ref={thumbnailContainerRef}\n aria-hidden=\"true\"\n data-testid=\"thumbnail-container\"\n >\n <div className={styles.thumbnailWrapper}>\n {items.map((item, index) => {\n const src = isCustomItem(item)\n ? item.thumbnailSrc\n : item.thumbnailSrc ?? item.src;\n return (\n <div\n className={styles.thumbnailItemContainer}\n key={index}\n >\n <div\n className={styles.thumbnailItem}\n data-active={index === currentSlide}\n data-testid=\"thumbnail-item\"\n onClick={() => goToSlide(index)}\n ref={(el) =>\n (thumbnailRefs.current[index] = el)\n }\n >\n {src ? (\n <StatefulImage\n className={styles.thumbnailImage}\n src={src}\n alt={`Thumbnail ${index + 1}`}\n fit=\"cover\"\n />\n ) : (\n <ImagePlaceholder\n className={\n styles.slidePlaceholderImage\n }\n />\n )}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n };\n\n const renderTopActions = () => {\n return (\n <div\n className={styles.topActionButtons}\n ref={mergedTopBarRef}\n data-has-file-info={hasFileInfo}\n >\n {hasFileInfo && renderFileInfo()}\n\n {resolvedCustomActions.map((action, index) => (\n <ClickableIcon\n key={index}\n className={styles.iconButton}\n aria-label={action.ariaLabel}\n data-testid={action[\"data-testid\"]}\n onClick={() => handleCustomAction(action)}\n >\n {cloneElement(action.icon, { \"aria-hidden\": true })}\n </ClickableIcon>\n ))}\n\n {!hideMagnifier && !isCustomItem(currentItem) && (\n <ClickableIcon\n className={styles.iconButton}\n aria-label={zoom === 1 ? \"Zoom in\" : \"Zoom out\"}\n onClick={handleMagnifier}\n >\n {zoom === 1 ? (\n <MagnifierPlusIcon aria-hidden />\n ) : (\n <MagnifierMinusIcon aria-hidden />\n )}\n </ClickableIcon>\n )}\n\n {onDelete && (\n <ClickableIcon\n className={clsx(\n styles.iconButton,\n styles.iconButtonError\n )}\n aria-label={`Delete ${\n (isCustomItem(currentItem) &&\n currentItem.itemLabel?.trim()) ||\n \"image\"\n }`}\n data-testid=\"delete-btn\"\n onClick={handleDelete}\n >\n <BinIcon aria-hidden />\n </ClickableIcon>\n )}\n\n <ClickableIcon\n className={styles.iconButton}\n aria-label={\n hasAnyItemLabel\n ? \"Close carousel\"\n : \"Close image carousel\"\n }\n onClick={onClose}\n >\n <CrossIcon aria-hidden />\n </ClickableIcon>\n </div>\n );\n };\n\n return (\n <ModalV2\n {...otherProps}\n data-testid=\"image-carousel-modal\"\n aria-label={hasAnyItemLabel ? \"Carousel\" : \"Image carousel\"}\n show={show}\n disableInitialFocus\n >\n <div className={styles.carouselModalContent}>\n <div className={styles.imageGalleryContainer}>\n <div className={styles.imageGalleryWrapper}>\n <div\n className={styles.imageGallerySwipe}\n ref={containerRef}\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleTouchEnd}\n >\n {renderSlides()}\n </div>\n\n {!hideNavigation && (\n <>\n <ClickableIcon\n className={clsx(\n styles.iconButton,\n styles.arrowButton,\n styles.arrowButtonLeft\n )}\n ref={prevArrowButtonRef}\n aria-label={`Previous ${carouselItemNoun}`}\n data-testid=\"prev-btn\"\n onClick={goToPrevSlide}\n >\n <ChevronLeftIcon aria-hidden />\n </ClickableIcon>\n <ClickableIcon\n className={clsx(\n styles.iconButton,\n styles.arrowButton,\n styles.arrowButtonRight\n )}\n ref={nextArrowButtonRef}\n aria-label={`Next ${carouselItemNoun}`}\n data-testid=\"forward-btn\"\n onClick={goToNextSlide}\n >\n <ChevronRightIcon aria-hidden />\n </ClickableIcon>\n </>\n )}\n\n {!hideCounter && (\n <div className={styles.boxChip} aria-hidden=\"true\">\n <Typography.BodyXS\n className={styles.chip}\n weight=\"semibold\"\n data-testid=\"carousel-counter\"\n >{`${currentSlide + 1}/${\n items.length\n }`}</Typography.BodyXS>\n </div>\n )}\n </div>\n\n {!hideThumbnail && renderThumbnails()}\n </div>\n {renderTopActions()}\n </div>\n </ModalV2>\n );\n};\n\n// @catalog\n/**\n * A fullscreen modal carousel for browsing images and custom media items.\n *\n * Use to present a collection of images or custom content in an overlay with\n * navigation controls, zoom support, and an optional thumbnail strip.\n * The top info bar is rendered only when at least one item provides some file metadata.\n * @keywords carousel, gallery, image, lightbox, media, overlay\n */\nexport const FullscreenImageCarousel = forwardRef<\n FullscreenImageCarouselRef,\n FullscreenImageCarouselProps\n>(Component);\n"],"names":["isCustomItem","item","type","Component","_a","ref","items","initialActiveItemIndex","hideThumbnail","hideNavigation","hideCounter","hideMagnifier","customActions","onDelete","onClose","insets","topBarRef","show","otherProps","__rest","currentSlide","setCurrentSlide","useStateCallback","imagesDimension","setImageDimension","useState","zoom","setZoom","startX","setStartX","endX","setEndX","containerRef","useRef","thumbnailRefs","zoomRefs","imageRef","topActionButtons","setTopActionButtons","topActionButtonsRef","useMemo","current","mergedTopBarRef","mergeRefs","prevArrowButtonRef","nextArrowButtonRef","thumbnailContainerRef","diff","currentItem","resolvedCustomActions","_c","_b","hasAnyItemLabel","some","itemLabel","trim","carouselItemNoun","hasFileInfo","fileName","fileSize","useApplyStyle","styles.tokens","insetTop","formatUnitValue","top","insetLeft","left","insetRight","right","arrowButton","thumbnailContainer","insetBottom","bottom","getItemAriaLabel","useCallback","index","itemTypeLabel","prefix","alt","positionLabel","length","useImperativeHandle","currentItemIndex","setCurrentItem","goToSlide","goToPrevItem","goToPrevSlide","goToNextItem","goToNextSlide","useEventListener","e","key","useEffect","focus","scrollIntoView","behavior","inline","handleZoom","state","scale","handleDelete","handleMagnifier","zoomRatio","getZoomRatio","centerView","_d","resetTransform","setDimension","src","height","width","oldState","Object","assign","imageDimension","clientHeight","clientWidth","isImgLandscapeRelativeToDevice","prev","slide","clearAnnouncer","announce","renderFileInfo","trimmedName","trimmedSize","_jsxs","className","clsx","styles.fileInfoTextWrapper","styles.fileInfoTextWrapperCentered","children","_jsx","Typography","BodyBL","styles.fileInfoFileName","weight","BodyMD","styles.fileInfoFileSize","ModalV2","disableInitialFocus","styles.carouselModalContent","styles.imageGalleryContainer","styles.imageGalleryWrapper","styles.imageGallerySwipe","onTouchStart","touches","clientX","onTouchMove","onTouchEnd","Math","abs","offsetWidth","undefined","styles.imageGallerySlides","style","transform","map","isActive","isActiveOrAdjacent","styles.imageGallerySlide","styles.focusableImageRegion","tabIndex","renderContent","ImagePlaceholder","styles.slidePlaceholderImage","TransformWrapper","el","panning","disabled","initialScale","onZoom","onZoomStop","onWheel","TransformComponent","StatefulImage","styles.slideImage","placeholder","fit","retrieveImageDimension","_Fragment","ClickableIcon","styles.iconButton","styles.arrowButton","styles.arrowButtonLeft","onClick","ChevronLeftIcon","styles.arrowButtonRight","ChevronRightIcon","styles.boxChip","BodyXS","styles.chip","styles.thumbnailContainer","styles.thumbnailWrapper","thumbnailSrc","styles.thumbnailItemContainer","styles.thumbnailItem","styles.thumbnailImage","styles.topActionButtons","action","ariaLabel","handleCustomAction","cloneElement","icon","MagnifierPlusIcon","MagnifierMinusIcon","styles.iconButtonError","BinIcon","CrossIcon","renderTopActions","FullscreenImageCarousel","forwardRef"],"mappings":"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"}
@@ -17,6 +17,25 @@ export interface FullscreenImageCarouselRef {
17
17
  /** Navigates to the next item, wrapping from the last item to the first. */
18
18
  goToNextItem: () => void;
19
19
  }
20
+ /**
21
+ * Custom button to be rendered in the carousel's top bar.
22
+ */
23
+ export interface FullscreenImageCarouselCustomAction {
24
+ /** Icon element rendered inside the button. */
25
+ icon: JSX.Element;
26
+ /**
27
+ * Accessible name for the button.
28
+ */
29
+ ariaLabel: string;
30
+ /**
31
+ * Called when the action is activated.
32
+ *
33
+ * @param item The item that was active when the action fired.
34
+ * @param index Zero-based index of that item in the `items` array.
35
+ */
36
+ onClick: (item: FullscreenImageCarouselItemProps, index: number) => void;
37
+ "data-testid"?: string | undefined;
38
+ }
20
39
  /**
21
40
  * Props for the `FullscreenImageCarousel`component.
22
41
  */
@@ -54,6 +73,13 @@ export interface FullscreenImageCarouselProps extends Pick<ModalV2Props, "show"
54
73
  * @default false
55
74
  */
56
75
  hideMagnifier?: boolean | undefined;
76
+ /**
77
+ * Additional icon buttons rendered in the top bar, positioned before the
78
+ * default buttons. Applies to every item.
79
+ *
80
+ * An item's own `customActions` replaces this list for that item.
81
+ */
82
+ customActions?: FullscreenImageCarouselCustomAction[] | undefined;
57
83
  /**
58
84
  * Called when the delete button is activated for the current item.
59
85
  *
@@ -68,6 +94,10 @@ export interface FullscreenImageCarouselProps extends Pick<ModalV2Props, "show"
68
94
  * of the viewport and avoid overlap with device UI elements.
69
95
  */
70
96
  insets?: Insets | undefined;
97
+ /**
98
+ * Ref to the top bar element, which holds the file info and the action buttons.
99
+ */
100
+ topBarRef?: React.Ref<HTMLDivElement> | undefined;
71
101
  }
72
102
  interface FullscreenImageCarouselBaseItemProps {
73
103
  /**
@@ -79,6 +109,13 @@ interface FullscreenImageCarouselBaseItemProps {
79
109
  * info bar (e.g. "2.4 MB").
80
110
  */
81
111
  fileSize?: string | undefined;
112
+ /**
113
+ * Replaces the component-level `customActions` while this item is active.
114
+ *
115
+ * Leave `undefined` to inherit the component-level list. Pass `[]` to
116
+ * render no custom actions for this item.
117
+ */
118
+ customActions?: FullscreenImageCarouselCustomAction[] | undefined;
82
119
  }
83
120
  /**
84
121
  * A standard image item rendered inside the carousel slide.
package/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export{Accordion}from"./accordion/accordion.js";export{Alert}from"./alert/alert.js";export{LoadingDots}from"./animations/loading-dots/loading-dots.js";export{LoadingDotsSpinner}from"./animations/loading-dots-spinner/loading-dots-spinner.js";export{LoadingSpinner}from"./animations/loading-spinner/loading-spinner.js";export{ThemedLoadingSpinner}from"./animations/themed-loading-spinner/themed-loading-spinner.js";export{Avatar}from"./avatar/avatar.js";export{Badge}from"./badge/badge.js";export{BoxContainer}from"./box-container/box-container.js";export{Breadcrumb}from"./breadcrumb/breadcrumb.js";export{Button}from"./button/button.js";export{Calendar}from"./calendar/calendar.js";export{Card}from"./card/card.js";export{Checkbox}from"./checkbox/checkbox.js";export{CountdownTimer}from"./countdown-timer/countdown-timer.js";export{DashedBorder}from"./dashed-border/dashed-border.js";export{DataTable}from"./data-table/data-table.js";export{DateInput}from"./date-input/date-input.js";export{DateNavigator}from"./date-navigator/date-navigator.js";export{DateRangeInput}from"./date-range-input/date-range-input.js";export{Divider}from"./divider/divider.js";export{Drawer}from"./drawer/drawer.js";export{ESignature}from"./e-signature/e-signature.js";export{ErrorDisplay}from"./error-display/error-display.js";export{ErrorDisplayHelper}from"./error-display/helper.js";export{FeedbackRating}from"./feedback-rating/feedback-rating.js";export{FileDownload}from"./file-download/file-download.js";export{FileUpload}from"./file-upload/file-upload.js";export{Filter}from"./filter/filter.js";export{Footer}from"./footer/footer.js";export{Form}from"./form/index.js";export{Component,FullscreenImageCarousel}from"./fullscreen-image-carousel/fullscreen-image-carousel.js";export{HistogramSlider}from"./histogram-slider/histogram-slider.js";export{ImageButton}from"./image-button/image-button.js";export{Input}from"./input/input.js";export{InputGroup}from"./input-group/input-group.js";export{InputMultiSelect}from"./input-multi-select/input-multi-select.js";export{InputNestedMultiSelect}from"./input-nested-multi-select/input-nested-multi-select.js";export{InputNestedSelect}from"./input-nested-select/input-nested-select.js";export{InputRangeSelect}from"./input-range-select/input-range-select.js";export{InputRangeSlider}from"./input-range-slider/input-range-slider.js";export{InputSelect}from"./input-select/input-select.js";export{InputSlider}from"./input-slider/input-slider.js";export{Textarea}from"./input-textarea/textarea.js";export{LanguageSwitcher}from"./language-switcher/language-switcher.js";export{Layout}from"./layout/index.js";export{LinkList}from"./link-list/link-list.js";export{Markup}from"./markup/markup.js";export{MaskedInput}from"./masked-input/masked-input.js";export{Masthead}from"./masthead/masthead.js";export{Menu,MenuTrigger}from"./menu/menu.js";export{Modal}from"./modal/index.js";export{ModalV2}from"./modal-v2/modal-v2.js";export{Navbar}from"./navbar/navbar.js";export{NBComponent,NotificationBanner}from"./notification-banner/notification-banner.js";export{withNotificationBanner}from"./notification-banner/notification-banner-hoc.js";export{OtpInput}from"./otp-input/otp-input.js";export{Overlay}from"./overlay/overlay.js";export{Pagination}from"./pagination/pagination.js";export{PhoneNumberInput}from"./phone-number-input/phone-number-input.js";export{Pill}from"./pill/pill.js";export{Popover}from"./popover/popover.js";export{PopoverInline}from"./popover/popover-inline/popover-inline.js";export{PopoverTrigger}from"./popover/popover-trigger.js";export{PredictiveTextInput}from"./predictive-text-input/predictive-text-input.js";export{ProgressIndicator}from"./progress-indicator/progress-indicator.js";export{RadioButton}from"./radio-button/radio-button.js";export{SelectHistogram}from"./select-histogram/select-histogram.js";export{Sidenav}from"./sidenav/sidenav.js";export{SingpassButton}from"./singpass-button/singpass-button.js";export{SmartAppBanner}from"./smart-app-banner/smart-app-banner.js";export{Tab}from"./tab/tab.js";export{Table}from"./table/table.js";export{Tag}from"./tag/tag.js";export{TextList}from"./text-list/index.js";export{ThemeProvider}from"./theme/theme-provider/index.js";export{useInheritedThemeScope,useTheme}from"./theme/theme-provider/hooks.js";export{Border,BorderStyle,BorderThickness}from"./theme/tokens/border.js";export{Breakpoint}from"./theme/tokens/breakpoint.js";export{Colour,PrimitiveColours,SemanticColours}from"./theme/tokens/colour.js";export{ComponentToken}from"./theme/tokens/component.js";export{Font,FontSpec}from"./theme/tokens/font.js";export{MediaQuery}from"./theme/tokens/media-query.js";export{Motion}from"./theme/tokens/motion.js";export{Radius}from"./theme/tokens/radius.js";export{Shadow}from"./theme/tokens/shadow.js";export{Spacing}from"./theme/tokens/spacing.js";export{THEME_TYPES}from"./theme/types.js";export{formatUnitValue,parsePxOrRemValue}from"./theme/utils/css-variable.js";export{useApplyStyle}from"./theme/utils/use-apply-styles.js";export{useDesignToken}from"./theme/utils/use-design-token.js";export{useMaxWidthMediaQuery,useMediaQuery,useMinWidthMediaQuery,useResolvedBreakpointToken}from"./theme/utils/use-media-query.js";export{TimeRangePicker}from"./time-range-picker/time-range-picker.js";export{TimeSlotBar}from"./time-slot-bar/time-slot-bar.js";export{TimeSlotBarWeek}from"./time-slot-bar-week/time-slot-bar-week.js";export{TimeSlotWeekView}from"./time-slot-week-view/time-slot-week-view.js";export{Timeline}from"./timeline/timeline.js";export{Timepicker}from"./timepicker/timepicker.js";export{TimeTable}from"./timetable/timetable.js";export{Toast}from"./toast/toast.js";export{Toggle}from"./toggle/toggle.js";export{Typography}from"./typography/index.js";export{UneditableSection}from"./uneditable-section/index.js";export{UnitNumberInput}from"./unit-number/unit-number-input.js";
1
+ export{Accordion}from"./accordion/accordion.js";export{Alert}from"./alert/alert.js";export{LoadingDots}from"./animations/loading-dots/loading-dots.js";export{LoadingDotsSpinner}from"./animations/loading-dots-spinner/loading-dots-spinner.js";export{LoadingSpinner}from"./animations/loading-spinner/loading-spinner.js";export{ThemedLoadingSpinner}from"./animations/themed-loading-spinner/themed-loading-spinner.js";export{Avatar}from"./avatar/avatar.js";export{Badge}from"./badge/badge.js";export{BoxContainer}from"./box-container/box-container.js";export{Breadcrumb}from"./breadcrumb/breadcrumb.js";export{Button}from"./button/button.js";export{Calendar}from"./calendar/calendar.js";export{Card}from"./card/card.js";export{Checkbox}from"./checkbox/checkbox.js";export{CountdownTimer}from"./countdown-timer/countdown-timer.js";export{DashedBorder}from"./dashed-border/dashed-border.js";export{DataTable}from"./data-table/data-table.js";export{DateInput}from"./date-input/date-input.js";export{DateNavigator}from"./date-navigator/date-navigator.js";export{DateRangeInput}from"./date-range-input/date-range-input.js";export{Divider}from"./divider/divider.js";export{Drawer}from"./drawer/drawer.js";export{ESignature}from"./e-signature/e-signature.js";export{ErrorDisplay}from"./error-display/error-display.js";export{ErrorDisplayHelper}from"./error-display/helper.js";export{FeedbackRating}from"./feedback-rating/feedback-rating.js";export{FileDownload}from"./file-download/file-download.js";export{FileUpload}from"./file-upload/file-upload.js";export{Filter}from"./filter/filter.js";export{Footer}from"./footer/footer.js";export{Form}from"./form/index.js";export{Component,FullscreenImageCarousel}from"./fullscreen-image-carousel/fullscreen-image-carousel.js";export{HistogramSlider}from"./histogram-slider/histogram-slider.js";export{ImageButton}from"./image-button/image-button.js";export{Input}from"./input/input.js";export{InputGroup}from"./input-group/input-group.js";export{InputMultiSelect}from"./input-multi-select/input-multi-select.js";export{InputNestedMultiSelect}from"./input-nested-multi-select/input-nested-multi-select.js";export{InputNestedSelect}from"./input-nested-select/input-nested-select.js";export{InputRangeSelect}from"./input-range-select/input-range-select.js";export{InputRangeSlider}from"./input-range-slider/input-range-slider.js";export{InputSelect}from"./input-select/input-select.js";export{InputSlider}from"./input-slider/input-slider.js";export{Textarea}from"./input-textarea/textarea.js";export{LanguageSwitcher}from"./language-switcher/language-switcher.js";export{Layout}from"./layout/index.js";export{LinkList}from"./link-list/link-list.js";export{Markup}from"./markup/markup.js";export{MaskedInput}from"./masked-input/masked-input.js";export{Masthead}from"./masthead/masthead.js";export{Menu,MenuTrigger}from"./menu/menu.js";export{Modal}from"./modal/index.js";export{ModalV2}from"./modal-v2/modal-v2.js";export{Navbar}from"./navbar/navbar.js";export{NBComponent,NotificationBanner}from"./notification-banner/notification-banner.js";export{withNotificationBanner}from"./notification-banner/notification-banner-hoc.js";export{OtpInput}from"./otp-input/otp-input.js";export{Overlay}from"./overlay/overlay.js";export{Pagination}from"./pagination/pagination.js";export{PhoneNumberInput}from"./phone-number-input/phone-number-input.js";export{Pill}from"./pill/pill.js";export{Popover}from"./popover/popover.js";export{PopoverInline}from"./popover/popover-inline/popover-inline.js";export{PopoverTrigger}from"./popover/popover-trigger.js";export{PredictiveTextInput}from"./predictive-text-input/predictive-text-input.js";export{ProgressIndicator}from"./progress-indicator/progress-indicator.js";export{RadioButton}from"./radio-button/radio-button.js";export{SelectHistogram}from"./select-histogram/select-histogram.js";export{Sidenav}from"./sidenav/sidenav.js";export{SingpassButton}from"./singpass-button/singpass-button.js";export{SmartAppBanner}from"./smart-app-banner/smart-app-banner.js";export{Tab}from"./tab/tab.js";export{Table}from"./table/table.js";export{Tag}from"./tag/tag.js";export{TextList}from"./text-list/index.js";export{ThemeProvider}from"./theme/theme-provider/index.js";export{useInheritedThemeScope,useTheme}from"./theme/theme-provider/hooks.js";export{Border,BorderStyle,BorderThickness}from"./theme/tokens/border.js";export{Breakpoint}from"./theme/tokens/breakpoint.js";export{Colour,PrimitiveColours,SemanticColours}from"./theme/tokens/colour.js";export{ComponentToken}from"./theme/tokens/component.js";export{Font,FontSpec}from"./theme/tokens/font.js";export{MediaQuery}from"./theme/tokens/media-query.js";export{Motion}from"./theme/tokens/motion.js";export{Radius}from"./theme/tokens/radius.js";export{Shadow}from"./theme/tokens/shadow.js";export{Spacing}from"./theme/tokens/spacing.js";export{THEME_FONT_PRESETS,THEME_TYPES}from"./theme/types.js";export{formatUnitValue,parsePxOrRemValue}from"./theme/utils/css-variable.js";export{useApplyStyle}from"./theme/utils/use-apply-styles.js";export{useDesignToken}from"./theme/utils/use-design-token.js";export{useMaxWidthMediaQuery,useMediaQuery,useMinWidthMediaQuery,useResolvedBreakpointToken}from"./theme/utils/use-media-query.js";export{TimeRangePicker}from"./time-range-picker/time-range-picker.js";export{TimeSlotBar}from"./time-slot-bar/time-slot-bar.js";export{TimeSlotBarWeek}from"./time-slot-bar-week/time-slot-bar-week.js";export{TimeSlotWeekView}from"./time-slot-week-view/time-slot-week-view.js";export{Timeline}from"./timeline/timeline.js";export{Timepicker}from"./timepicker/timepicker.js";export{TimeTable}from"./timetable/timetable.js";export{Toast}from"./toast/toast.js";export{Toggle}from"./toggle/toggle.js";export{Typography}from"./typography/index.js";export{UneditableSection}from"./uneditable-section/index.js";export{UnitNumberInput}from"./unit-number/unit-number-input.js";
2
2
  //# sourceMappingURL=index.js.map
@@ -1,2 +1,2 @@
1
- import{jsx as e}from"react/jsx-runtime";import"./sgds-day.css";import"./sgds-night.css";import t from"clsx";import{memo as s,useEffect as m}from"react";import"../theme/theme-provider/index.js";import{useTheme as o}from"../theme/theme-provider/hooks.js";import"../theme/tokens/border.js";import"../theme/tokens/colour.js";import"../theme/tokens/font.js";import"../theme/tokens/media-query.js";import"../util/calendar-helper.js";import"../external/dayjs/dayjs.min.js";import"../util/simple-id-generator.js";import"../util/string-helper.js";import"@react-aria/live-announcer";import"../theme/utils/use-media-query.js";import{wrapper as r,wrapperStretch as d}from"./masthead.styles.js";const i=s((({stretch:s=!1})=>{const{mode:i}=o(),p="dark"===i;m((()=>{l()||h()}),[]),m((()=>{p?document.documentElement.classList.add(c):document.documentElement.classList.remove(c)}),[p]);const l=()=>document.getElementById(n),h=()=>{if(!document.getElementById(n)){const e=document.createElement("script");e.id=n,e.type="module",e.src=a,document.head.appendChild(e)}};return e("div",{className:t(r,s&&d),dangerouslySetInnerHTML:{__html:"<sgds-masthead></sgds-masthead>"}})})),n="lifesg-ds-masthead-script",a="https://cdn.jsdelivr.net/npm/@govtechsg/sgds-web-component@3/components/Masthead/index.umd.js",c="sgds-night-theme";export{i as Masthead};
1
+ import{jsx as e}from"react/jsx-runtime";import"./sgds-day.css";import"./sgds-night.css";import t from"clsx";import{memo as s,useEffect as m}from"react";import"../theme/theme-provider/index.js";import{useTheme as r}from"../theme/theme-provider/hooks.js";import"../theme/tokens/border.js";import"../theme/tokens/colour.js";import"../theme/tokens/font.js";import"../theme/tokens/media-query.js";import"../util/calendar-helper.js";import"../external/dayjs/dayjs.min.js";import"../util/simple-id-generator.js";import"../util/string-helper.js";import"@react-aria/live-announcer";import"../theme/utils/use-media-query.js";import{wrapper as o,wrapperStretch as i}from"./masthead.styles.js";const n=s((({stretch:s=!1})=>{const{mode:n}=r(),a="dark"===n;m((()=>{import("@govtechsg/sgds-web-component/components/Masthead/index.js")}),[]),m((()=>{a?document.documentElement.classList.add(d):document.documentElement.classList.remove(d)}),[a]);return e("div",{className:t(o,s&&i),dangerouslySetInnerHTML:{__html:"<sgds-masthead></sgds-masthead>"}})})),d="sgds-night-theme";export{n as Masthead};
2
2
  //# sourceMappingURL=masthead.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"masthead.js","sources":["../../src/masthead/masthead.tsx"],"sourcesContent":["import \"@govtechsg/sgds-web-component/themes/day.css\";\nimport \"@govtechsg/sgds-web-component/themes/night.css\";\n\nimport clsx from \"clsx\";\nimport { memo, useEffect } from \"react\";\n\nimport { useTheme } from \"../theme\";\nimport * as styles from \"./masthead.styles\";\nimport type { MastheadProps } from \"./types\";\n\nconst MastheadComponent = ({ stretch = false }: MastheadProps): JSX.Element => {\n const { mode } = useTheme();\n const isDarkMode = mode === \"dark\";\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n if (!doAssetsExist()) {\n addAssets();\n }\n }, []);\n\n useEffect(() => {\n // SGDS dark mode only takes effect when this class is set on the :root element\n if (isDarkMode) {\n document.documentElement.classList.add(SGDS_THEME_NIGHT_CLASSNAME);\n } else {\n document.documentElement.classList.remove(\n SGDS_THEME_NIGHT_CLASSNAME\n );\n }\n }, [isDarkMode]);\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const doAssetsExist = () => {\n return document.getElementById(SCRIPT_ID);\n };\n\n const addAssets = () => {\n if (!document.getElementById(SCRIPT_ID)) {\n const script = document.createElement(\"script\");\n script.id = SCRIPT_ID;\n script.type = \"module\";\n script.src = SCRIPT_SRC;\n\n document.head.appendChild(script);\n }\n };\n\n const createContent = () => {\n /**\n * Note: Had to use this method because we had to create a\n * custom type to handle Web Components (refer to this guide\n * https://blog.devgenius.io/how-to-use-web-components-in-react-54c951399bfd)\n * But we are having troubles exporting the custom type definition\n * via rollup\n */\n return { __html: \"<sgds-masthead></sgds-masthead>\" };\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n\n return (\n <div\n className={clsx(styles.wrapper, stretch && styles.wrapperStretch)}\n dangerouslySetInnerHTML={createContent()}\n />\n );\n};\n\n// @catalog\n/**\n * Displays the Singapore Government Design System (SGDS) masthead banner.\n *\n * Use `Masthead` at the top of government digital services to meet the SGDS\n * masthead requirement.\n * @keywords banner, branding, compliance, government, SGDS\n */\nexport const Masthead = memo(MastheadComponent);\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\nconst SCRIPT_ID = \"lifesg-ds-masthead-script\";\nconst SCRIPT_SRC =\n \"https://cdn.jsdelivr.net/npm/@govtechsg/sgds-web-component@3/components/Masthead/index.umd.js\";\nconst SGDS_THEME_NIGHT_CLASSNAME = \"sgds-night-theme\";\n"],"names":["Masthead","memo","stretch","mode","useTheme","isDarkMode","useEffect","doAssetsExist","addAssets","document","documentElement","classList","add","SGDS_THEME_NIGHT_CLASSNAME","remove","getElementById","SCRIPT_ID","script","createElement","id","type","src","SCRIPT_SRC","head","appendChild","_jsx","className","clsx","styles.wrapper","styles.wrapperStretch","dangerouslySetInnerHTML","__html"],"mappings":"wsBAUA,MAyEaA,EAAWC,GAzEE,EAAGC,WAAU,MACnC,MAAMC,KAAEA,GAASC,IACXC,EAAsB,SAATF,EAKnBG,GAAU,KACDC,KACDC,GACJ,GACD,IAEHF,GAAU,KAEFD,EACAI,SAASC,gBAAgBC,UAAUC,IAAIC,GAEvCJ,SAASC,gBAAgBC,UAAUG,OAC/BD,EAER,GACD,CAACR,IAKJ,MAAME,EAAgB,IACXE,SAASM,eAAeC,GAG7BR,EAAY,KACd,IAAKC,SAASM,eAAeC,GAAY,CACrC,MAAMC,EAASR,SAASS,cAAc,UACtCD,EAAOE,GAAKH,EACZC,EAAOG,KAAO,SACdH,EAAOI,IAAMC,EAEbb,SAASc,KAAKC,YAAYP,EAC9B,GAkBJ,OACIQ,SACIC,UAAWC,EAAKC,EAAgB1B,GAAW2B,GAC3CC,wBAVG,CAAEC,OAAQ,oCAWf,IAiBJf,EAAY,4BACZM,EACF,gGACET,EAA6B"}
1
+ {"version":3,"file":"masthead.js","sources":["../../src/masthead/masthead.tsx"],"sourcesContent":["import \"@govtechsg/sgds-web-component/themes/day.css\";\nimport \"@govtechsg/sgds-web-component/themes/night.css\";\n\nimport clsx from \"clsx\";\nimport { memo, useEffect } from \"react\";\n\nimport { useTheme } from \"../theme\";\nimport * as styles from \"./masthead.styles\";\nimport type { MastheadProps } from \"./types\";\n\nconst MastheadComponent = ({ stretch = false }: MastheadProps): JSX.Element => {\n const { mode } = useTheme();\n const isDarkMode = mode === \"dark\";\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n import(\"@govtechsg/sgds-web-component/components/Masthead/index.js\");\n }, []);\n\n useEffect(() => {\n // SGDS dark mode only takes effect when this class is set on the :root element\n if (isDarkMode) {\n document.documentElement.classList.add(SGDS_THEME_NIGHT_CLASSNAME);\n } else {\n document.documentElement.classList.remove(\n SGDS_THEME_NIGHT_CLASSNAME\n );\n }\n }, [isDarkMode]);\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const createContent = () => {\n /**\n * Note: Had to use this method because we had to create a\n * custom type to handle Web Components (refer to this guide\n * https://blog.devgenius.io/how-to-use-web-components-in-react-54c951399bfd)\n * But we are having troubles exporting the custom type definition\n * via rollup\n */\n return { __html: \"<sgds-masthead></sgds-masthead>\" };\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n\n return (\n <div\n className={clsx(styles.wrapper, stretch && styles.wrapperStretch)}\n dangerouslySetInnerHTML={createContent()}\n />\n );\n};\n\n// @catalog\n/**\n * Displays the Singapore Government Design System (SGDS) masthead banner.\n *\n * Use `Masthead` at the top of government digital services to meet the SGDS\n * masthead requirement.\n * @keywords banner, branding, compliance, government, SGDS\n */\nexport const Masthead = memo(MastheadComponent);\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\nconst SGDS_THEME_NIGHT_CLASSNAME = \"sgds-night-theme\";\n"],"names":["Masthead","memo","stretch","mode","useTheme","isDarkMode","useEffect","import","document","documentElement","classList","add","SGDS_THEME_NIGHT_CLASSNAME","remove","_jsx","className","clsx","styles.wrapper","styles.wrapperStretch","dangerouslySetInnerHTML","__html"],"mappings":"wsBAUA,MAwDaA,EAAWC,GAxDE,EAAGC,WAAU,MACnC,MAAMC,KAAEA,GAASC,IACXC,EAAsB,SAATF,EAKnBG,GAAU,KACNC,OAAO,6DAA6D,GACrE,IAEHD,GAAU,KAEFD,EACAG,SAASC,gBAAgBC,UAAUC,IAAIC,GAEvCJ,SAASC,gBAAgBC,UAAUG,OAC/BD,EAER,GACD,CAACP,IAoBJ,OACIS,SACIC,UAAWC,EAAKC,EAAgBf,GAAWgB,GAC3CC,wBAVG,CAAEC,OAAQ,oCAWf,IAiBJR,EAA6B"}