@lifesg/react-design-system 3.5.0-canary.7 → 3.5.0-canary.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/accordion/accordion-item.js +1 -1
- package/accordion/accordion-item.js.map +1 -1
- package/accordion/types.d.ts +7 -0
- package/button/button.style.js +20 -19
- package/button/button.style.js.map +1 -1
- package/cjs/accordion/accordion-item.js +1 -1
- package/cjs/accordion/accordion-item.js.map +1 -1
- package/cjs/button/button.style.js +3 -2
- package/cjs/button/button.style.js.map +1 -1
- package/cjs/file-download/file-download.js +1 -1
- package/cjs/file-download/file-download.js.map +1 -1
- package/cjs/file-download/file-list-card/file-list-card.js +1 -1
- package/cjs/file-download/file-list-card/file-list-card.js.map +1 -1
- package/cjs/file-download/file-list-card/file-list-card.styles.js +75 -59
- package/cjs/file-download/file-list-card/file-list-card.styles.js.map +1 -1
- package/cjs/file-upload/helper.js +1 -1
- package/cjs/file-upload/helper.js.map +1 -1
- package/cjs/fullscreen-image-carousel/fullscreen-image-carousel.js +1 -1
- package/cjs/fullscreen-image-carousel/fullscreen-image-carousel.js.map +1 -1
- package/cjs/fullscreen-image-carousel/fullscreen-image-carousel.style.js +19 -19
- package/cjs/fullscreen-image-carousel/fullscreen-image-carousel.style.js.map +1 -1
- package/cjs/navbar/menu.js +1 -1
- package/cjs/navbar/menu.js.map +1 -1
- package/cjs/navbar/menu.styles.js +1 -1
- package/cjs/navbar/menu.styles.js.map +1 -1
- package/cjs/navbar/navbar-items.js +1 -1
- package/cjs/navbar/navbar-items.js.map +1 -1
- package/cjs/navbar/navbar-items.styles.js +20 -21
- package/cjs/navbar/navbar-items.styles.js.map +1 -1
- package/file-download/file-download.d.ts +1 -1
- package/file-download/file-download.js +1 -1
- package/file-download/file-download.js.map +1 -1
- package/file-download/file-list-card/file-list-card.d.ts +1 -1
- package/file-download/file-list-card/file-list-card.js +1 -1
- package/file-download/file-list-card/file-list-card.js.map +1 -1
- package/file-download/file-list-card/file-list-card.styles.d.ts +8 -0
- package/file-download/file-list-card/file-list-card.styles.js +53 -37
- package/file-download/file-list-card/file-list-card.styles.js.map +1 -1
- package/file-download/file-list-card/types.d.ts +2 -1
- package/file-download/types.d.ts +7 -0
- package/file-upload/helper.d.ts +30 -0
- package/file-upload/helper.js +1 -1
- package/file-upload/helper.js.map +1 -1
- package/fullscreen-image-carousel/fullscreen-image-carousel.d.ts +1 -1
- package/fullscreen-image-carousel/fullscreen-image-carousel.js +1 -1
- package/fullscreen-image-carousel/fullscreen-image-carousel.js.map +1 -1
- package/fullscreen-image-carousel/fullscreen-image-carousel.style.d.ts +7 -0
- package/fullscreen-image-carousel/fullscreen-image-carousel.style.js +21 -21
- package/fullscreen-image-carousel/fullscreen-image-carousel.style.js.map +1 -1
- package/fullscreen-image-carousel/types.d.ts +16 -0
- package/navbar/menu.d.ts +2 -1
- package/navbar/menu.js +1 -1
- package/navbar/menu.js.map +1 -1
- package/navbar/menu.styles.js +3 -3
- package/navbar/menu.styles.js.map +1 -1
- package/navbar/navbar-items.js +1 -1
- package/navbar/navbar-items.js.map +1 -1
- package/navbar/navbar-items.styles.js +30 -31
- package/navbar/navbar-items.styles.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{__awaiter as e}from"../../_virtual/_tslib.js";import{jsx as
|
|
1
|
+
import{__awaiter as e}from"../../_virtual/_tslib.js";import{jsx as i,jsxs as t,Fragment as r}from"react/jsx-runtime";import{DownloadIcon as n}from"@lifesg/react-icons";import{memo as a,useState as l,useContext as o,useRef as d,useEffect as s}from"react";import{r as c}from"../../external/react-responsive/dist/react-responsive.js";import{ThemeContext as m}from"styled-components";import{FileUploadHelper as p}from"../../file-upload/helper.js";import{VisuallyHidden as h}from"../../shared/accessibility/index.js";import{Breakpoint as u}from"../../theme/index.js";import"../../util/calendar-helper.js";import"../../util/date-helper.js";import"../../util/date-input-helper.js";import"../../util/simple-id-generator.js";import{StringHelper as f}from"../../util/string-helper.js";import"@react-aria/live-announcer";import{Item as y,Box as b,ContentSection as g,ExtendedNameSection as j,CardButton as w,ActionContainer as v,IconButton as x,Spinner as $,ThumbnailContainer as T,PdfThumbnail as C,Thumbnail as k,NameSection as D,FileSizeSection as z,MobileErrorMessage as _,ErrorIcon as I,ItemNameText as L,DesktopErrorMessage as P}from"./file-list-card.styles.js";const S=a((({fileItem:a,onDownload:S,onClick:F})=>{const{id:M,name:R,mimeType:U,size:B,errorMessage:N,thumbnailImageDataUrl:O,truncateText:Q=!0,ready:W=!0,clickLabel:q}=a,[A,E]=l(!1),[G,H]=l(!1),J=p.formatFileSizeDisplay(B),K=p.resolveThumbnailDisplay(U,O),V="none"!==K.type,X=o(m),Y=u["sm-max"]({theme:X}),Z=c.useMediaQuery({maxWidth:Y}),[ee,ie]=l(),te=d(null);s((()=>{te.current&&ie(Z?oe(R):R)}),[R,Z]);const re=()=>e(void 0,void 0,void 0,(function*(){if(W&&!A){E(!0);try{H(!1),yield S(a)}catch(e){H(!0)}finally{E(!1)}}})),ne=()=>{W&&(F?F(a):re())},ae=e=>{e.stopPropagation(),ne()},le=e=>{e.stopPropagation(),re()},oe=e=>{if(!Q)return e;const i=te&&te.current?te.current.getBoundingClientRect().width:0;return f.truncateTwoLines(e,i,16,1.5)},de=()=>t(r,{children:[i(D,{children:t(r,{children:[i(L,{ref:te,children:ee}),G&&t(P,{children:[i(I,{"aria-hidden":!0}),N||"Something went wrong"]})]})}),i(z,{children:J||"-"}),G&&t(_,{children:[i(I,{"aria-hidden":!0}),N||"Something went wrong"]})]});return i(y,{"data-testid":M,children:t(b,{onClick:ne,$error:G,children:[t(g,{$hasThumbnail:V,children:["none"===K.type?null:i(T,{"data-testid":`${M}-thumbnail`,children:"pdf-icon"===K.type?i(C,{"data-testid":`${M}-thumbnail-image`,src:p.PDF_ICON_URL}):i(k,{"data-testid":`${M}-thumbnail-image`,src:K.src})}),V?i(j,{children:de()}):de()]}),F?i(h,{children:i(w,{type:"button","data-testid":`${M}-card-button`,"aria-label":null!=q?q:R,disabled:!W,onClick:ae})}):null,i(v,{children:i(x,{"data-testid":`${M}-download-button`,type:"button",styleType:"light",sizeType:"small","aria-label":`download ${R}`,onClick:le,children:A||!W?i($,{size:16,"aria-hidden":!0}):i(n,{"aria-hidden":!0})})})]})})}));export{S as FileListCard};
|
|
2
2
|
//# sourceMappingURL=file-list-card.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-list-card.js","sources":["../../../src/file-download/file-list-card/file-list-card.tsx"],"sourcesContent":["import { DownloadIcon } from \"@lifesg/react-icons\";\nimport { memo, useContext, useEffect, useRef, useState } from \"react\";\nimport { useMediaQuery } from \"react-responsive\";\nimport { ThemeContext } from \"styled-components\";\nimport { FileUploadHelper } from \"../../file-upload/helper\";\nimport { Breakpoint } from \"../../theme\";\nimport { StringHelper } from \"../../util\";\nimport {\n ActionContainer,\n Box,\n ContentSection,\n DesktopErrorMessage,\n ErrorIcon,\n ExtendedNameSection,\n FileSizeSection,\n IconButton,\n Item,\n ItemNameText,\n MobileErrorMessage,\n NameSection,\n Spinner,\n Thumbnail,\n ThumbnailContainer,\n} from \"./file-list-card.styles\";\nimport { FileListItemProps } from \"./types\";\n\nconst Component = ({ fileItem, onDownload }: FileListItemProps) => {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const {\n id,\n name,\n size,\n errorMessage,\n thumbnailImageDataUrl,\n truncateText = true,\n ready = true,\n } = fileItem;\n\n // Local variables\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [isError, setIsError] = useState<boolean>(false);\n const fileSize = FileUploadHelper.formatFileSizeDisplay(size);\n const theme = useContext(ThemeContext);\n const mobileBreakpoint = Breakpoint[\"sm-max\"]({ theme });\n const isMobile = useMediaQuery({ maxWidth: mobileBreakpoint });\n const [displayText, setDisplayText] = useState<string>();\n const containerRef = useRef<HTMLDivElement>(null);\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n if (!containerRef.current) return;\n if (isMobile) {\n setDisplayText(getTruncatedText(name));\n } else {\n setDisplayText(name);\n }\n }, [name, isMobile]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleDownload = async () => {\n if (!ready || isLoading) {\n return;\n }\n\n setIsLoading(true);\n try {\n setIsError(false);\n await onDownload(fileItem);\n } catch {\n setIsError(true);\n } finally {\n setIsLoading(false);\n }\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const getTruncatedText = (value: string) => {\n if (!truncateText) return value;\n\n const widthOfElement =\n containerRef && containerRef.current\n ? containerRef.current.getBoundingClientRect().width\n : 0;\n\n return StringHelper.truncateTwoLines(value, widthOfElement, 16, 1.5);\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderNameDescription = () => (\n <>\n <ItemNameText ref={containerRef}>{displayText}</ItemNameText>\n {isError && (\n <DesktopErrorMessage>\n <ErrorIcon aria-hidden />\n {errorMessage ? errorMessage : \"Something went wrong\"}\n </DesktopErrorMessage>\n )}\n </>\n );\n\n const renderWithThumbnail = (thumbnailSrc: string) => (\n <>\n <ThumbnailContainer data-testid={`${id}-thumbnail`}>\n <Thumbnail\n data-testid={`${id}-thumbnail-image`}\n src={thumbnailSrc}\n />\n </ThumbnailContainer>\n <ExtendedNameSection>\n <NameSection>{renderNameDescription()}</NameSection>\n <FileSizeSection>{fileSize ? fileSize : \"-\"}</FileSizeSection>\n {isError && (\n <MobileErrorMessage>\n <ErrorIcon aria-hidden />\n {errorMessage ? errorMessage : \"Something went wrong\"}\n </MobileErrorMessage>\n )}\n </ExtendedNameSection>\n </>\n );\n\n const renderDefault = () => (\n <>\n <NameSection>{renderNameDescription()}</NameSection>\n <FileSizeSection>{fileSize ? fileSize : \"-\"}</FileSizeSection>\n {isError && (\n <MobileErrorMessage>\n <ErrorIcon aria-hidden />\n {errorMessage ? errorMessage : \"Something went wrong\"}\n </MobileErrorMessage>\n )}\n </>\n );\n\n const renderContents = () => {\n let content: JSX.Element;\n\n if (thumbnailImageDataUrl) {\n content = renderWithThumbnail(thumbnailImageDataUrl);\n } else {\n content = renderDefault();\n }\n\n return (\n <ContentSection $hasThumbnail={!!thumbnailImageDataUrl}>\n {content}\n </ContentSection>\n );\n };\n\n const renderActions = () => {\n return (\n <ActionContainer>\n <IconButton\n data-testid={`${id}-download-button`}\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`download ${name}`}\n >\n {isLoading || !ready ? (\n <Spinner size={16} aria-hidden />\n ) : (\n <DownloadIcon aria-hidden />\n )}\n </IconButton>\n </ActionContainer>\n );\n };\n\n return (\n <Item data-testid={id}>\n <Box onClick={handleDownload} $error={isError}>\n {renderContents()}\n {renderActions()}\n </Box>\n </Item>\n );\n};\n\nexport const FileListCard = memo(Component);\n"],"names":["FileListCard","memo","fileItem","onDownload","id","name","size","errorMessage","thumbnailImageDataUrl","truncateText","ready","isLoading","setIsLoading","useState","isError","setIsError","fileSize","FileUploadHelper","formatFileSizeDisplay","theme","useContext","ThemeContext","mobileBreakpoint","Breakpoint","isMobile","useMediaQuery","maxWidth","displayText","setDisplayText","containerRef","useRef","useEffect","current","getTruncatedText","value","widthOfElement","getBoundingClientRect","width","StringHelper","truncateTwoLines","renderNameDescription","_jsxs","_jsx","ItemNameText","ref","children","DesktopErrorMessage","ErrorIcon","Item","Box","onClick","__awaiter","_a","$error","content","_Fragment","ThumbnailContainer","Thumbnail","src","ExtendedNameSection","NameSection","FileSizeSection","MobileErrorMessage","ContentSection","$hasThumbnail","renderContents","ActionContainer","IconButton","type","styleType","sizeType","Spinner","DownloadIcon"],"mappings":"8hCA0BA,MAoKaA,EAAeC,GApKV,EAAGC,WAAUC,iBAI3B,MAAMC,GACFA,EAAEC,KACFA,EAAIC,KACJA,EAAIC,aACJA,EAAYC,sBACZA,EAAqBC,aACrBA,GAAe,EAAIC,MACnBA,GAAQ,GACRR,GAGGS,EAAWC,GAAgBC,GAAkB,IAC7CC,EAASC,GAAcF,GAAkB,GAC1CG,EAAWC,EAAiBC,sBAAsBZ,GAClDa,EAAQC,EAAWC,GACnBC,EAAmBC,EAAW,UAAU,CAAEJ,UAC1CK,EAAWC,EAAAA,cAAc,CAAEC,SAAUJ,KACpCK,EAAaC,GAAkBf,IAChCgB,EAAeC,EAAuB,MAK5CC,GAAU,KACDF,EAAaG,SAEdJ,EADAJ,EACeS,EAAiB5B,GAEjBA,EACnB,GACD,CAACA,EAAMmB,IAKV,MAmBMS,EAAoBC,IACtB,IAAKzB,EAAc,OAAOyB,EAE1B,MAAMC,EACFN,GAAgBA,EAAaG,QACvBH,EAAaG,QAAQI,wBAAwBC,MAC7C,EAEV,OAAOC,EAAaC,iBAAiBL,EAAOC,EAAgB,GAAI,IAAI,EAMlEK,EAAwB,IAC1BC,eACIC,EAACC,EAAY,CAACC,IAAKf,EAAYgB,SAAGlB,IACjCb,GACG2B,EAACK,aACGJ,EAACK,sBACAxC,GAA8B,6BA4E/C,OACImC,EAACM,EAAI,CAAA,cAAc5C,EAAEyC,SACjBJ,EAACQ,EAAG,CAACC,QArHU,IAAWC,OAAA,OAAA,OAAA,GAAA,YAC9B,GAAKzC,IAASC,EAAd,CAIAC,GAAa,GACb,IACIG,GAAW,SACLZ,EAAWD,EACrB,CAAE,MAAAkD,GACErC,GAAW,EACf,SACIH,GAAa,EACjB,CAVA,CAWJ,IAuGoCyC,OAAUvC,EAAO+B,SAAA,CAtC9B,MACnB,IAAIS,EAQJ,OALIA,EArCJb,EAAAc,EAoCI/C,EApCJ,CAAAqC,SAAA,CACIH,EAACc,EAAkB,CAAA,cAAc,GAAGpD,uBAChCsC,EAACe,EAAS,CAAA,cACO,GAAGrD,oBAChBsD,IAiCsBlD,MA9B9BiC,EAACkB,EAAmB,CAAAd,SAAA,CAChBH,EAACkB,EAAW,CAAAf,SAAEL,MACdE,EAACmB,EAAe,CAAAhB,SAAE7B,GAAsB,MACvCF,GACG2B,EAACqB,EAAkB,CAAAjB,SAAA,CACfH,EAACK,EAAS,CAAA,eAAA,IACTxC,GAA8B,+BAQ/C,CAAAsC,SAAA,CACIH,EAACkB,EAAW,CAAAf,SAAEL,MACdE,EAACmB,EAAe,CAAAhB,SAAE7B,GAAsB,MACvCF,GACG2B,EAACqB,EAAkB,CAAAjB,SAAA,CACfH,EAACK,EAAS,CAAA,eAAA,IACTxC,GAA8B,6BAgBvCmC,EAACqB,EAAc,CAAAC,gBAAkBxD,EAAqBqC,SACjDS,GACY,EA2BZW,GArBLvB,EAACwB,EAAe,CAAArB,SACZH,EAACyB,EAAU,CAAA,cACM,GAAG/D,oBAChBgE,KAAK,SACLC,UAAU,QACVC,SAAS,QAAO,aACJ,YAAYjE,IAAMwC,SAE7BlC,IAAcD,EACXgC,EAAC6B,EAAO,CAACjE,KAAM,sBAEfoC,EAAC8B,EAAY,CAAA,eAAA,YAatB"}
|
|
1
|
+
{"version":3,"file":"file-list-card.js","sources":["../../../src/file-download/file-list-card/file-list-card.tsx"],"sourcesContent":["import { DownloadIcon } from \"@lifesg/react-icons\";\nimport { memo, useContext, useEffect, useRef, useState } from \"react\";\nimport { useMediaQuery } from \"react-responsive\";\nimport { ThemeContext } from \"styled-components\";\nimport { FileUploadHelper } from \"../../file-upload/helper\";\nimport { VisuallyHidden } from \"../../shared/accessibility\";\nimport { Breakpoint } from \"../../theme\";\nimport { StringHelper } from \"../../util\";\nimport {\n ActionContainer,\n Box,\n CardButton,\n ContentSection,\n DesktopErrorMessage,\n ErrorIcon,\n ExtendedNameSection,\n FileSizeSection,\n IconButton,\n Item,\n ItemNameText,\n MobileErrorMessage,\n NameSection,\n PdfThumbnail,\n Spinner,\n Thumbnail,\n ThumbnailContainer,\n} from \"./file-list-card.styles\";\nimport { FileListItemProps } from \"./types\";\n\nconst Component = ({ fileItem, onDownload, onClick }: FileListItemProps) => {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const {\n id,\n name,\n mimeType,\n size,\n errorMessage,\n thumbnailImageDataUrl,\n truncateText = true,\n ready = true,\n clickLabel,\n } = fileItem;\n\n // Local variables\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [isError, setIsError] = useState<boolean>(false);\n const fileSize = FileUploadHelper.formatFileSizeDisplay(size);\n const thumbnailDisplay = FileUploadHelper.resolveThumbnailDisplay(\n mimeType,\n thumbnailImageDataUrl\n );\n const hasThumbnail = thumbnailDisplay.type !== \"none\";\n const theme = useContext(ThemeContext);\n const mobileBreakpoint = Breakpoint[\"sm-max\"]({ theme });\n const isMobile = useMediaQuery({ maxWidth: mobileBreakpoint });\n const [displayText, setDisplayText] = useState<string>();\n const containerRef = useRef<HTMLDivElement>(null);\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n if (!containerRef.current) return;\n if (isMobile) {\n setDisplayText(getTruncatedText(name));\n } else {\n setDisplayText(name);\n }\n }, [name, isMobile]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleDownload = async () => {\n if (!ready || isLoading) {\n return;\n }\n\n setIsLoading(true);\n try {\n setIsError(false);\n await onDownload(fileItem);\n } catch {\n setIsError(true);\n } finally {\n setIsLoading(false);\n }\n };\n\n const handleCardClick = () => {\n if (!ready) {\n return;\n }\n\n if (onClick) {\n onClick(fileItem);\n return;\n }\n\n handleDownload();\n };\n\n const handleCardButtonClick = (\n event: React.MouseEvent<HTMLButtonElement>\n ) => {\n // The button sits inside Box, which also handles clicks. Without this,\n // both handlers fire and the action runs twice.\n event.stopPropagation();\n handleCardClick();\n };\n\n const handleDownloadButtonClick = (\n event: React.MouseEvent<HTMLButtonElement>\n ) => {\n // Same reason as above: stop the click from also reaching Box.\n event.stopPropagation();\n handleDownload();\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const getTruncatedText = (value: string) => {\n if (!truncateText) return value;\n\n const widthOfElement =\n containerRef && containerRef.current\n ? containerRef.current.getBoundingClientRect().width\n : 0;\n\n return StringHelper.truncateTwoLines(value, widthOfElement, 16, 1.5);\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderNameDescription = () => (\n <>\n <ItemNameText ref={containerRef}>{displayText}</ItemNameText>\n {isError && (\n <DesktopErrorMessage>\n <ErrorIcon aria-hidden />\n {errorMessage ? errorMessage : \"Something went wrong\"}\n </DesktopErrorMessage>\n )}\n </>\n );\n\n const renderThumbnail = () => {\n if (thumbnailDisplay.type === \"none\") {\n return null;\n }\n\n return (\n <ThumbnailContainer data-testid={`${id}-thumbnail`}>\n {thumbnailDisplay.type === \"pdf-icon\" ? (\n <PdfThumbnail\n data-testid={`${id}-thumbnail-image`}\n src={FileUploadHelper.PDF_ICON_URL}\n />\n ) : (\n <Thumbnail\n data-testid={`${id}-thumbnail-image`}\n src={thumbnailDisplay.src}\n />\n )}\n </ThumbnailContainer>\n );\n };\n\n const renderNameSizeError = () => (\n <>\n <NameSection>{renderNameDescription()}</NameSection>\n <FileSizeSection>{fileSize ? fileSize : \"-\"}</FileSizeSection>\n {isError && (\n <MobileErrorMessage>\n <ErrorIcon aria-hidden />\n {errorMessage ? errorMessage : \"Something went wrong\"}\n </MobileErrorMessage>\n )}\n </>\n );\n\n const renderContents = () => (\n <ContentSection $hasThumbnail={hasThumbnail}>\n {renderThumbnail()}\n {hasThumbnail ? (\n <ExtendedNameSection>\n {renderNameSizeError()}\n </ExtendedNameSection>\n ) : (\n renderNameSizeError()\n )}\n </ContentSection>\n );\n\n const renderCardButton = () => {\n if (!onClick) {\n return null;\n }\n\n return (\n <VisuallyHidden>\n <CardButton\n type=\"button\"\n data-testid={`${id}-card-button`}\n aria-label={clickLabel ?? name}\n disabled={!ready}\n onClick={handleCardButtonClick}\n />\n </VisuallyHidden>\n );\n };\n\n const renderActions = () => {\n return (\n <ActionContainer>\n <IconButton\n data-testid={`${id}-download-button`}\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`download ${name}`}\n onClick={handleDownloadButtonClick}\n >\n {isLoading || !ready ? (\n <Spinner size={16} aria-hidden />\n ) : (\n <DownloadIcon aria-hidden />\n )}\n </IconButton>\n </ActionContainer>\n );\n };\n\n return (\n <Item data-testid={id}>\n <Box onClick={handleCardClick} $error={isError}>\n {renderContents()}\n {renderCardButton()}\n {renderActions()}\n </Box>\n </Item>\n );\n};\n\nexport const FileListCard = memo(Component);\n"],"names":["FileListCard","memo","fileItem","onDownload","onClick","id","name","mimeType","size","errorMessage","thumbnailImageDataUrl","truncateText","ready","clickLabel","isLoading","setIsLoading","useState","isError","setIsError","fileSize","FileUploadHelper","formatFileSizeDisplay","thumbnailDisplay","resolveThumbnailDisplay","hasThumbnail","type","theme","useContext","ThemeContext","mobileBreakpoint","Breakpoint","isMobile","useMediaQuery","maxWidth","displayText","setDisplayText","containerRef","useRef","useEffect","current","getTruncatedText","handleDownload","__awaiter","_a","handleCardClick","handleCardButtonClick","event","stopPropagation","handleDownloadButtonClick","value","widthOfElement","getBoundingClientRect","width","StringHelper","truncateTwoLines","renderNameSizeError","_jsxs","_Fragment","children","_jsx","NameSection","ItemNameText","ref","DesktopErrorMessage","ErrorIcon","FileSizeSection","MobileErrorMessage","Item","Box","$error","ContentSection","$hasThumbnail","ThumbnailContainer","PdfThumbnail","src","PDF_ICON_URL","Thumbnail","ExtendedNameSection","VisuallyHidden","CardButton","disabled","ActionContainer","IconButton","styleType","sizeType","Spinner","DownloadIcon"],"mappings":"qoCA6BA,MA2NaA,EAAeC,GA3NV,EAAGC,WAAUC,aAAYC,cAIvC,MAAMC,GACFA,EAAEC,KACFA,EAAIC,SACJA,EAAQC,KACRA,EAAIC,aACJA,EAAYC,sBACZA,EAAqBC,aACrBA,GAAe,EAAIC,MACnBA,GAAQ,EAAIC,WACZA,GACAX,GAGGY,EAAWC,GAAgBC,GAAkB,IAC7CC,EAASC,GAAcF,GAAkB,GAC1CG,EAAWC,EAAiBC,sBAAsBb,GAClDc,EAAmBF,EAAiBG,wBACtChB,EACAG,GAEEc,EAAyC,SAA1BF,EAAiBG,KAChCC,EAAQC,EAAWC,GACnBC,EAAmBC,EAAW,UAAU,CAAEJ,UAC1CK,EAAWC,EAAAA,cAAc,CAAEC,SAAUJ,KACpCK,GAAaC,IAAkBnB,IAChCoB,GAAeC,EAAuB,MAK5CC,GAAU,KACDF,GAAaG,SAEdJ,GADAJ,EACeS,GAAiBlC,GAEjBA,EACnB,GACD,CAACA,EAAMyB,IAKV,MAAMU,GAAiB,IAAWC,OAAA,OAAA,OAAA,GAAA,YAC9B,GAAK9B,IAASE,EAAd,CAIAC,GAAa,GACb,IACIG,GAAW,SACLf,EAAWD,EACrB,CAAE,MAAAyC,GACEzB,GAAW,EACf,SACIH,GAAa,EACjB,CAVA,CAWJ,IAEM6B,GAAkB,KACfhC,IAIDR,EACAA,EAAQF,GAIZuC,KAAgB,EAGdI,GACFC,IAIAA,EAAMC,kBACNH,IAAiB,EAGfI,GACFF,IAGAA,EAAMC,kBACNN,IAAgB,EAMdD,GAAoBS,IACtB,IAAKtC,EAAc,OAAOsC,EAE1B,MAAMC,EACFd,IAAgBA,GAAaG,QACvBH,GAAaG,QAAQY,wBAAwBC,MAC7C,EAEV,OAAOC,EAAaC,iBAAiBL,EAAOC,EAAgB,GAAI,IAAI,EAwClEK,GAAsB,IACxBC,EAAAC,EAAA,CAAAC,SAAA,CACIC,EAACC,EAAW,CAAAF,SAnChBF,eACIG,EAACE,EAAY,CAACC,IAAK1B,GAAYsB,SAAGxB,KACjCjB,GACGuC,EAACO,aACGJ,EAACK,sBACAvD,GAA8B,+BA+BvCkD,EAACM,EAAe,CAAAP,SAAEvC,GAAsB,MACvCF,GACGuC,EAACU,EAAkB,CAAAR,SAAA,CACfC,EAACK,EAAS,CAAA,eAAA,IACTvD,GAA8B,6BA0D/C,OACIkD,EAACQ,EAAI,CAAA,cAAc9D,EAAEqD,SACjBF,EAACY,EAAG,CAAChE,QAASwC,GAAeyB,OAAUpD,EAAOyC,SAAA,CArDlDF,EAACc,EAAc,CAAAC,cAAgB/C,EAAYkC,SAAA,CAnCb,SAA1BpC,EAAiBG,KACV,KAIPkC,EAACa,EAAkB,CAAA,cAAc,GAAGnE,cAAcqD,SACnB,aAA1BpC,EAAiBG,KACdkC,EAACc,EAAY,CAAA,cACI,GAAGpE,oBAChBqE,IAAKtD,EAAiBuD,eAG1BhB,EAACiB,EAAS,CAAA,cACO,GAAGvE,oBAChBqE,IAAKpD,EAAiBoD,QAuBjClD,EACGmC,EAACkB,EAAmB,CAAAnB,SACfH,OAGLA,QAMHnD,EAKDuD,EAACmB,EAAc,CAAApB,SACXC,EAACoB,EAAU,CACPtD,KAAK,SAAQ,cACA,GAAGpB,6BACJQ,QAAAA,EAAcP,EAC1B0E,UAAWpE,EACXR,QAASyC,OAVV,KAkBPc,EAACsB,EAAe,CAAAvB,SACZC,EAACuB,EAAU,CAAA,cACM,GAAG7E,oBAChBoB,KAAK,SACL0D,UAAU,QACVC,SAAS,QAAO,aACJ,YAAY9E,IACxBF,QAAS4C,GAAyBU,SAEjC5C,IAAcF,EACX+C,EAAC0B,EAAO,CAAC7E,KAAM,GAAE,eAAA,IAEjBmD,EAAC2B,EAAY,CAAA,eAAA,YActB"}
|
|
@@ -5,6 +5,7 @@ interface ContentSectionStyleProps {
|
|
|
5
5
|
$hasThumbnail?: boolean | undefined;
|
|
6
6
|
}
|
|
7
7
|
export declare const Item: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, never>>> & string;
|
|
8
|
+
export declare const CardButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>>> & string;
|
|
8
9
|
export declare const Box: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "$error"> & BoxStyleProps, never> & Partial<Pick<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "$error"> & BoxStyleProps, never>>> & string;
|
|
9
10
|
export declare const ContentSection: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "$hasThumbnail"> & ContentSectionStyleProps, never> & Partial<Pick<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "$hasThumbnail"> & ContentSectionStyleProps, never>>> & string;
|
|
10
11
|
export declare const NameSection: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>>> & string;
|
|
@@ -57,4 +58,11 @@ export declare const ActionContainer: import("styled-components/dist/types").ISt
|
|
|
57
58
|
export declare const IconButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("../..").IconButtonProps & import("react").RefAttributes<HTMLButtonElement>, never> & Partial<Pick<import("../..").IconButtonProps & import("react").RefAttributes<HTMLButtonElement>, never>>> & string & Omit<(props: import("../..").IconButtonProps & import("react").RefAttributes<HTMLButtonElement>) => React.ReactElement | null, keyof import("react").Component<any, {}, any>>;
|
|
58
59
|
export declare const ThumbnailContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>>> & string;
|
|
59
60
|
export declare const Thumbnail: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("../../shared/image-with-fallback/image-with-fallback").ImageWithFallbackProps, never> & Partial<Pick<import("../../shared/image-with-fallback/image-with-fallback").ImageWithFallbackProps, never>>> & string & Omit<({ src, alt, className, "data-testid": testId, }: import("../../shared/image-with-fallback/image-with-fallback").ImageWithFallbackProps) => import("react/jsx-runtime").JSX.Element, keyof import("react").Component<any, {}, any>>;
|
|
61
|
+
export declare const PdfThumbnail: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<import("../../shared/image-with-fallback/image-with-fallback").ImageWithFallbackProps, never> & Partial<Pick<import("../../shared/image-with-fallback/image-with-fallback").ImageWithFallbackProps, never>> & {
|
|
62
|
+
as?: import("styled-components").WebTarget | undefined;
|
|
63
|
+
forwardedAs?: import("styled-components").WebTarget | undefined;
|
|
64
|
+
}, never> & Partial<Pick<import("styled-components").FastOmit<import("../../shared/image-with-fallback/image-with-fallback").ImageWithFallbackProps, never> & Partial<Pick<import("../../shared/image-with-fallback/image-with-fallback").ImageWithFallbackProps, never>> & {
|
|
65
|
+
as?: import("styled-components").WebTarget | undefined;
|
|
66
|
+
forwardedAs?: import("styled-components").WebTarget | undefined;
|
|
67
|
+
}, never>>> & string;
|
|
60
68
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import i,{css as
|
|
1
|
+
import i,{css as e}from"styled-components";import{ExclamationCircleFillIcon as r}from"@lifesg/react-icons/exclamation-circle-fill";import{IconButton as t}from"../../icon-button/icon-button.js";import{ComponentLoadingSpinner as o}from"../../shared/component-loading-spinner/component-loading-spinner.js";import{ImageWithFallback as n}from"../../shared/image-with-fallback/image-with-fallback.js";import{lineClampCss as a}from"../../shared/styles/index.js";import{Spacing as l,Colour as d,Border as s,Radius as c,MediaQuery as g,Font as p}from"../../theme/index.js";const m=i.li`
|
|
2
2
|
display: flex;
|
|
3
3
|
align-items: center;
|
|
4
4
|
|
|
@@ -8,7 +8,12 @@ import i,{css as r}from"styled-components";import{ExclamationCircleFillIcon as e
|
|
|
8
8
|
&:not(:last-child) {
|
|
9
9
|
margin-bottom: ${l["spacing-16"]};
|
|
10
10
|
}
|
|
11
|
-
`,$=i.
|
|
11
|
+
`,$=i.button`
|
|
12
|
+
appearance: none;
|
|
13
|
+
padding: 0;
|
|
14
|
+
background: none;
|
|
15
|
+
border: none;
|
|
16
|
+
`,h=i.div`
|
|
12
17
|
display: flex;
|
|
13
18
|
align-items: center;
|
|
14
19
|
|
|
@@ -18,9 +23,9 @@ import i,{css as r}from"styled-components";import{ExclamationCircleFillIcon as e
|
|
|
18
23
|
|
|
19
24
|
background: ${d["bg-primary-subtlest"]};
|
|
20
25
|
border: ${s["width-010"]} ${s.solid} ${d.border};
|
|
21
|
-
border-radius: ${
|
|
26
|
+
border-radius: ${c.sm};
|
|
22
27
|
|
|
23
|
-
${
|
|
28
|
+
${g.MaxWidth.lg} {
|
|
24
29
|
padding: ${l["spacing-16"]};
|
|
25
30
|
}
|
|
26
31
|
|
|
@@ -28,32 +33,41 @@ import i,{css as r}from"styled-components";import{ExclamationCircleFillIcon as e
|
|
|
28
33
|
background: ${d["bg-hover"]};
|
|
29
34
|
}
|
|
30
35
|
|
|
31
|
-
${
|
|
36
|
+
&:has(${$}:focus-visible) {
|
|
37
|
+
outline: 2px solid ${d["focus-ring"]};
|
|
38
|
+
outline-offset: -2px;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
${i=>{if(i.$error)return e`
|
|
32
42
|
background: ${d["bg-error"]};
|
|
33
43
|
border-color: ${d["border-error"]};
|
|
34
44
|
|
|
35
45
|
&:hover {
|
|
36
46
|
background: ${d["bg-error"]};
|
|
37
47
|
}
|
|
48
|
+
|
|
49
|
+
&:has(${$}:focus-visible) {
|
|
50
|
+
outline-color: ${d["border-error-focus"]};
|
|
51
|
+
}
|
|
38
52
|
`}}
|
|
39
|
-
`,
|
|
53
|
+
`,f=i.div`
|
|
40
54
|
display: flex;
|
|
41
55
|
flex: 1;
|
|
42
56
|
align-items: center;
|
|
43
57
|
|
|
44
|
-
${
|
|
58
|
+
${g.MaxWidth.lg} {
|
|
45
59
|
flex-direction: column;
|
|
46
60
|
align-items: flex-start;
|
|
47
61
|
width: 100%;
|
|
48
62
|
}
|
|
49
63
|
|
|
50
|
-
${i=>{if(i.$hasThumbnail)return
|
|
51
|
-
${
|
|
64
|
+
${i=>{if(i.$hasThumbnail)return e`
|
|
65
|
+
${g.MaxWidth.lg} {
|
|
52
66
|
flex-direction: row;
|
|
53
67
|
align-items: center;
|
|
54
68
|
}
|
|
55
69
|
`}}
|
|
56
|
-
`,
|
|
70
|
+
`,x=i.div`
|
|
57
71
|
display: flex;
|
|
58
72
|
flex: 1;
|
|
59
73
|
flex-direction: column;
|
|
@@ -63,27 +77,27 @@ import i,{css as r}from"styled-components";import{ExclamationCircleFillIcon as e
|
|
|
63
77
|
overflow-wrap: break-word;
|
|
64
78
|
word-break: break-all;
|
|
65
79
|
white-space: normal;
|
|
66
|
-
`,
|
|
80
|
+
`,b=i.div`
|
|
67
81
|
display: flex;
|
|
68
82
|
flex: 1;
|
|
69
83
|
align-items: center;
|
|
70
84
|
|
|
71
|
-
${
|
|
85
|
+
${g.MaxWidth.lg} {
|
|
72
86
|
flex-direction: column;
|
|
73
87
|
align-items: flex-start;
|
|
74
88
|
width: 100%;
|
|
75
89
|
}
|
|
76
|
-
`,
|
|
90
|
+
`,u=i.div`
|
|
77
91
|
display: flex;
|
|
78
92
|
justify-content: flex-end;
|
|
79
93
|
|
|
80
94
|
width: 5rem;
|
|
81
95
|
margin-left: ${l["spacing-8"]};
|
|
82
96
|
|
|
83
|
-
${
|
|
97
|
+
${p["body-md-regular"]}
|
|
84
98
|
color: ${d.text};
|
|
85
99
|
|
|
86
|
-
${
|
|
100
|
+
${g.MaxWidth.lg} {
|
|
87
101
|
justify-content: flex-start;
|
|
88
102
|
|
|
89
103
|
width: 100%;
|
|
@@ -92,62 +106,62 @@ import i,{css as r}from"styled-components";import{ExclamationCircleFillIcon as e
|
|
|
92
106
|
|
|
93
107
|
${a(2)}
|
|
94
108
|
}
|
|
95
|
-
`,
|
|
96
|
-
${
|
|
109
|
+
`,y=i.div`
|
|
110
|
+
${p["body-md-regular"]}
|
|
97
111
|
color: ${d.text};
|
|
98
112
|
|
|
99
|
-
${
|
|
113
|
+
${g.MaxWidth.lg} {
|
|
100
114
|
${a(2)}
|
|
101
115
|
}
|
|
102
|
-
`;i(
|
|
103
|
-
${
|
|
116
|
+
`;i(y)`
|
|
117
|
+
${p["body-md-regular"]}
|
|
104
118
|
margin-top: ${l["spacing-4"]};
|
|
105
|
-
`;const
|
|
119
|
+
`;const w=i(r)`
|
|
106
120
|
height: 1lh;
|
|
107
121
|
width: 1em;
|
|
108
122
|
flex-shrink: 0;
|
|
109
123
|
color: ${d["icon-error-strong"]};
|
|
110
|
-
`,
|
|
111
|
-
${
|
|
124
|
+
`,v=i.div`
|
|
125
|
+
${p["body-sm-semibold"]}
|
|
112
126
|
color: ${d["text-error"]};
|
|
113
|
-
`,
|
|
127
|
+
`,k=i(v)`
|
|
114
128
|
margin-top: ${l["spacing-8"]};
|
|
115
129
|
display: flex;
|
|
116
130
|
gap: ${l["spacing-4"]};
|
|
117
131
|
|
|
118
|
-
${
|
|
132
|
+
${g.MaxWidth.lg} {
|
|
119
133
|
display: none;
|
|
120
134
|
visibility: hidden;
|
|
121
135
|
}
|
|
122
|
-
`,
|
|
136
|
+
`,M=i(v)`
|
|
123
137
|
display: none;
|
|
124
138
|
visibility: hidden;
|
|
125
139
|
|
|
126
|
-
${
|
|
140
|
+
${g.MaxWidth.lg} {
|
|
127
141
|
display: flex;
|
|
128
142
|
gap: ${l["spacing-4"]};
|
|
129
143
|
visibility: visible;
|
|
130
144
|
margin-top: ${l["spacing-8"]};
|
|
131
145
|
}
|
|
132
|
-
`,
|
|
146
|
+
`,W=i(o)`
|
|
133
147
|
color: ${d["icon-primary"]};
|
|
134
|
-
`,
|
|
148
|
+
`,j=i.div`
|
|
135
149
|
display: flex;
|
|
136
150
|
justify-content: flex-end;
|
|
137
151
|
align-items: center;
|
|
138
152
|
|
|
139
153
|
margin-left: ${l["spacing-32"]};
|
|
140
154
|
|
|
141
|
-
${
|
|
155
|
+
${g.MaxWidth.lg} {
|
|
142
156
|
margin-left: ${l["spacing-16"]};
|
|
143
157
|
}
|
|
144
|
-
`,
|
|
158
|
+
`,B=i(t)`
|
|
145
159
|
min-width: unset;
|
|
146
160
|
|
|
147
161
|
&:not(:last-child) {
|
|
148
162
|
margin-right: ${l["spacing-16"]};
|
|
149
163
|
}
|
|
150
|
-
`,
|
|
164
|
+
`,I=i.div`
|
|
151
165
|
width: auto;
|
|
152
166
|
margin-right: ${l["spacing-32"]};
|
|
153
167
|
|
|
@@ -156,11 +170,11 @@ import i,{css as r}from"styled-components";import{ExclamationCircleFillIcon as e
|
|
|
156
170
|
flex-direction: column;
|
|
157
171
|
justify-content: center;
|
|
158
172
|
|
|
159
|
-
${
|
|
173
|
+
${g.MaxWidth.lg} {
|
|
160
174
|
margin-right: ${l["spacing-16"]};
|
|
161
175
|
}
|
|
162
|
-
`,
|
|
163
|
-
border-radius: ${
|
|
176
|
+
`,T=i(n)`
|
|
177
|
+
border-radius: ${c.sm};
|
|
164
178
|
border: ${s["width-010"]} ${s.solid} ${d.border};
|
|
165
179
|
|
|
166
180
|
width: 96px;
|
|
@@ -168,9 +182,11 @@ import i,{css as r}from"styled-components";import{ExclamationCircleFillIcon as e
|
|
|
168
182
|
aspect-ratio: 1;
|
|
169
183
|
object-fit: cover;
|
|
170
184
|
|
|
171
|
-
${
|
|
185
|
+
${g.MaxWidth.lg} {
|
|
172
186
|
width: 64px;
|
|
173
187
|
height: 64px;
|
|
174
188
|
}
|
|
175
|
-
|
|
189
|
+
`,q=i(T)`
|
|
190
|
+
border: none;
|
|
191
|
+
`;export{j as ActionContainer,h as Box,$ as CardButton,f as ContentSection,k as DesktopErrorMessage,w as ErrorIcon,b as ExtendedNameSection,u as FileSizeSection,B as IconButton,m as Item,y as ItemNameText,M as MobileErrorMessage,x as NameSection,q as PdfThumbnail,W as Spinner,T as Thumbnail,I as ThumbnailContainer};
|
|
176
192
|
//# sourceMappingURL=file-list-card.styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-list-card.styles.js","sources":["../../../src/file-download/file-list-card/file-list-card.styles.tsx"],"sourcesContent":["import styled, { css } from \"styled-components\";\nimport { ExclamationCircleFillIcon } from \"@lifesg/react-icons/exclamation-circle-fill\";\nimport { IconButton as DSIconButton } from \"../../icon-button\";\nimport { ComponentLoadingSpinner } from \"../../shared/component-loading-spinner\";\nimport { ImageWithFallback } from \"../../shared/image-with-fallback/image-with-fallback\";\nimport { lineClampCss } from \"../../shared/styles\";\nimport { Border, Colour, Font, MediaQuery, Radius, Spacing } from \"../../theme\";\n\n// =============================================================================\n// STYLE INTERFACES\n// =============================================================================\n\ninterface BoxStyleProps {\n $error?: boolean | undefined;\n}\n\ninterface ContentSectionStyleProps {\n $hasThumbnail?: boolean | undefined;\n}\n\n// =============================================================================\n// STYLING\n// =============================================================================\nexport const Item = styled.li`\n display: flex;\n align-items: center;\n\n width: 100%;\n border: none;\n\n &:not(:last-child) {\n margin-bottom: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const Box = styled.div<BoxStyleProps>`\n display: flex;\n align-items: center;\n\n width: 100%;\n padding: ${Spacing[\"spacing-16\"]} ${Spacing[\"spacing-32\"]};\n cursor: pointer;\n\n background: ${Colour[\"bg-primary-subtlest\"]};\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n border-radius: ${Radius[\"sm\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n padding: ${Spacing[\"spacing-16\"]};\n }\n\n &:hover {\n background: ${Colour[\"bg-hover\"]};\n }\n\n ${(props) => {\n if (props.$error) {\n return css`\n background: ${Colour[\"bg-error\"]};\n border-color: ${Colour[\"border-error\"]};\n\n &:hover {\n background: ${Colour[\"bg-error\"]};\n }\n `;\n }\n }}\n`;\n\nexport const ContentSection = styled.div<ContentSectionStyleProps>`\n display: flex;\n flex: 1;\n align-items: center;\n\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n }\n\n ${(props) => {\n if (props.$hasThumbnail) {\n return css`\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: row;\n align-items: center;\n }\n `;\n }\n }}\n`;\n\nexport const NameSection = styled.div`\n display: flex;\n flex: 1;\n flex-direction: column;\n\n width: 100%;\n\n overflow-wrap: break-word;\n word-break: break-all;\n white-space: normal;\n`;\n\nexport const ExtendedNameSection = styled.div`\n display: flex;\n flex: 1;\n align-items: center;\n\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n }\n`;\n\nexport const FileSizeSection = styled.div`\n display: flex;\n justify-content: flex-end;\n\n width: 5rem;\n margin-left: ${Spacing[\"spacing-8\"]};\n\n ${Font[\"body-md-regular\"]}\n color: ${Colour[\"text\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n justify-content: flex-start;\n\n width: 100%;\n margin-left: 0;\n margin-top: ${Spacing[\"spacing-8\"]};\n\n ${lineClampCss(2)}\n }\n`;\n\nexport const ItemNameText = styled.div`\n ${Font[\"body-md-regular\"]}\n color: ${Colour[\"text\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n ${lineClampCss(2)}\n }\n`;\n\nexport const ItemDescriptionText = styled(ItemNameText)`\n ${Font[\"body-md-regular\"]}\n margin-top: ${Spacing[\"spacing-4\"]};\n`;\n\nexport const ErrorIcon = styled(ExclamationCircleFillIcon)`\n height: 1lh;\n width: 1em;\n flex-shrink: 0;\n color: ${Colour[\"icon-error-strong\"]};\n`;\n\nconst BaseErrorMessage = styled.div`\n ${Font[\"body-sm-semibold\"]}\n color: ${Colour[\"text-error\"]};\n`;\n\nexport const DesktopErrorMessage = styled(BaseErrorMessage)`\n margin-top: ${Spacing[\"spacing-8\"]};\n display: flex;\n gap: ${Spacing[\"spacing-4\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n display: none;\n visibility: hidden;\n }\n`;\n\nexport const MobileErrorMessage = styled(BaseErrorMessage)`\n display: none;\n visibility: hidden;\n\n ${MediaQuery.MaxWidth.lg} {\n display: flex;\n gap: ${Spacing[\"spacing-4\"]};\n visibility: visible;\n margin-top: ${Spacing[\"spacing-8\"]};\n }\n`;\n\nexport const Spinner = styled(ComponentLoadingSpinner)`\n color: ${Colour[\"icon-primary\"]};\n`;\n\nexport const ActionContainer = styled.div`\n display: flex;\n justify-content: flex-end;\n align-items: center;\n\n margin-left: ${Spacing[\"spacing-32\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n margin-left: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const IconButton = styled(DSIconButton)`\n min-width: unset;\n\n &:not(:last-child) {\n margin-right: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const ThumbnailContainer = styled.div`\n width: auto;\n margin-right: ${Spacing[\"spacing-32\"]};\n\n display: flex;\n flex-shrink: 0;\n flex-direction: column;\n justify-content: center;\n\n ${MediaQuery.MaxWidth.lg} {\n margin-right: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const Thumbnail = styled(ImageWithFallback)`\n border-radius: ${Radius[\"sm\"]};\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n\n width: 96px;\n height: 96px;\n aspect-ratio: 1;\n object-fit: cover;\n\n ${MediaQuery.MaxWidth.lg} {\n width: 64px;\n height: 64px;\n }\n`;\n"],"names":["Item","styled","li","Spacing","Box","div","Colour","Border","Radius","MediaQuery","MaxWidth","lg","props","$error","css","ContentSection","$hasThumbnail","NameSection","ExtendedNameSection","FileSizeSection","Font","lineClampCss","ItemNameText","ErrorIcon","ExclamationCircleFillIcon","BaseErrorMessage","DesktopErrorMessage","MobileErrorMessage","Spinner","ComponentLoadingSpinner","ActionContainer","IconButton","DSIconButton","ThumbnailContainer","Thumbnail","ImageWithFallback"],"mappings":"ojBAuBO,MAAMA,EAAOC,EAAOC,EAAE;;;;;;;;yBAQJC,EAAQ;;EAIpBC,
|
|
1
|
+
{"version":3,"file":"file-list-card.styles.js","sources":["../../../src/file-download/file-list-card/file-list-card.styles.tsx"],"sourcesContent":["import styled, { css } from \"styled-components\";\nimport { ExclamationCircleFillIcon } from \"@lifesg/react-icons/exclamation-circle-fill\";\nimport { IconButton as DSIconButton } from \"../../icon-button\";\nimport { ComponentLoadingSpinner } from \"../../shared/component-loading-spinner\";\nimport { ImageWithFallback } from \"../../shared/image-with-fallback/image-with-fallback\";\nimport { lineClampCss } from \"../../shared/styles\";\nimport { Border, Colour, Font, MediaQuery, Radius, Spacing } from \"../../theme\";\n\n// =============================================================================\n// STYLE INTERFACES\n// =============================================================================\n\ninterface BoxStyleProps {\n $error?: boolean | undefined;\n}\n\ninterface ContentSectionStyleProps {\n $hasThumbnail?: boolean | undefined;\n}\n\n// =============================================================================\n// STYLING\n// =============================================================================\nexport const Item = styled.li`\n display: flex;\n align-items: center;\n\n width: 100%;\n border: none;\n\n &:not(:last-child) {\n margin-bottom: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const CardButton = styled.button`\n appearance: none;\n padding: 0;\n background: none;\n border: none;\n`;\n\nexport const Box = styled.div<BoxStyleProps>`\n display: flex;\n align-items: center;\n\n width: 100%;\n padding: ${Spacing[\"spacing-16\"]} ${Spacing[\"spacing-32\"]};\n cursor: pointer;\n\n background: ${Colour[\"bg-primary-subtlest\"]};\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n border-radius: ${Radius[\"sm\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n padding: ${Spacing[\"spacing-16\"]};\n }\n\n &:hover {\n background: ${Colour[\"bg-hover\"]};\n }\n\n &:has(${CardButton}:focus-visible) {\n outline: 2px solid ${Colour[\"focus-ring\"]};\n outline-offset: -2px;\n }\n\n ${(props) => {\n if (props.$error) {\n return css`\n background: ${Colour[\"bg-error\"]};\n border-color: ${Colour[\"border-error\"]};\n\n &:hover {\n background: ${Colour[\"bg-error\"]};\n }\n\n &:has(${CardButton}:focus-visible) {\n outline-color: ${Colour[\"border-error-focus\"]};\n }\n `;\n }\n }}\n`;\n\nexport const ContentSection = styled.div<ContentSectionStyleProps>`\n display: flex;\n flex: 1;\n align-items: center;\n\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n }\n\n ${(props) => {\n if (props.$hasThumbnail) {\n return css`\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: row;\n align-items: center;\n }\n `;\n }\n }}\n`;\n\nexport const NameSection = styled.div`\n display: flex;\n flex: 1;\n flex-direction: column;\n\n width: 100%;\n\n overflow-wrap: break-word;\n word-break: break-all;\n white-space: normal;\n`;\n\nexport const ExtendedNameSection = styled.div`\n display: flex;\n flex: 1;\n align-items: center;\n\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n }\n`;\n\nexport const FileSizeSection = styled.div`\n display: flex;\n justify-content: flex-end;\n\n width: 5rem;\n margin-left: ${Spacing[\"spacing-8\"]};\n\n ${Font[\"body-md-regular\"]}\n color: ${Colour[\"text\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n justify-content: flex-start;\n\n width: 100%;\n margin-left: 0;\n margin-top: ${Spacing[\"spacing-8\"]};\n\n ${lineClampCss(2)}\n }\n`;\n\nexport const ItemNameText = styled.div`\n ${Font[\"body-md-regular\"]}\n color: ${Colour[\"text\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n ${lineClampCss(2)}\n }\n`;\n\nexport const ItemDescriptionText = styled(ItemNameText)`\n ${Font[\"body-md-regular\"]}\n margin-top: ${Spacing[\"spacing-4\"]};\n`;\n\nexport const ErrorIcon = styled(ExclamationCircleFillIcon)`\n height: 1lh;\n width: 1em;\n flex-shrink: 0;\n color: ${Colour[\"icon-error-strong\"]};\n`;\n\nconst BaseErrorMessage = styled.div`\n ${Font[\"body-sm-semibold\"]}\n color: ${Colour[\"text-error\"]};\n`;\n\nexport const DesktopErrorMessage = styled(BaseErrorMessage)`\n margin-top: ${Spacing[\"spacing-8\"]};\n display: flex;\n gap: ${Spacing[\"spacing-4\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n display: none;\n visibility: hidden;\n }\n`;\n\nexport const MobileErrorMessage = styled(BaseErrorMessage)`\n display: none;\n visibility: hidden;\n\n ${MediaQuery.MaxWidth.lg} {\n display: flex;\n gap: ${Spacing[\"spacing-4\"]};\n visibility: visible;\n margin-top: ${Spacing[\"spacing-8\"]};\n }\n`;\n\nexport const Spinner = styled(ComponentLoadingSpinner)`\n color: ${Colour[\"icon-primary\"]};\n`;\n\nexport const ActionContainer = styled.div`\n display: flex;\n justify-content: flex-end;\n align-items: center;\n\n margin-left: ${Spacing[\"spacing-32\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n margin-left: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const IconButton = styled(DSIconButton)`\n min-width: unset;\n\n &:not(:last-child) {\n margin-right: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const ThumbnailContainer = styled.div`\n width: auto;\n margin-right: ${Spacing[\"spacing-32\"]};\n\n display: flex;\n flex-shrink: 0;\n flex-direction: column;\n justify-content: center;\n\n ${MediaQuery.MaxWidth.lg} {\n margin-right: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const Thumbnail = styled(ImageWithFallback)`\n border-radius: ${Radius[\"sm\"]};\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n\n width: 96px;\n height: 96px;\n aspect-ratio: 1;\n object-fit: cover;\n\n ${MediaQuery.MaxWidth.lg} {\n width: 64px;\n height: 64px;\n }\n`;\n\nexport const PdfThumbnail = styled(Thumbnail)`\n border: none;\n`;\n"],"names":["Item","styled","li","Spacing","CardButton","button","Box","div","Colour","Border","Radius","MediaQuery","MaxWidth","lg","props","$error","css","ContentSection","$hasThumbnail","NameSection","ExtendedNameSection","FileSizeSection","Font","lineClampCss","ItemNameText","ErrorIcon","ExclamationCircleFillIcon","BaseErrorMessage","DesktopErrorMessage","MobileErrorMessage","Spinner","ComponentLoadingSpinner","ActionContainer","IconButton","DSIconButton","ThumbnailContainer","Thumbnail","ImageWithFallback","PdfThumbnail"],"mappings":"ojBAuBO,MAAMA,EAAOC,EAAOC,EAAE;;;;;;;;yBAQJC,EAAQ;;EAIpBC,EAAaH,EAAOI,MAAM;;;;;EAO1BC,EAAML,EAAOM,GAAkB;;;;;eAK7BJ,EAAQ,iBAAiBA,EAAQ;;;kBAG9BK,EAAO;cACXC,EAAO,gBAAgBA,EAAc,SAAKD,EAAe;qBAClDE,EAAW;;MAE1BC,EAAWC,SAASC;mBACPV,EAAQ;;;;sBAILK,EAAO;;;YAGjBJ;6BACiBI,EAAO;;;;MAI7BM,IACC,GAAIA,EAAMC,OACN,OAAOC,CAAG;8BACQR,EAAO;gCACLA,EAAO;;;kCAGLA,EAAO;;;wBAGjBJ;qCACaI,EAAO;;aAGpC;EAIKS,EAAiBhB,EAAOM,GAA6B;;;;;MAK5DI,EAAWC,SAASC;;;;;;MAMnBC,IACC,GAAIA,EAAMI,cACN,OAAOF,CAAG;kBACJL,EAAWC,SAASC;;;;aAK9B;EAIKM,EAAclB,EAAOM,GAAG;;;;;;;;;;EAYxBa,EAAsBnB,EAAOM,GAAG;;;;;MAKvCI,EAAWC,SAASC;;;;;EAObQ,EAAkBpB,EAAOM,GAAG;;;;;mBAKtBJ,EAAQ;;MAErBmB,EAAK;aACEd,EAAa;;MAEpBG,EAAWC,SAASC;;;;;sBAKJV,EAAQ;;UAEpBoB,EAAa;;EAIVC,EAAevB,EAAOM,GAAG;MAChCe,EAAK;aACEd,EAAa;;MAEpBG,EAAWC,SAASC;UAChBU,EAAa;;EAIYtB,EAAOuB,EAAa;MACjDF,EAAK;kBACOnB,EAAQ;QAGbsB,EAAYxB,EAAOyB,EAA0B;;;;aAI7ClB,EAAO;EAGdmB,EAAmB1B,EAAOM,GAAG;MAC7Be,EAAK;aACEd,EAAO;EAGPoB,EAAsB3B,EAAO0B,EAAiB;kBACzCxB,EAAQ;;WAEfA,EAAQ;;MAEbQ,EAAWC,SAASC;;;;EAMbgB,EAAqB5B,EAAO0B,EAAiB;;;;MAIpDhB,EAAWC,SAASC;;eAEXV,EAAQ;;sBAEDA,EAAQ;;EAIjB2B,EAAU7B,EAAO8B,EAAwB;aACzCvB,EAAO;EAGPwB,EAAkB/B,EAAOM,GAAG;;;;;mBAKtBJ,EAAQ;;MAErBQ,EAAWC,SAASC;uBACHV,EAAQ;;EAIlB8B,EAAahC,EAAOiC,EAAa;;;;wBAItB/B,EAAQ;;EAInBgC,EAAqBlC,EAAOM,GAAG;;oBAExBJ,EAAQ;;;;;;;MAOtBQ,EAAWC,SAASC;wBACFV,EAAQ;;EAInBiC,EAAYnC,EAAOoC,EAAkB;qBAC7B3B,EAAW;cAClBD,EAAO,gBAAgBA,EAAc,SAAKD,EAAe;;;;;;;MAOjEG,EAAWC,SAASC;;;;EAMbyB,EAAerC,EAAOmC,EAAU;;"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { FileItemDownloadProps } from "../types";
|
|
1
|
+
import type { FileItemDownloadProps } from "../types";
|
|
2
2
|
export interface FileListItemProps {
|
|
3
3
|
fileItem: FileItemDownloadProps;
|
|
4
4
|
onDownload: (file: FileItemDownloadProps) => void | Promise<void>;
|
|
5
|
+
onClick?: ((file: FileItemDownloadProps) => void) | undefined;
|
|
5
6
|
}
|
package/file-download/types.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ export interface FileItemDownloadProps {
|
|
|
16
16
|
truncateText?: boolean | undefined;
|
|
17
17
|
/** Indicate if file is ready for download, defaults to true */
|
|
18
18
|
ready?: boolean | undefined;
|
|
19
|
+
/** Name for the card, used when `FileDownload` is given an `onClick`. */
|
|
20
|
+
clickLabel?: string | undefined;
|
|
19
21
|
}
|
|
20
22
|
export type FileDownloadStyle = "bordered" | "no-border";
|
|
21
23
|
export interface FileDownloadProps {
|
|
@@ -30,4 +32,9 @@ export interface FileDownloadProps {
|
|
|
30
32
|
id?: string | undefined;
|
|
31
33
|
/** Called when file item is clicked */
|
|
32
34
|
onDownload: (file: FileItemDownloadProps) => void | Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Called when a file card itself is activated, as opposed to its download button.
|
|
37
|
+
* When omitted, activating the card triggers `onDownload` instead.
|
|
38
|
+
*/
|
|
39
|
+
onClick?: ((file: FileItemDownloadProps) => void) | undefined;
|
|
33
40
|
}
|
package/file-upload/helper.d.ts
CHANGED
|
@@ -1,6 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a file's thumbnail slot should be rendered.
|
|
3
|
+
*
|
|
4
|
+
* - `image` — a thumbnail was supplied; render it at `src`
|
|
5
|
+
* - `pdf-icon` — a PDF with no thumbnail; render the PDF badge borderless
|
|
6
|
+
* - `none` — nothing to show; render no thumbnail slot at all
|
|
7
|
+
*/
|
|
8
|
+
export type FileThumbnailDisplay = {
|
|
9
|
+
type: "image";
|
|
10
|
+
src: string;
|
|
11
|
+
} | {
|
|
12
|
+
type: "pdf-icon";
|
|
13
|
+
} | {
|
|
14
|
+
type: "none";
|
|
15
|
+
};
|
|
1
16
|
export declare namespace FileUploadHelper {
|
|
2
17
|
const PDF_MIME_TYPE = "application/pdf";
|
|
3
18
|
const PDF_ICON_URL = "https://assets.life.gov.sg/react-design-system/img/upload/pdf.svg";
|
|
4
19
|
const formatFileSizeDisplay: (size?: number) => string;
|
|
5
20
|
const isSupportedImageType: (type: string) => boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Decides how a file's thumbnail slot should render, given its MIME type
|
|
23
|
+
* and any thumbnail the consumer supplied.
|
|
24
|
+
*
|
|
25
|
+
* Lives on `FileUploadHelper` so `FileUpload` can adopt it later. Today
|
|
26
|
+
* only `FileDownload` calls it: `FileUpload` still decides this inline in
|
|
27
|
+
* `file-list-item-thumbnail.tsx`, and the two do NOT yet agree — for a
|
|
28
|
+
* non-PDF with no thumbnail this returns `"none"` while `FileUpload`
|
|
29
|
+
* renders an `<img>` with an empty `src`. Do not read this as an invariant
|
|
30
|
+
* the two components already share.
|
|
31
|
+
*
|
|
32
|
+
* Callers render the result with their own markup, because their thumbnails
|
|
33
|
+
* change size at different breakpoints.
|
|
34
|
+
*/
|
|
35
|
+
const resolveThumbnailDisplay: (mimeType: string | undefined, thumbnailImageDataUrl: string | undefined) => FileThumbnailDisplay;
|
|
6
36
|
}
|
package/file-upload/helper.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e;!function(e){e.PDF_MIME_TYPE="application/pdf",e.PDF_ICON_URL="https://assets.life.gov.sg/react-design-system/img/upload/pdf.svg",e.formatFileSizeDisplay=e=>{if(!e||0===e)return"0 KB";const i=Math.floor(Math.log(e)/Math.log(1024));return`${Number(e/Math.pow(1024,i)).toFixed(0)} ${["B","KB","MB","GB","TB","PB","EB","ZB","YB"][i]}`},e.isSupportedImageType=e=>["image/avif","image/gif","image/jpeg","image/png","image/svg+xml","image/webp"].includes(e)}(e||(e={}));export{e as FileUploadHelper};
|
|
1
|
+
var e;!function(e){e.PDF_MIME_TYPE="application/pdf",e.PDF_ICON_URL="https://assets.life.gov.sg/react-design-system/img/upload/pdf.svg",e.formatFileSizeDisplay=e=>{if(!e||0===e)return"0 KB";const i=Math.floor(Math.log(e)/Math.log(1024));return`${Number(e/Math.pow(1024,i)).toFixed(0)} ${["B","KB","MB","GB","TB","PB","EB","ZB","YB"][i]}`},e.isSupportedImageType=e=>["image/avif","image/gif","image/jpeg","image/png","image/svg+xml","image/webp"].includes(e),e.resolveThumbnailDisplay=(i,a)=>a?{type:"image",src:a}:i===e.PDF_MIME_TYPE?{type:"pdf-icon"}:{type:"none"}}(e||(e={}));export{e as FileUploadHelper};
|
|
2
2
|
//# sourceMappingURL=helper.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helper.js","sources":["../../src/file-upload/helper.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"helper.js","sources":["../../src/file-upload/helper.ts"],"sourcesContent":["/**\n * How a file's thumbnail slot should be rendered.\n *\n * - `image` — a thumbnail was supplied; render it at `src`\n * - `pdf-icon` — a PDF with no thumbnail; render the PDF badge borderless\n * - `none` — nothing to show; render no thumbnail slot at all\n */\nexport type FileThumbnailDisplay =\n | { type: \"image\"; src: string }\n | { type: \"pdf-icon\" }\n | { type: \"none\" };\n\nexport namespace FileUploadHelper {\n export const PDF_MIME_TYPE = \"application/pdf\";\n export const PDF_ICON_URL =\n \"https://assets.life.gov.sg/react-design-system/img/upload/pdf.svg\";\n\n // Adapted from https://stackoverflow.com/questions/15900485/correct-way-to-convert-size-in-size-to-kb-mb-gb-in-javascript\n export const formatFileSizeDisplay = (size?: number) => {\n if (!size || size === 0) return \"0 KB\";\n\n const sizes = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\n\n const index: number = Math.floor(Math.log(size) / Math.log(1024));\n\n const value = Number(size / Math.pow(1024, index)).toFixed(0);\n const measurement = sizes[index];\n\n return `${value} ${measurement}`;\n };\n\n export const isSupportedImageType = (type: string) => {\n /** Currently only images supported by html <img> */\n const acceptedImageTypes = [\n \"image/avif\",\n \"image/gif\",\n \"image/jpeg\",\n \"image/png\",\n \"image/svg+xml\",\n \"image/webp\",\n ];\n\n return acceptedImageTypes.includes(type);\n };\n\n /**\n * Decides how a file's thumbnail slot should render, given its MIME type\n * and any thumbnail the consumer supplied.\n *\n * Lives on `FileUploadHelper` so `FileUpload` can adopt it later. Today\n * only `FileDownload` calls it: `FileUpload` still decides this inline in\n * `file-list-item-thumbnail.tsx`, and the two do NOT yet agree — for a\n * non-PDF with no thumbnail this returns `\"none\"` while `FileUpload`\n * renders an `<img>` with an empty `src`. Do not read this as an invariant\n * the two components already share.\n *\n * Callers render the result with their own markup, because their thumbnails\n * change size at different breakpoints.\n */\n export const resolveThumbnailDisplay = (\n mimeType: string | undefined,\n thumbnailImageDataUrl: string | undefined\n ): FileThumbnailDisplay => {\n if (thumbnailImageDataUrl) {\n return { type: \"image\", src: thumbnailImageDataUrl };\n }\n\n if (mimeType === PDF_MIME_TYPE) {\n return { type: \"pdf-icon\" };\n }\n\n return { type: \"none\" };\n };\n}\n"],"names":["FileUploadHelper","PDF_MIME_TYPE","PDF_ICON_URL","formatFileSizeDisplay","size","index","Math","floor","log","Number","pow","toFixed","isSupportedImageType","type","includes","resolveThumbnailDisplay","mimeType","thumbnailImageDataUrl","src"],"mappings":"AAYM,IAAWA,GAAjB,SAAiBA,GACAA,EAAAC,cAAgB,kBAChBD,EAAAE,aACT,oEAGSF,EAAAG,sBAAyBC,IAClC,IAAKA,GAAiB,IAATA,EAAY,MAAO,OAEhC,MAEMC,EAAgBC,KAAKC,MAAMD,KAAKE,IAAIJ,GAAQE,KAAKE,IAAI,OAK3D,MAAO,GAHOC,OAAOL,EAAOE,KAAKI,IAAI,KAAML,IAAQM,QAAQ,MAJ7C,CAAC,IAAK,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,MAKpCN,IAEM,EAGvBL,EAAAY,qBAAwBC,GAEN,CACvB,aACA,YACA,aACA,YACA,gBACA,cAGsBC,SAASD,GAiB1Bb,EAAAe,wBAA0B,CACnCC,EACAC,IAEIA,EACO,CAAEJ,KAAM,QAASK,IAAKD,GAG7BD,IAAahB,EAAAC,cACN,CAAEY,KAAM,YAGZ,CAAEA,KAAM,OAEtB,CA7DD,CAAiBb,IAAAA,EAAgB,CAAA"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { FullscreenImageCarouselProps, FullscreenImageCarouselRef } from "./types";
|
|
2
|
-
export declare const Component: ({ items, initialActiveItemIndex, hideThumbnail, hideNavigation, hideCounter, hideMagnifier, onDelete, onClose, insets, show, ...otherProps }: FullscreenImageCarouselProps, ref: React.Ref<FullscreenImageCarouselRef>) => import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export declare const Component: ({ items, initialActiveItemIndex, hideThumbnail, hideNavigation, hideCounter, hideMagnifier, customActions, onDelete, onClose, insets, topBarRef, show, ...otherProps }: FullscreenImageCarouselProps, ref: React.Ref<FullscreenImageCarouselRef>) => import("react/jsx-runtime").JSX.Element;
|
|
3
3
|
export declare const FullscreenImageCarousel: (props: FullscreenImageCarouselProps & import("react").RefAttributes<FullscreenImageCarouselRef>) => React.ReactElement | null;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{__rest as e}from"../_virtual/_tslib.js";import{jsx as i,jsxs as t,Fragment as n}from"react/jsx-runtime";import{ChevronLeftIcon as l,ChevronRightIcon as r,MagnifierPlusIcon as o,MagnifierMinusIcon as a,CrossIcon as d}from"@lifesg/react-icons";import{BinIcon as s}from"@lifesg/react-icons/bin";import{clearAnnouncer as c,announce as u}from"@react-aria/live-announcer";import{forwardRef as h,useState as m,useRef as v,useMemo as f,useCallback as g,useImperativeHandle as p,useEffect as b}from"react";import{TransformWrapper as
|
|
1
|
+
import{__rest as e}from"../_virtual/_tslib.js";import{jsx as i,jsxs as t,Fragment as n}from"react/jsx-runtime";import{ChevronLeftIcon as l,ChevronRightIcon as r,MagnifierPlusIcon as o,MagnifierMinusIcon as a,CrossIcon as d}from"@lifesg/react-icons";import{BinIcon as s}from"@lifesg/react-icons/bin";import{clearAnnouncer as c,announce as u}from"@react-aria/live-announcer";import{forwardRef as h,useState as m,useRef as v,useMemo as f,useCallback as g,useImperativeHandle as p,useEffect as b,cloneElement as $}from"react";import{TransformWrapper as C,TransformComponent as I}from"react-zoom-pan-pinch";import{ModalV2 as w}from"../modal-v2/index.js";import{useStateCallback as j}from"../shared/hooks/use-state-callback.js";import"../util/calendar-helper.js";import"../util/date-helper.js";import"../util/date-input-helper.js";import"../util/simple-id-generator.js";import"../util/string-helper.js";import{useEventListener as k}from"../util/use-event-listener.js";import{CarouselModalContent as T,ImageGalleryContainer as x,ImageGalleryWrapper as L,ImageGallerySwipe as y,ArrowButton as A,BoxChip as S,Chip as N,ImageGallerySlides as R,ImageGallerySlide as D,FocusableImageRegion as M,SlidePlaceholderImage as z,SlideImage as Z,ThumbnailContainer as B,ThumbnailWrapper as O,ThumbnailItemContainer as W,ThumbnailItem as X,ThumbnailImage as E,TopActionButtons as F,CustomActionButton as P,MagnifierButton as V,DeleteButton as _,CloseButton as H,FileInfoTextWrapper as q,FileInfoFileName as G,FileInfoFileSize as J}from"./fullscreen-image-carousel.style.js";const K=e=>!!e&&"custom"===e.type,Q=(h,Q)=>{var U,Y,{items:ee,initialActiveItemIndex:ie,hideThumbnail:te=!1,hideNavigation:ne=!1,hideCounter:le=!1,hideMagnifier:re=!1,customActions:oe,onDelete:ae,onClose:de,insets:se,topBarRef:ce,show:ue}=h,he=e(h,["items","initialActiveItemIndex","hideThumbnail","hideNavigation","hideCounter","hideMagnifier","customActions","onDelete","onClose","insets","topBarRef","show"]);const[me,ve]=j(null!=ie?ie:0),[fe,ge]=m({}),[pe,be]=m(1),[$e,Ce]=m(),[Ie,we]=m(),je=v(null),ke=v([]),Te=v([]),xe=v(null),Le=$e&&Ie?$e-Ie:0,ye=ee[me],Ae=null!==(Y=null!==(U=null==ye?void 0:ye.customActions)&&void 0!==U?U:oe)&&void 0!==Y?Y:[],Se=ee.some((e=>{var i;return K(e)&&!!(null===(i=e.itemLabel)||void 0===i?void 0:i.trim())})),Ne=Se?"item":"image",Re=f((()=>ee.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())}))),[ee]),De=g((e=>{var i,t;const n=ee[e],l=Se?"Item":"Image",r=K(n)?(null===(i=n.itemLabel)||void 0===i?void 0:i.trim())||"":(null===(t=n.alt)||void 0===t?void 0:t.trim())||"",o=`${l} ${e+1} of ${ee.length}.`;return r?`${r}. ${o}`:o}),[ee,Se]);p(Q,(()=>({currentItemIndex:me,setCurrentItem:Ee,goToPrevItem:We,goToNextItem:Xe}))),k("keydown",(function(e){"ArrowRight"===e.key?Xe():"ArrowLeft"===e.key?We():"Escape"===e.key&&(null==de||de())}),"document"),b((()=>{var e;ue&&(null===(e=xe.current)||void 0===e||e.focus())}),[ue]),b((()=>{0!==ee.length?me>ee.length-1&&ve(ee.length-1):ve(0)}),[me,ee.length,ve]),b((()=>{var e,i;null===(i=null===(e=ke.current)||void 0===e?void 0:e[me])||void 0===i||i.scrollIntoView({behavior:"smooth",inline:"center"}),be(1)}),[me]);const Me=e=>{be(e.state.scale)},ze=()=>{ye&&ae&&ae(ye,me)};const Ze=()=>{var e,i,t,n;if(1===pe){const t=Oe();null===(i=null===(e=Te.current)||void 0===e?void 0:e[me])||void 0===i||i.centerView(t),be(null!=t?t:1)}else be(1),null===(n=null===(t=Te.current)||void 0===t?void 0:t[me])||void 0===n||n.resetTransform()},Be=({src:e,height:i,width:t})=>{ge((n=>Object.assign(Object.assign({},n),{[e]:{height:i,width:t}})))},Oe=()=>{if(!ye||K(ye))return;const e=fe[ye.src];if(je.current&&e){const{clientHeight:i,clientWidth:t}=je.current,{width:n,height:l}=e,r=l/n<i/t;return n<t&&l<i?r?t/n:i/l:r?i/(l/(n/t)):t/(n/(l/i))}},We=()=>{var e,i;null===(i=null===(e=Te.current)||void 0===e?void 0:e[me])||void 0===i||i.resetTransform(),ve((e=>0===e?ee.length-1:e-1),(e=>{c("polite"),u(De(e),"polite")}))},Xe=()=>{var e,i;null===(i=null===(e=Te.current)||void 0===e?void 0:e[me])||void 0===i||i.resetTransform(),ve((e=>e===ee.length-1?0:e+1),(e=>{c("polite"),u(De(e),"polite")}))},Ee=e=>{var i,t;null===(t=null===(i=Te.current)||void 0===i?void 0:i[me])||void 0===t||t.resetTransform(),ve(e)},Fe=()=>{const{fileName:e,fileSize:n}=null!=ye?ye:{},l=null==e?void 0:e.trim(),r=null==n?void 0:n.trim();return t(q,{$centerContent:!r,"aria-live":"polite","aria-atomic":"true","data-testid":"file-info-bar",children:[l&&i(G,{weight:"semibold","data-testid":"file-info-name",children:l}),r&&i(J,{"data-testid":"file-info-size",children:r})]})};return i(w,Object.assign({},he,{"data-testid":"image-carousel-modal","aria-label":Se?"Carousel":"Image carousel",show:ue,disableInitialFocus:!0,children:t(T,{children:[t(x,{children:[t(L,{children:[i(y,{ref:je,onTouchStart:e=>{pe<=1&&Ce(e.touches[0].clientX)},onTouchMove:e=>{!$e||pe>1||we(e.touches[0].clientX)},onTouchEnd:()=>{je.current&&(Math.abs(Le)>je.current.offsetWidth/3&&(Le>0?Xe():We()),Ce(void 0),we(void 0))},children:i(R,{style:{transform:`translateX(calc(${100*-me}% - ${Le}px))`},children:ee.map(((e,t)=>{const n=t===me,l=Math.abs(t-me)<=1||0===me&&t===ee.length-1||me===ee.length-1&&0===t;return i(D,{"data-testid":"slide-item",children:i(M,{ref:n?xe:null,tabIndex:n?0:-1,children:K(e)?l?e.renderContent():i(z,{}):i(C,{ref:e=>Te.current[t]=e,panning:{disabled:pe<=1},initialScale:1,onZoom:Me,onZoomStop:Me,onWheel:Me,children:i(I,{children:i(Z,{src:e.src,alt:De(t),placeholder:i(z,{}),fit:"scale-down",retrieveImageDimension:!0,setDimension:Be})})})})},t)}))})}),!ne&&t(n,{children:[i(A,{"aria-label":`Previous ${Ne}`,"data-testid":"prev-btn",$position:"left",onClick:We,$insetLeft:null==se?void 0:se.left,$insetRight:null==se?void 0:se.right,children:i(l,{"aria-hidden":!0})}),i(A,{"aria-label":`Next ${Ne}`,"data-testid":"forward-btn",$position:"right",onClick:Xe,$insetLeft:null==se?void 0:se.left,$insetRight:null==se?void 0:se.right,children:i(r,{"aria-hidden":!0})})]}),!le&&i(S,{"aria-hidden":"true",children:i(N,{weight:"semibold",children:`${me+1}/${ee.length}`})})]}),!te&&i(B,{$insetBottom:null==se?void 0:se.bottom,"aria-hidden":"true",children:i(O,{children:ee.map(((e,t)=>{var n;const l=K(e)?e.thumbnailSrc:null!==(n=e.thumbnailSrc)&&void 0!==n?n:e.src;return i(W,{children:i(X,{"data-testid":"thumbnail-item",$active:t===me,onClick:()=>Ee(t),ref:e=>ke.current[t]=e,children:l?i(E,{src:l,alt:`Thumbnail ${t+1}`,fit:"cover"}):i(z,{})})},t)}))})})]}),(()=>{var e;return t(F,{ref:ce,$hasFileInfo:Re,$insetTop:null==se?void 0:se.top,$insetLeft:null==se?void 0:se.left,$insetRight:null==se?void 0:se.right,children:[Re&&Fe(),Ae.map(((e,t)=>i(P,{"aria-label":e.ariaLabel,"data-testid":e["data-testid"],onClick:()=>(e=>{ye&&e.onClick(ye,me)})(e),children:$(e.icon,{"aria-hidden":!0})},t))),!re&&!K(ye)&&i(V,{"aria-label":1===pe?"Zoom in":"Zoom out",onClick:Ze,children:i(1===pe?o:a,{"aria-hidden":!0})}),ae&&i(_,{"aria-label":`Delete ${K(ye)&&(null===(e=ye.itemLabel)||void 0===e?void 0:e.trim())||"image"}`,"data-testid":"delete-btn",onClick:ze,children:i(s,{"aria-hidden":!0})}),i(H,{"aria-label":Se?"Close carousel":"Close image carousel",onClick:de,children:i(d,{"aria-hidden":!0})})]})})()]})}))},U=h(Q);export{Q as Component,U as FullscreenImageCarousel};
|
|
2
2
|
//# sourceMappingURL=fullscreen-image-carousel.js.map
|