@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.
Files changed (60) hide show
  1. package/accordion/accordion-item.js +1 -1
  2. package/accordion/accordion-item.js.map +1 -1
  3. package/accordion/types.d.ts +7 -0
  4. package/button/button.style.js +20 -19
  5. package/button/button.style.js.map +1 -1
  6. package/cjs/accordion/accordion-item.js +1 -1
  7. package/cjs/accordion/accordion-item.js.map +1 -1
  8. package/cjs/button/button.style.js +3 -2
  9. package/cjs/button/button.style.js.map +1 -1
  10. package/cjs/file-download/file-download.js +1 -1
  11. package/cjs/file-download/file-download.js.map +1 -1
  12. package/cjs/file-download/file-list-card/file-list-card.js +1 -1
  13. package/cjs/file-download/file-list-card/file-list-card.js.map +1 -1
  14. package/cjs/file-download/file-list-card/file-list-card.styles.js +75 -59
  15. package/cjs/file-download/file-list-card/file-list-card.styles.js.map +1 -1
  16. package/cjs/file-upload/helper.js +1 -1
  17. package/cjs/file-upload/helper.js.map +1 -1
  18. package/cjs/fullscreen-image-carousel/fullscreen-image-carousel.js +1 -1
  19. package/cjs/fullscreen-image-carousel/fullscreen-image-carousel.js.map +1 -1
  20. package/cjs/fullscreen-image-carousel/fullscreen-image-carousel.style.js +19 -19
  21. package/cjs/fullscreen-image-carousel/fullscreen-image-carousel.style.js.map +1 -1
  22. package/cjs/navbar/menu.js +1 -1
  23. package/cjs/navbar/menu.js.map +1 -1
  24. package/cjs/navbar/menu.styles.js +1 -1
  25. package/cjs/navbar/menu.styles.js.map +1 -1
  26. package/cjs/navbar/navbar-items.js +1 -1
  27. package/cjs/navbar/navbar-items.js.map +1 -1
  28. package/cjs/navbar/navbar-items.styles.js +20 -21
  29. package/cjs/navbar/navbar-items.styles.js.map +1 -1
  30. package/file-download/file-download.d.ts +1 -1
  31. package/file-download/file-download.js +1 -1
  32. package/file-download/file-download.js.map +1 -1
  33. package/file-download/file-list-card/file-list-card.d.ts +1 -1
  34. package/file-download/file-list-card/file-list-card.js +1 -1
  35. package/file-download/file-list-card/file-list-card.js.map +1 -1
  36. package/file-download/file-list-card/file-list-card.styles.d.ts +8 -0
  37. package/file-download/file-list-card/file-list-card.styles.js +53 -37
  38. package/file-download/file-list-card/file-list-card.styles.js.map +1 -1
  39. package/file-download/file-list-card/types.d.ts +2 -1
  40. package/file-download/types.d.ts +7 -0
  41. package/file-upload/helper.d.ts +30 -0
  42. package/file-upload/helper.js +1 -1
  43. package/file-upload/helper.js.map +1 -1
  44. package/fullscreen-image-carousel/fullscreen-image-carousel.d.ts +1 -1
  45. package/fullscreen-image-carousel/fullscreen-image-carousel.js +1 -1
  46. package/fullscreen-image-carousel/fullscreen-image-carousel.js.map +1 -1
  47. package/fullscreen-image-carousel/fullscreen-image-carousel.style.d.ts +7 -0
  48. package/fullscreen-image-carousel/fullscreen-image-carousel.style.js +21 -21
  49. package/fullscreen-image-carousel/fullscreen-image-carousel.style.js.map +1 -1
  50. package/fullscreen-image-carousel/types.d.ts +16 -0
  51. package/navbar/menu.d.ts +2 -1
  52. package/navbar/menu.js +1 -1
  53. package/navbar/menu.js.map +1 -1
  54. package/navbar/menu.styles.js +3 -3
  55. package/navbar/menu.styles.js.map +1 -1
  56. package/navbar/navbar-items.js +1 -1
  57. package/navbar/navbar-items.js.map +1 -1
  58. package/navbar/navbar-items.styles.js +30 -31
  59. package/navbar/navbar-items.styles.js.map +1 -1
  60. package/package.json +1 -1
