@lifesg/react-design-system 1.0.0-alpha.21 → 1.0.0-alpha.22

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.
@@ -1,3 +1,3 @@
1
1
  /// <reference types="react" />
2
2
  import { OtpInputProps } from "./types";
3
- export declare const OtpInput: ({ id, "data-testid": dataTestId, className, cooldownDuration, actionButtonProps, errorMessage, numOfInput, onChange, onCooldownStart, onCooldownEnd, ...otherProps }: OtpInputProps) => JSX.Element;
3
+ export declare const OtpInput: ({ id, value, "data-testid": dataTestId, className, cooldownDuration, actionButtonProps, errorMessage, numOfInput, onChange, onCooldownStart, onCooldownEnd, ...otherProps }: OtpInputProps) => JSX.Element;
@@ -4,17 +4,17 @@ export interface OtpInputProps extends React.AriaAttributes {
4
4
  id?: string | undefined;
5
5
  "data-testid"?: string | undefined;
6
6
  className?: string | undefined;
7
- /** The combined value of the Otp inputs */
8
- value?: string | undefined;
7
+ /** The array of input values */
8
+ value?: string[] | undefined;
9
9
  errorMessage?: string | undefined;
10
10
  /** The duration (in seconds) to disable the submit button after a click is made */
11
11
  cooldownDuration: number;
12
12
  /** The props for the submit button */
13
- actionButtonProps: ButtonProps;
13
+ actionButtonProps?: ButtonProps | undefined;
14
14
  /** The number of characters for the Otp */
15
15
  numOfInput: number;
16
- /** Called when one of the input is changed. Returns the combined value of all Otp inputs */
17
- onChange?: ((value: string) => void) | undefined;
16
+ /** Called when one of the input is changed. Returns an array of all the input values */
17
+ onChange?: ((value: string[]) => void) | undefined;
18
18
  /** Called when the cooldown begins */
19
19
  onCooldownStart?: () => void;
20
20
  /** Called when the cooldown ends */
package/overlay/index.js CHANGED
@@ -36,5 +36,5 @@ import{jsx as t}from"react/jsx-runtime";import e,{useState as n,useRef as i,useE
36
36
  `,t.$disableTransition&&(e+=s`
37
37
  transition: none;
38
38
  `),e}}
39
- `,c=({show:d=!1,rootId:s,onOverlayClick:c,children:b,backgroundOpacity:y,backgroundBlur:h=!0,disableTransition:p=!1,enableOverlayClick:v=!1,zIndex:$,id:f})=>{const[g,w]=n(null),[k,x]=n(),T=i(),C=i(null),I=b&&e.cloneElement(b,{ref:C}),O=f?`lifesg-ds-overlay-root-${f}`:"lifesg-ds-overlay-root";o((()=>{if(d){const t=L();if(B(t),!t){const t=setTimeout((()=>{W("add")}),200);return()=>clearTimeout(t)}}else if(!T.current){const t=setTimeout((()=>{W("remove")}),200);return()=>clearTimeout(t)}}),[d]),o((()=>{w(E());const t=L();return B(t),t||z(),()=>{W("remove")}}),[]);const B=t=>{T.current=t,x(t)},E=()=>document&&s?document.getElementById(s):document?document.body:null,L=()=>document.body.classList.contains(m),z=()=>{if(!document.getElementById(u)){const t=document.createElement("style");t.id=u;const e=document.documentElement.clientWidth,n=window.innerWidth-e;t.innerHTML=`\n\t\t\t\t.${m} {\n\t\t\t\t\toverflow: hidden;\n\t\t\t\t\tpadding-right: ${n}px !important;\n\t\t\t\t\t-ms-overflow-style: none;\n\t\t\t\t\tscrollbar-width: none;\n\t\t\t\t}\n\n\t\t\t\t.${m}::-webkit-scrollbar {\n\t\t\t\t\tdisplay: none;\n\t\t\t\t}\n\t\t\t`,document.body.appendChild(t)}},W=t=>{const e=document.body.classList.contains(m);"add"!==t||e?"remove"===t&&e&&document.body.classList.remove(m):document.body.classList.add(m)},j=t=>{t.preventDefault();const e=C.current?.firstChild;e&&e.contains(t.target)||c&&v&&c()};return g?r.createPortal(t(l,{id:O,"data-testid":O,$show:d,zIndex:$,$stacked:k,children:b&&t(a,{"data-testid":"overlay-wrapper",$show:d,$backgroundOpacity:y||(k?.5:.8),$backgroundBlur:h,$disableTransition:p,$enableOverlayClick:v,onClick:j,children:I})}),g):null},u="lifesg-ds-overlay-stylesheet",m="lifesg-ds-overlay-open";export{c as Overlay};
39
+ `,c=({show:d=!1,rootId:s,onOverlayClick:c,children:b,backgroundOpacity:y,backgroundBlur:h=!0,disableTransition:p=!1,enableOverlayClick:v=!1,zIndex:$,id:f})=>{const[g,w]=n(null),[k,x]=n(),T=i(),C=i(null),I=b&&e.cloneElement(b,{ref:C}),O=f?`lifesg-ds-overlay-root-${f}`:"lifesg-ds-overlay-root";o((()=>{if(d){const t=L();if(B(t),!t){const t=setTimeout((()=>{W("add")}),200);return()=>clearTimeout(t)}}else if(!T.current){const t=setTimeout((()=>{W("remove")}),200);return()=>clearTimeout(t)}}),[d]),o((()=>{w(E());const t=L();return B(t),t||z(),()=>{W("remove")}}),[]);const B=t=>{T.current=t,x(t)},E=()=>document&&s?document.getElementById(s):document?document.body:null,L=()=>document.body.classList.contains(m),z=()=>{if(!document.getElementById(u)){const t=document.createElement("style");t.id=u;const e=document.documentElement.clientWidth,n=window.innerWidth-e;t.innerHTML=`\n\t\t\t\t.${m} {\n\t\t\t\t\toverflow: hidden;\n\t\t\t\t\tpadding-right: ${n}px !important;\n\t\t\t\t\t-ms-overflow-style: none;\n\t\t\t\t\tscrollbar-width: none;\n\t\t\t\t}\n\n\t\t\t\t.${m}::-webkit-scrollbar {\n\t\t\t\t\tdisplay: none;\n\t\t\t\t}\n\t\t\t`,document.body.appendChild(t)}},W=t=>{const e=document.body.classList.contains(m);"add"!==t||e?"remove"===t&&e&&document.body.classList.remove(m):document.body.classList.add(m)},j=t=>{const e=C.current?.firstChild;e&&e.contains(t.target)||c&&v&&(t.preventDefault(),c())};return g?r.createPortal(t(l,{id:O,"data-testid":O,$show:d,zIndex:$,$stacked:k,children:b&&t(a,{"data-testid":"overlay-wrapper",$show:d,$backgroundOpacity:y||(k?.5:.8),$backgroundBlur:h,$disableTransition:p,$enableOverlayClick:v,onClick:j,children:I})}),g):null},u="lifesg-ds-overlay-stylesheet",m="lifesg-ds-overlay-open";export{c as Overlay};
40
40
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/overlay/overlay.styles.tsx","../../src/overlay/overlay.tsx"],"sourcesContent":["import styled, { css } from \"styled-components\";\nimport { StyleProps } from \"./types\";\n\nconst getBackdropFilter = (blur: boolean) => {\n let styleString = \"\";\n\n if (blur) {\n styleString += \"blur(10px)\";\n }\n\n return styleString.length > 0 ? styleString : \"none\";\n};\n\nexport const Root = styled.div<StyleProps>`\n position: fixed;\n left: 0;\n top: 0;\n height: 0;\n width: 0;\n visibility: hidden;\n z-index: ${(props) => {\n return props.zIndex || (props.$stacked ? 99999 : 99998);\n }};\n\n ${(props) => {\n if (props.$show) {\n return css`\n height: 100%;\n width: 100vw;\n visibility: visible;\n `;\n }\n }}\n`;\n\nexport const Wrapper = styled.div<StyleProps>`\n position: absolute;\n left: 0;\n top: 0;\n background-color: rgba(5, 1, 1, ${(props) => props.$backgroundOpacity});\n backdrop-filter: ${(props) => getBackdropFilter(props.$backgroundBlur)};\n transition: opacity 200ms ease;\n\n ${(props) => {\n let customStyles = \"\";\n if (props.$show) {\n customStyles += css`\n visibility: visible;\n opacity: 1;\n pointer-events: auto;\n height: 100%;\n width: 100vw;\n `;\n } else {\n customStyles += css`\n visibility: hidden;\n opacity: 0;\n transition-delay: ${props.$disableTransition ? \"0ms\" : \"400ms\"};\n pointer-events: none;\n height: 0;\n width: 0;\n `;\n }\n if (props.$disableTransition) {\n customStyles += css`\n transition: none;\n `;\n }\n\n return customStyles;\n }}\n`;\n","import React, { useEffect, useRef, useState } from \"react\";\nimport ReactDOM from \"react-dom\";\nimport { OverlayProps } from \"./types\";\nimport { Root, Wrapper } from \"./overlay.styles\";\n\nexport const Overlay = ({\n show = false,\n rootId,\n onOverlayClick,\n children,\n backgroundOpacity,\n backgroundBlur = true,\n disableTransition = false,\n enableOverlayClick = false,\n zIndex,\n id,\n}: OverlayProps): JSX.Element | null => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const [rootElement, setRootElement] = useState<HTMLElement | null>(null);\n const [isStacked, _setIsStacked] = useState<boolean>();\n\n const stacked = useRef<boolean>();\n\n const childRef = useRef<HTMLDivElement>(null);\n const childWithRef =\n children && React.cloneElement(children, { ref: childRef });\n\n const overlayRootId = id\n ? `lifesg-ds-overlay-root-${id}`\n : \"lifesg-ds-overlay-root\";\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n if (show) {\n const isStacked = checkIfStacked();\n setStacked(isStacked);\n\n if (!isStacked) {\n const timerId = setTimeout(() => {\n applyBodyStyleClass(\"add\");\n }, 200); // Allow overlay animations to complete\n return () => clearTimeout(timerId);\n }\n } else {\n /**\n * Here we have to used the ref value to know if it is stacked\n * rather than checking for the presence of the overlay class\n * on <body>\n */\n if (!stacked.current) {\n const timerId = setTimeout(() => {\n applyBodyStyleClass(\"remove\");\n }, 200); // Allow overlay animations to complete\n return () => clearTimeout(timerId);\n }\n }\n }, [show]);\n\n useEffect(() => {\n setRootElement(getRootElement());\n\n /**\n * Only add stylesheet for a non-stacked overlay\n */\n const isStacked = checkIfStacked();\n setStacked(isStacked);\n if (!isStacked) addStylesheetForDocumentBody();\n\n return () => {\n applyBodyStyleClass(\"remove\");\n };\n }, []);\n\n // =============================================================================\n // REF FUNCTIONS\n // =============================================================================\n const setStacked = (data: boolean) => {\n stacked.current = data;\n _setIsStacked(data);\n };\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const getRootElement = (): HTMLElement | null => {\n if (document && rootId) {\n return document.getElementById(rootId);\n } else if (document) {\n // If rootId not specified, we'll use body\n return document.body;\n } else {\n return null;\n }\n };\n\n const checkIfStacked = () => {\n /**\n * Check if the body style was altered before. If it was, then this is\n * a stacked overlay\n */\n return document.body.classList.contains(OVERLAY_OPEN_CLASSNAME);\n };\n\n const addStylesheetForDocumentBody = () => {\n /**\n * This stylesheet is to manipulate the <body>. We only add once\n */\n if (!document.getElementById(STYLESHEET_ID)) {\n const overlayStyleSheet = document.createElement(\"style\");\n overlayStyleSheet.id = STYLESHEET_ID;\n\n const documentWidth = document.documentElement.clientWidth;\n const windowWidth = window.innerWidth;\n const scrollBarWidth = windowWidth - documentWidth;\n\n overlayStyleSheet.innerHTML = `\n\t\t\t\t.${OVERLAY_OPEN_CLASSNAME} {\n\t\t\t\t\toverflow: hidden;\n\t\t\t\t\tpadding-right: ${scrollBarWidth}px !important;\n\t\t\t\t\t-ms-overflow-style: none;\n\t\t\t\t\tscrollbar-width: none;\n\t\t\t\t}\n\n\t\t\t\t.${OVERLAY_OPEN_CLASSNAME}::-webkit-scrollbar {\n\t\t\t\t\tdisplay: none;\n\t\t\t\t}\n\t\t\t`;\n\n document.body.appendChild(overlayStyleSheet);\n }\n };\n\n /**\n * This sets the style of <body> to hide the scrollbar\n */\n const applyBodyStyleClass = (action: \"add\" | \"remove\") => {\n const isOverlayStyleClassApplied = document.body.classList.contains(\n OVERLAY_OPEN_CLASSNAME\n );\n\n if (action === \"add\" && !isOverlayStyleClassApplied) {\n document.body.classList.add(OVERLAY_OPEN_CLASSNAME);\n } else if (action === \"remove\" && isOverlayStyleClassApplied) {\n document.body.classList.remove(OVERLAY_OPEN_CLASSNAME);\n }\n };\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleWrapperClick = (event: React.MouseEvent<HTMLDivElement>) => {\n event.preventDefault();\n\n const modal = childRef.current?.firstChild;\n if (modal && (modal as any).contains(event.target)) {\n return;\n } else if (onOverlayClick && enableOverlayClick) {\n onOverlayClick();\n }\n };\n\n // =============================================================================\n // RENDER\n // =============================================================================\n const renderWrapper = () => (\n <Wrapper\n data-testid={\"overlay-wrapper\"}\n $show={show}\n $backgroundOpacity={backgroundOpacity || (isStacked ? 0.5 : 0.8)}\n $backgroundBlur={backgroundBlur}\n $disableTransition={disableTransition}\n $enableOverlayClick={enableOverlayClick}\n onClick={handleWrapperClick}\n >\n {childWithRef}\n </Wrapper>\n );\n\n const renderComponent = () => (\n <Root\n id={overlayRootId}\n data-testid={overlayRootId}\n $show={show}\n zIndex={zIndex}\n $stacked={isStacked}\n >\n {children && renderWrapper()}\n </Root>\n );\n\n return rootElement\n ? ReactDOM.createPortal(renderComponent(), rootElement)\n : null;\n};\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\nconst STYLESHEET_ID = \"lifesg-ds-overlay-stylesheet\";\nconst OVERLAY_OPEN_CLASSNAME = \"lifesg-ds-overlay-open\";\n"],"names":["Root","styled","div","props","zIndex","$stacked","$show","css","Wrapper","$backgroundOpacity","blur","styleString","length","getBackdropFilter","$backgroundBlur","customStyles","$disableTransition","Overlay","show","rootId","onOverlayClick","children","backgroundOpacity","backgroundBlur","disableTransition","enableOverlayClick","id","rootElement","setRootElement","useState","isStacked","_setIsStacked","stacked","useRef","childRef","childWithRef","React","cloneElement","ref","overlayRootId","useEffect","checkIfStacked","setStacked","timerId","setTimeout","applyBodyStyleClass","clearTimeout","current","getRootElement","addStylesheetForDocumentBody","data","document","getElementById","body","classList","contains","OVERLAY_OPEN_CLASSNAME","STYLESHEET_ID","overlayStyleSheet","createElement","documentWidth","documentElement","clientWidth","scrollBarWidth","window","innerWidth","innerHTML","appendChild","action","isOverlayStyleClassApplied","remove","add","handleWrapperClick","event","preventDefault","modal","firstChild","target","ReactDOM","createPortal","_jsx","$enableOverlayClick","onClick"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/overlay/overlay.styles.tsx","../../src/overlay/overlay.tsx"],"sourcesContent":["import styled, { css } from \"styled-components\";\nimport { StyleProps } from \"./types\";\n\nconst getBackdropFilter = (blur: boolean) => {\n let styleString = \"\";\n\n if (blur) {\n styleString += \"blur(10px)\";\n }\n\n return styleString.length > 0 ? styleString : \"none\";\n};\n\nexport const Root = styled.div<StyleProps>`\n position: fixed;\n left: 0;\n top: 0;\n height: 0;\n width: 0;\n visibility: hidden;\n z-index: ${(props) => {\n return props.zIndex || (props.$stacked ? 99999 : 99998);\n }};\n\n ${(props) => {\n if (props.$show) {\n return css`\n height: 100%;\n width: 100vw;\n visibility: visible;\n `;\n }\n }}\n`;\n\nexport const Wrapper = styled.div<StyleProps>`\n position: absolute;\n left: 0;\n top: 0;\n background-color: rgba(5, 1, 1, ${(props) => props.$backgroundOpacity});\n backdrop-filter: ${(props) => getBackdropFilter(props.$backgroundBlur)};\n transition: opacity 200ms ease;\n\n ${(props) => {\n let customStyles = \"\";\n if (props.$show) {\n customStyles += css`\n visibility: visible;\n opacity: 1;\n pointer-events: auto;\n height: 100%;\n width: 100vw;\n `;\n } else {\n customStyles += css`\n visibility: hidden;\n opacity: 0;\n transition-delay: ${props.$disableTransition ? \"0ms\" : \"400ms\"};\n pointer-events: none;\n height: 0;\n width: 0;\n `;\n }\n if (props.$disableTransition) {\n customStyles += css`\n transition: none;\n `;\n }\n\n return customStyles;\n }}\n`;\n","import React, { useEffect, useRef, useState } from \"react\";\nimport ReactDOM from \"react-dom\";\nimport { OverlayProps } from \"./types\";\nimport { Root, Wrapper } from \"./overlay.styles\";\n\nexport const Overlay = ({\n show = false,\n rootId,\n onOverlayClick,\n children,\n backgroundOpacity,\n backgroundBlur = true,\n disableTransition = false,\n enableOverlayClick = false,\n zIndex,\n id,\n}: OverlayProps): JSX.Element | null => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const [rootElement, setRootElement] = useState<HTMLElement | null>(null);\n const [isStacked, _setIsStacked] = useState<boolean>();\n\n const stacked = useRef<boolean>();\n\n const childRef = useRef<HTMLDivElement>(null);\n const childWithRef =\n children && React.cloneElement(children, { ref: childRef });\n\n const overlayRootId = id\n ? `lifesg-ds-overlay-root-${id}`\n : \"lifesg-ds-overlay-root\";\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n if (show) {\n const isStacked = checkIfStacked();\n setStacked(isStacked);\n\n if (!isStacked) {\n const timerId = setTimeout(() => {\n applyBodyStyleClass(\"add\");\n }, 200); // Allow overlay animations to complete\n return () => clearTimeout(timerId);\n }\n } else {\n /**\n * Here we have to used the ref value to know if it is stacked\n * rather than checking for the presence of the overlay class\n * on <body>\n */\n if (!stacked.current) {\n const timerId = setTimeout(() => {\n applyBodyStyleClass(\"remove\");\n }, 200); // Allow overlay animations to complete\n return () => clearTimeout(timerId);\n }\n }\n }, [show]);\n\n useEffect(() => {\n setRootElement(getRootElement());\n\n /**\n * Only add stylesheet for a non-stacked overlay\n */\n const isStacked = checkIfStacked();\n setStacked(isStacked);\n if (!isStacked) addStylesheetForDocumentBody();\n\n return () => {\n applyBodyStyleClass(\"remove\");\n };\n }, []);\n\n // =============================================================================\n // REF FUNCTIONS\n // =============================================================================\n const setStacked = (data: boolean) => {\n stacked.current = data;\n _setIsStacked(data);\n };\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const getRootElement = (): HTMLElement | null => {\n if (document && rootId) {\n return document.getElementById(rootId);\n } else if (document) {\n // If rootId not specified, we'll use body\n return document.body;\n } else {\n return null;\n }\n };\n\n const checkIfStacked = () => {\n /**\n * Check if the body style was altered before. If it was, then this is\n * a stacked overlay\n */\n return document.body.classList.contains(OVERLAY_OPEN_CLASSNAME);\n };\n\n const addStylesheetForDocumentBody = () => {\n /**\n * This stylesheet is to manipulate the <body>. We only add once\n */\n if (!document.getElementById(STYLESHEET_ID)) {\n const overlayStyleSheet = document.createElement(\"style\");\n overlayStyleSheet.id = STYLESHEET_ID;\n\n const documentWidth = document.documentElement.clientWidth;\n const windowWidth = window.innerWidth;\n const scrollBarWidth = windowWidth - documentWidth;\n\n overlayStyleSheet.innerHTML = `\n\t\t\t\t.${OVERLAY_OPEN_CLASSNAME} {\n\t\t\t\t\toverflow: hidden;\n\t\t\t\t\tpadding-right: ${scrollBarWidth}px !important;\n\t\t\t\t\t-ms-overflow-style: none;\n\t\t\t\t\tscrollbar-width: none;\n\t\t\t\t}\n\n\t\t\t\t.${OVERLAY_OPEN_CLASSNAME}::-webkit-scrollbar {\n\t\t\t\t\tdisplay: none;\n\t\t\t\t}\n\t\t\t`;\n\n document.body.appendChild(overlayStyleSheet);\n }\n };\n\n /**\n * This sets the style of <body> to hide the scrollbar\n */\n const applyBodyStyleClass = (action: \"add\" | \"remove\") => {\n const isOverlayStyleClassApplied = document.body.classList.contains(\n OVERLAY_OPEN_CLASSNAME\n );\n\n if (action === \"add\" && !isOverlayStyleClassApplied) {\n document.body.classList.add(OVERLAY_OPEN_CLASSNAME);\n } else if (action === \"remove\" && isOverlayStyleClassApplied) {\n document.body.classList.remove(OVERLAY_OPEN_CLASSNAME);\n }\n };\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleWrapperClick = (event: React.MouseEvent<HTMLDivElement>) => {\n const modal = childRef.current?.firstChild;\n if (modal && (modal as any).contains(event.target)) {\n return;\n } else if (onOverlayClick && enableOverlayClick) {\n event.preventDefault();\n onOverlayClick();\n }\n };\n\n // =============================================================================\n // RENDER\n // =============================================================================\n const renderWrapper = () => (\n <Wrapper\n data-testid={\"overlay-wrapper\"}\n $show={show}\n $backgroundOpacity={backgroundOpacity || (isStacked ? 0.5 : 0.8)}\n $backgroundBlur={backgroundBlur}\n $disableTransition={disableTransition}\n $enableOverlayClick={enableOverlayClick}\n onClick={handleWrapperClick}\n >\n {childWithRef}\n </Wrapper>\n );\n\n const renderComponent = () => (\n <Root\n id={overlayRootId}\n data-testid={overlayRootId}\n $show={show}\n zIndex={zIndex}\n $stacked={isStacked}\n >\n {children && renderWrapper()}\n </Root>\n );\n\n return rootElement\n ? ReactDOM.createPortal(renderComponent(), rootElement)\n : null;\n};\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\nconst STYLESHEET_ID = \"lifesg-ds-overlay-stylesheet\";\nconst OVERLAY_OPEN_CLASSNAME = \"lifesg-ds-overlay-open\";\n"],"names":["Root","styled","div","props","zIndex","$stacked","$show","css","Wrapper","$backgroundOpacity","blur","styleString","length","getBackdropFilter","$backgroundBlur","customStyles","$disableTransition","Overlay","show","rootId","onOverlayClick","children","backgroundOpacity","backgroundBlur","disableTransition","enableOverlayClick","id","rootElement","setRootElement","useState","isStacked","_setIsStacked","stacked","useRef","childRef","childWithRef","React","cloneElement","ref","overlayRootId","useEffect","checkIfStacked","setStacked","timerId","setTimeout","applyBodyStyleClass","clearTimeout","current","getRootElement","addStylesheetForDocumentBody","data","document","getElementById","body","classList","contains","OVERLAY_OPEN_CLASSNAME","STYLESHEET_ID","overlayStyleSheet","createElement","documentWidth","documentElement","clientWidth","scrollBarWidth","window","innerWidth","innerHTML","appendChild","action","isOverlayStyleClassApplied","remove","add","handleWrapperClick","event","modal","firstChild","target","preventDefault","ReactDOM","createPortal","_jsx","$enableOverlayClick","onClick"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifesg/react-design-system",
3
- "version": "1.0.0-alpha.21",
3
+ "version": "1.0.0-alpha.22",
4
4
  "description": "A component design system for LifeSG web apps",
5
5
  "main": "./cjs/index.js",
6
6
  "module": "./index.js",
package/popover/index.js CHANGED
@@ -229,7 +229,7 @@ var t=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,r=Object.pr
229
229
  `,e.$disableTransition&&(t+=s`
230
230
  transition: none;
231
231
  `),t}}
232
- `,bn=({show:e=!1,rootId:t,onOverlayClick:r,children:c,backgroundOpacity:s,backgroundBlur:d=!0,disableTransition:f=!1,enableOverlayClick:p=!1,zIndex:h,id:y})=>{const[m,g]=i(null),[v,b]=i(),w=a(),S=a(null),x=c&&o.cloneElement(c,{ref:S}),$=y?`lifesg-ds-overlay-root-${y}`:"lifesg-ds-overlay-root";l((()=>{if(e){const e=O();if(_(e),!e){const e=setTimeout((()=>{C("add")}),200);return()=>clearTimeout(e)}}else if(!w.current){const e=setTimeout((()=>{C("remove")}),200);return()=>clearTimeout(e)}}),[e]),l((()=>{g(F());const e=O();return _(e),e||j(),()=>{C("remove")}}),[]);const _=e=>{w.current=e,b(e)},F=()=>document&&t?document.getElementById(t):document?document.body:null,O=()=>document.body.classList.contains(Sn),j=()=>{if(!document.getElementById(wn)){const e=document.createElement("style");e.id=wn;const t=document.documentElement.clientWidth,n=window.innerWidth-t;e.innerHTML=`\n\t\t\t\t.${Sn} {\n\t\t\t\t\toverflow: hidden;\n\t\t\t\t\tpadding-right: ${n}px !important;\n\t\t\t\t\t-ms-overflow-style: none;\n\t\t\t\t\tscrollbar-width: none;\n\t\t\t\t}\n\n\t\t\t\t.${Sn}::-webkit-scrollbar {\n\t\t\t\t\tdisplay: none;\n\t\t\t\t}\n\t\t\t`,document.body.appendChild(e)}},C=e=>{const t=document.body.classList.contains(Sn);"add"!==e||t?"remove"===e&&t&&document.body.classList.remove(Sn):document.body.classList.add(Sn)},H=e=>{e.preventDefault();const t=S.current?.firstChild;t&&t.contains(e.target)||r&&p&&r()};return m?u.createPortal(n(gn,{id:$,"data-testid":$,$show:e,zIndex:h,$stacked:v,children:c&&n(vn,{"data-testid":"overlay-wrapper",$show:e,$backgroundOpacity:s||(v?.5:.8),$backgroundBlur:d,$disableTransition:f,$enableOverlayClick:p,onClick:H,children:x})}),m):null},wn="lifesg-ds-overlay-stylesheet",Sn="lifesg-ds-overlay-open",xn=e=>Object.keys(h).reduce(((t,n)=>{const r=h[n];return t[n]=`@media screen and (${e}: ${r}px)`,t}),{}),$n=xn("max-width"),_n=(xn("min-width"),c.div`
232
+ `,bn=({show:e=!1,rootId:t,onOverlayClick:r,children:c,backgroundOpacity:s,backgroundBlur:d=!0,disableTransition:f=!1,enableOverlayClick:p=!1,zIndex:h,id:y})=>{const[m,g]=i(null),[v,b]=i(),w=a(),S=a(null),x=c&&o.cloneElement(c,{ref:S}),$=y?`lifesg-ds-overlay-root-${y}`:"lifesg-ds-overlay-root";l((()=>{if(e){const e=O();if(_(e),!e){const e=setTimeout((()=>{C("add")}),200);return()=>clearTimeout(e)}}else if(!w.current){const e=setTimeout((()=>{C("remove")}),200);return()=>clearTimeout(e)}}),[e]),l((()=>{g(F());const e=O();return _(e),e||j(),()=>{C("remove")}}),[]);const _=e=>{w.current=e,b(e)},F=()=>document&&t?document.getElementById(t):document?document.body:null,O=()=>document.body.classList.contains(Sn),j=()=>{if(!document.getElementById(wn)){const e=document.createElement("style");e.id=wn;const t=document.documentElement.clientWidth,n=window.innerWidth-t;e.innerHTML=`\n\t\t\t\t.${Sn} {\n\t\t\t\t\toverflow: hidden;\n\t\t\t\t\tpadding-right: ${n}px !important;\n\t\t\t\t\t-ms-overflow-style: none;\n\t\t\t\t\tscrollbar-width: none;\n\t\t\t\t}\n\n\t\t\t\t.${Sn}::-webkit-scrollbar {\n\t\t\t\t\tdisplay: none;\n\t\t\t\t}\n\t\t\t`,document.body.appendChild(e)}},C=e=>{const t=document.body.classList.contains(Sn);"add"!==e||t?"remove"===e&&t&&document.body.classList.remove(Sn):document.body.classList.add(Sn)},H=e=>{const t=S.current?.firstChild;t&&t.contains(e.target)||r&&p&&(e.preventDefault(),r())};return m?u.createPortal(n(gn,{id:$,"data-testid":$,$show:e,zIndex:h,$stacked:v,children:c&&n(vn,{"data-testid":"overlay-wrapper",$show:e,$backgroundOpacity:s||(v?.5:.8),$backgroundBlur:d,$disableTransition:f,$enableOverlayClick:p,onClick:H,children:x})}),m):null},wn="lifesg-ds-overlay-stylesheet",Sn="lifesg-ds-overlay-open",xn=e=>Object.keys(h).reduce(((t,n)=>{const r=h[n];return t[n]=`@media screen and (${e}: ${r}px)`,t}),{}),$n=xn("max-width"),_n=(xn("min-width"),c.div`
233
233
  position: relative;
234
234
  display: flex;
235
235
  justify-content: center;