@@ -1,2 +1,2 @@
1
- import{__awaiter as e}from"../../_virtual/_tslib.js";import{jsx as r,jsxs as i,Fragment as t}from"react/jsx-runtime";import{DownloadIcon as n}from"@lifesg/react-icons";import{memo as l,useState as a,useContext as o,useRef as d,useEffect as s}from"react";import{r as m}from"../../external/react-responsive/dist/react-responsive.js";import{ThemeContext as c}from"styled-components";import{FileUploadHelper as h}from"../../file-upload/helper.js";import{Breakpoint as p}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 u}from"../../util/string-helper.js";import"@react-aria/live-announcer";import{Item as f,Box as g,ContentSection as y,ActionContainer as j,IconButton as w,Spinner as b,ThumbnailContainer as v,Thumbnail as x,ExtendedNameSection as $,NameSection as T,FileSizeSection as z,MobileErrorMessage as S,ErrorIcon as D,ItemNameText as C,DesktopErrorMessage as I}from"./file-list-card.styles.js";const M=l((({fileItem:l,onDownload:M})=>{const{id:_,name:k,size:B,errorMessage:F,thumbnailImageDataUrl:L,truncateText:Q=!0,ready:R=!0}=l,[U,W]=a(!1),[q,A]=a(!1),E=h.formatFileSizeDisplay(B),G=o(c),H=p["sm-max"]({theme:G}),J=m.useMediaQuery({maxWidth:H}),[K,N]=a(),O=d(null);s((()=>{O.current&&N(J?P(k):k)}),[k,J]);const P=e=>{if(!Q)return e;const r=O&&O.current?O.current.getBoundingClientRect().width:0;return u.truncateTwoLines(e,r,16,1.5)},V=()=>i(t,{children:[r(C,{ref:O,children:K}),q&&i(I,{children:[r(D,{"aria-hidden":!0}),F||"Something went wrong"]})]});return r(f,{"data-testid":_,children:i(g,{onClick:()=>e(void 0,void 0,void 0,(function*(){if(R&&!U){W(!0);try{A(!1),yield M(l)}catch(e){A(!0)}finally{W(!1)}}})),$error:q,children:[(()=>{let e;return e=i(t,L?{children:[r(v,{"data-testid":`${_}-thumbnail`,children:r(x,{"data-testid":`${_}-thumbnail-image`,src:L})}),i($,{children:[r(T,{children:V()}),r(z,{children:E||"-"}),q&&i(S,{children:[r(D,{"aria-hidden":!0}),F||"Something went wrong"]})]})]}:{children:[r(T,{children:V()}),r(z,{children:E||"-"}),q&&i(S,{children:[r(D,{"aria-hidden":!0}),F||"Something went wrong"]})]}),r(y,{$hasThumbnail:!!L,children:e})})(),r(j,{children:r(w,{"data-testid":`${_}-download-button`,type:"button",styleType:"light",sizeType:"small","aria-label":`download ${k}`,children:U||!R?r(b,{size:16,"aria-hidden":!0}):r(n,{"aria-hidden":!0})})})]})})}));export{M as FileListCard};
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 r}from"styled-components";import{ExclamationCircleFillIcon as e}from"@lifesg/react-icons/exclamation-circle-fill";import{IconButton as t}from"../../icon-button/icon-button.js";import{ComponentLoadingSpinner as n}from"../../shared/component-loading-spinner/component-loading-spinner.js";import{ImageWithFallback as o}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 g,MediaQuery as c,Font as m}from"../../theme/index.js";const p=i.li`
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.div`
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: ${g.sm};
26
+ border-radius: ${c.sm};
22
27
 
23
- ${c.MaxWidth.lg} {
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
- ${i=>{if(i.$error)return r`
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
- `,h=i.div`
53
+ `,f=i.div`
40
54
  display: flex;
41
55
  flex: 1;
42
56
  align-items: center;
43
57
 
44
- ${c.MaxWidth.lg} {
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 r`
51
- ${c.MaxWidth.lg} {
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
- `,f=i.div`
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
- `,x=i.div`
80
+ `,b=i.div`
67
81
  display: flex;
68
82
  flex: 1;
69
83
  align-items: center;
70
84
 
71
- ${c.MaxWidth.lg} {
85
+ ${g.MaxWidth.lg} {
72
86
  flex-direction: column;
73
87
  align-items: flex-start;
74
88
  width: 100%;
75
89
  }
76
- `,b=i.div`
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
- ${m["body-md-regular"]}
97
+ ${p["body-md-regular"]}
84
98
  color: ${d.text};
85
99
 
86
- ${c.MaxWidth.lg} {
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
- `,u=i.div`
96
- ${m["body-md-regular"]}
109
+ `,y=i.div`
110
+ ${p["body-md-regular"]}
97
111
  color: ${d.text};
98
112
 
99
- ${c.MaxWidth.lg} {
113
+ ${g.MaxWidth.lg} {
100
114
  ${a(2)}
101
115
  }
102
- `;i(u)`
103
- ${m["body-md-regular"]}
116
+ `;i(y)`
117
+ ${p["body-md-regular"]}
104
118
  margin-top: ${l["spacing-4"]};
105
- `;const y=i(e)`
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
- `,w=i.div`
111
- ${m["body-sm-semibold"]}
124
+ `,v=i.div`
125
+ ${p["body-sm-semibold"]}
112
126
  color: ${d["text-error"]};
113
- `,v=i(w)`
127
+ `,k=i(v)`
114
128
  margin-top: ${l["spacing-8"]};
115
129
  display: flex;
116
130
  gap: ${l["spacing-4"]};
117
131
 
118
- ${c.MaxWidth.lg} {
132
+ ${g.MaxWidth.lg} {
119
133
  display: none;
120
134
  visibility: hidden;
121
135
  }
122
- `,k=i(w)`
136
+ `,M=i(v)`
123
137
  display: none;
124
138
  visibility: hidden;
125
139
 
126
- ${c.MaxWidth.lg} {
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
- `,M=i(n)`
146
+ `,W=i(o)`
133
147
  color: ${d["icon-primary"]};
134
- `,W=i.div`
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
- ${c.MaxWidth.lg} {
155
+ ${g.MaxWidth.lg} {
142
156
  margin-left: ${l["spacing-16"]};
143
157
  }
144
- `,j=i(t)`
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
- `,B=i.div`
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
- ${c.MaxWidth.lg} {
173
+ ${g.MaxWidth.lg} {
160
174
  margin-right: ${l["spacing-16"]};
161
175
  }
162
- `,I=i(o)`
163
- border-radius: ${g.sm};
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
- ${c.MaxWidth.lg} {
185
+ ${g.MaxWidth.lg} {
172
186
  width: 64px;
173
187
  height: 64px;
174
188
  }
175
- `;export{W as ActionContainer,$ as Box,h as ContentSection,v as DesktopErrorMessage,y as ErrorIcon,x as ExtendedNameSection,b as FileSizeSection,j as IconButton,p as Item,u as ItemNameText,k as MobileErrorMessage,f as NameSection,M as Spinner,I as Thumbnail,B as ThumbnailContainer};
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,EAAMH,EAAOI,GAAkB;;;;;eAK7BF,EAAQ,iBAAiBA,EAAQ;;;kBAG9BG,EAAO;cACXC,EAAO,gBAAgBA,EAAc,SAAKD,EAAe;qBAClDE,EAAW;;MAE1BC,EAAWC,SAASC;mBACPR,EAAQ;;;;sBAILG,EAAO;;;MAGtBM,IACC,GAAIA,EAAMC,OACN,OAAOC,CAAG;8BACQR,EAAO;gCACLA,EAAO;;;kCAGLA,EAAO;;aAGjC;EAIKS,EAAiBd,EAAOI,GAA6B;;;;;MAK5DI,EAAWC,SAASC;;;;;;MAMnBC,IACC,GAAIA,EAAMI,cACN,OAAOF,CAAG;kBACJL,EAAWC,SAASC;;;;aAK9B;EAIKM,EAAchB,EAAOI,GAAG;;;;;;;;;;EAYxBa,EAAsBjB,EAAOI,GAAG;;;;;MAKvCI,EAAWC,SAASC;;;;;EAObQ,EAAkBlB,EAAOI,GAAG;;;;;mBAKtBF,EAAQ;;MAErBiB,EAAK;aACEd,EAAa;;MAEpBG,EAAWC,SAASC;;;;;sBAKJR,EAAQ;;UAEpBkB,EAAa;;EAIVC,EAAerB,EAAOI,GAAG;MAChCe,EAAK;aACEd,EAAa;;MAEpBG,EAAWC,SAASC;UAChBU,EAAa;;EAIYpB,EAAOqB,EAAa;MACjDF,EAAK;kBACOjB,EAAQ;QAGboB,EAAYtB,EAAOuB,EAA0B;;;;aAI7ClB,EAAO;EAGdmB,EAAmBxB,EAAOI,GAAG;MAC7Be,EAAK;aACEd,EAAO;EAGPoB,EAAsBzB,EAAOwB,EAAiB;kBACzCtB,EAAQ;;WAEfA,EAAQ;;MAEbM,EAAWC,SAASC;;;;EAMbgB,EAAqB1B,EAAOwB,EAAiB;;;;MAIpDhB,EAAWC,SAASC;;eAEXR,EAAQ;;sBAEDA,EAAQ;;EAIjByB,EAAU3B,EAAO4B,EAAwB;aACzCvB,EAAO;EAGPwB,EAAkB7B,EAAOI,GAAG;;;;;mBAKtBF,EAAQ;;MAErBM,EAAWC,SAASC;uBACHR,EAAQ;;EAIlB4B,EAAa9B,EAAO+B,EAAa;;;;wBAItB7B,EAAQ;;EAInB8B,EAAqBhC,EAAOI,GAAG;;oBAExBF,EAAQ;;;;;;;MAOtBM,EAAWC,SAASC;wBACFR,EAAQ;;EAInB+B,EAAYjC,EAAOkC,EAAkB;qBAC7B3B,EAAW;cAClBD,EAAO,gBAAgBA,EAAc,SAAKD,EAAe;;;;;;;MAOjEG,EAAWC,SAASC;;;;"}
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
  }
@@ -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
  }
@@ -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
  }
@@ -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":["export 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"],"names":["FileUploadHelper","PDF_MIME_TYPE","PDF_ICON_URL","formatFileSizeDisplay","size","index","Math","floor","log","Number","pow","toFixed","isSupportedImageType","type","includes"],"mappings":"AAAM,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,EAE1C,CAhCD,CAAiBb,IAAAA,EAAgB,CAAA"}
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 $,TransformComponent as I}from"react-zoom-pan-pinch";import{ModalV2 as C}from"../modal-v2/index.js";import{useStateCallback as w}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 j}from"../util/use-event-listener.js";import{CarouselModalContent as T,ImageGalleryContainer as k,ImageGalleryWrapper as x,ImageGallerySwipe as y,ArrowButton as L,BoxChip as S,Chip as N,TopActionButtons as D,MagnifierButton as M,DeleteButton as z,CloseButton as A,ImageGallerySlides as R,ImageGallerySlide as Z,FocusableImageRegion as O,SlidePlaceholderImage as W,SlideImage as X,ThumbnailContainer as E,ThumbnailWrapper as F,ThumbnailItemContainer as P,ThumbnailItem as V,ThumbnailImage as _,FileInfoTextWrapper as B,FileInfoFileName as H,FileInfoFileSize as q}from"./fullscreen-image-carousel.style.js";const G=e=>!!e&&"custom"===e.type,J=(h,J)=>{var K,{items:Q,initialActiveItemIndex:U,hideThumbnail:Y=!1,hideNavigation:ee=!1,hideCounter:ie=!1,hideMagnifier:te=!1,onDelete:ne,onClose:le,insets:re,show:oe}=h,ae=e(h,["items","initialActiveItemIndex","hideThumbnail","hideNavigation","hideCounter","hideMagnifier","onDelete","onClose","insets","show"]);const[de,se]=w(null!=U?U:0),[ce,ue]=m({}),[he,me]=m(1),[ve,fe]=m(),[ge,pe]=m(),be=v(null),$e=v([]),Ie=v([]),Ce=v(null),we=ve&&ge?ve-ge:0,je=Q[de],Te=Q.some((e=>{var i;return G(e)&&!!(null===(i=e.itemLabel)||void 0===i?void 0:i.trim())})),ke=Te?"item":"image",xe=f((()=>Q.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())}))),[Q]),ye=g((e=>{var i,t;const n=Q[e],l=Te?"Item":"Image",r=G(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 ${Q.length}.`;return r?`${r}. ${o}`:o}),[Q,Te]);p(J,(()=>({currentItemIndex:de,setCurrentItem:ze,goToPrevItem:De,goToNextItem:Me}))),j("keydown",(function(e){"ArrowRight"===e.key?Me():"ArrowLeft"===e.key?De():"Escape"===e.key&&(null==le||le())}),"document"),b((()=>{var e;oe&&(null===(e=Ce.current)||void 0===e||e.focus())}),[oe]),b((()=>{0!==Q.length?de>Q.length-1&&se(Q.length-1):se(0)}),[de,Q.length,se]),b((()=>{var e,i;null===(i=null===(e=$e.current)||void 0===e?void 0:e[de])||void 0===i||i.scrollIntoView({behavior:"smooth",inline:"center"}),me(1)}),[de]);const Le=e=>{me(e.state.scale)};const Se=({src:e,height:i,width:t})=>{ue((n=>Object.assign(Object.assign({},n),{[e]:{height:i,width:t}})))},Ne=()=>{if(!je||G(je))return;const e=ce[je.src];if(be.current&&e){const{clientHeight:i,clientWidth:t}=be.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))}},De=()=>{var e,i;null===(i=null===(e=Ie.current)||void 0===e?void 0:e[de])||void 0===i||i.resetTransform(),se((e=>0===e?Q.length-1:e-1),(e=>{c("polite"),u(ye(e),"polite")}))},Me=()=>{var e,i;null===(i=null===(e=Ie.current)||void 0===e?void 0:e[de])||void 0===i||i.resetTransform(),se((e=>e===Q.length-1?0:e+1),(e=>{c("polite"),u(ye(e),"polite")}))},ze=e=>{var i,t;null===(t=null===(i=Ie.current)||void 0===i?void 0:i[de])||void 0===t||t.resetTransform(),se(e)};return i(C,Object.assign({},ae,{"data-testid":"image-carousel-modal","aria-label":Te?"Carousel":"Image carousel",show:oe,disableInitialFocus:!0,children:t(T,{children:[t(k,{children:[t(x,{children:[i(y,{ref:be,onTouchStart:e=>{he<=1&&fe(e.touches[0].clientX)},onTouchMove:e=>{!ve||he>1||pe(e.touches[0].clientX)},onTouchEnd:()=>{be.current&&(Math.abs(we)>be.current.offsetWidth/3&&(we>0?Me():De()),fe(void 0),pe(void 0))},children:i(R,{style:{transform:`translateX(calc(${100*-de}% - ${we}px))`},children:Q.map(((e,t)=>{const n=t===de,l=Math.abs(t-de)<=1||0===de&&t===Q.length-1||de===Q.length-1&&0===t;return i(Z,{"data-testid":"slide-item",children:i(O,{ref:n?Ce:null,tabIndex:n?0:-1,children:G(e)?l?e.renderContent():i(W,{}):i($,{ref:e=>Ie.current[t]=e,panning:{disabled:he<=1},initialScale:1,onZoom:Le,onZoomStop:Le,onWheel:Le,children:i(I,{children:i(X,{src:e.src,alt:ye(t),placeholder:i(W,{}),fit:"scale-down",retrieveImageDimension:!0,setDimension:Se})})})})},t)}))})}),!ee&&t(n,{children:[i(L,{"aria-label":`Previous ${ke}`,"data-testid":"prev-btn",$position:"left",onClick:De,$insetLeft:null==re?void 0:re.left,$insetRight:null==re?void 0:re.right,children:i(l,{"aria-hidden":!0})}),i(L,{"aria-label":`Next ${ke}`,"data-testid":"forward-btn",$position:"right",onClick:Me,$insetLeft:null==re?void 0:re.left,$insetRight:null==re?void 0:re.right,children:i(r,{"aria-hidden":!0})})]}),!ie&&i(S,{"aria-hidden":"true",children:i(N,{weight:"semibold",children:`${de+1}/${Q.length}`})})]}),!Y&&i(E,{$insetBottom:null==re?void 0:re.bottom,"aria-hidden":"true",children:i(F,{children:Q.map(((e,t)=>{var n;const l=G(e)?e.thumbnailSrc:null!==(n=e.thumbnailSrc)&&void 0!==n?n:e.src;return i(P,{children:i(V,{"data-testid":"thumbnail-item",$active:t===de,onClick:()=>ze(t),ref:e=>$e.current[t]=e,children:l?i(_,{src:l,alt:`Thumbnail ${t+1}`,fit:"cover"}):i(W,{})})},t)}))})})]}),t(D,{$hasFileInfo:xe,$insetTop:null==re?void 0:re.top,$insetLeft:null==re?void 0:re.left,$insetRight:null==re?void 0:re.right,children:[xe&&(()=>{const{fileName:e,fileSize:n}=null!=je?je:{},l=null==e?void 0:e.trim(),r=null==n?void 0:n.trim();return t(B,{$centerContent:!r,"aria-live":"polite","aria-atomic":"true","data-testid":"file-info-bar",children:[l&&i(H,{weight:"semibold","data-testid":"file-info-name",children:l}),r&&i(q,{"data-testid":"file-info-size",children:r})]})})(),!te&&!G(je)&&i(M,{"aria-label":1===he?"Zoom in":"Zoom out",onClick:()=>{var e,i,t,n;if(1===he){const t=Ne();null===(i=null===(e=Ie.current)||void 0===e?void 0:e[de])||void 0===i||i.centerView(t),me(null!=t?t:1)}else me(1),null===(n=null===(t=Ie.current)||void 0===t?void 0:t[de])||void 0===n||n.resetTransform()},children:i(1===he?o:a,{"aria-hidden":!0})}),ne&&i(z,{"aria-label":`Delete ${G(je)&&(null===(K=je.itemLabel)||void 0===K?void 0:K.trim())||"image"}`,"data-testid":"delete-btn",onClick:()=>{je&&ne&&ne(je,de)},children:i(s,{"aria-hidden":!0})}),i(A,{"aria-label":Te?"Close carousel":"Close image carousel",onClick:le,children:i(d,{"aria-hidden":!0})})]})]})}))},K=h(J);export{J as Component,K as FullscreenImageCarousel};
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