@lifesg/react-design-system 4.0.0-alpha.12 → 4.0.0-alpha.13
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/breadcrumb/breadcrumb.js +1 -1
- package/breadcrumb/breadcrumb.js.map +1 -1
- package/breadcrumb/breadcrumb.styles.d.ts +0 -8
- package/breadcrumb/breadcrumb.styles.js +1 -1
- package/breadcrumb/breadcrumb.styles.js.map +1 -1
- package/breadcrumb/breadcrumb.styles_1blzn8n.css +7 -0
- package/breadcrumb/types.d.ts +2 -13
- package/cjs/breadcrumb/breadcrumb.js +1 -1
- package/cjs/breadcrumb/breadcrumb.js.map +1 -1
- package/cjs/breadcrumb/breadcrumb.styles.js +1 -1
- package/cjs/breadcrumb/breadcrumb.styles.js.map +1 -1
- package/cjs/breadcrumb/breadcrumb.styles_1blzn8n.css +7 -0
- package/cjs/drawer/drawer.js +1 -1
- package/cjs/drawer/drawer.js.map +1 -1
- package/cjs/drawer/drawer.styles.js +1 -1
- package/cjs/drawer/drawer.styles.js.map +1 -1
- package/{drawer/drawer.styles_94hx3y.css → cjs/drawer/drawer.styles_a4bwe0.css} +6 -3
- package/cjs/file-upload/file-list/file-list.js +1 -1
- package/cjs/file-upload/file-list/file-list.js.map +1 -1
- package/cjs/file-upload/file-list/file-list.styles.js +1 -1
- package/cjs/file-upload/file-list/file-list.styles.js.map +1 -1
- package/cjs/file-upload/file-list/file-list.styles_1xbypnh.css +2 -0
- package/cjs/file-upload/file-list-item/file-item-actions.js +2 -0
- package/cjs/file-upload/file-list-item/file-item-actions.js.map +1 -0
- package/cjs/file-upload/file-list-item/file-item-actions.styles.js +2 -0
- package/cjs/file-upload/file-list-item/file-item-actions.styles.js.map +1 -0
- package/cjs/file-upload/file-list-item/file-item-actions.styles_1quulgy.css +8 -0
- package/cjs/file-upload/file-list-item/file-item-details.js +2 -0
- package/cjs/file-upload/file-list-item/file-item-details.js.map +1 -0
- package/cjs/file-upload/file-list-item/file-item-details.styles.js +2 -0
- package/cjs/file-upload/file-list-item/file-item-details.styles.js.map +1 -0
- package/cjs/file-upload/file-list-item/file-item-details.styles_1ce9akx.css +7 -0
- package/cjs/file-upload/file-list-item/file-list-item.js +1 -1
- package/cjs/file-upload/file-list-item/file-list-item.js.map +1 -1
- package/cjs/file-upload/file-list-item/file-list-item.styles.js +1 -1
- package/cjs/file-upload/file-list-item/file-list-item.styles.js.map +1 -1
- package/cjs/file-upload/file-list-item/file-list-item.styles_x3a500.css +10 -0
- package/cjs/file-upload/file-list-item/use-truncated-name.js +2 -0
- package/cjs/file-upload/file-list-item/use-truncated-name.js.map +1 -0
- package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.js +1 -1
- package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.js.map +1 -1
- package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js +1 -1
- package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js.map +1 -1
- package/cjs/local-nav/local-nav-dropdown/{local-nav-dropdown.styles_uhd4xl.css → local-nav-dropdown.styles_kpel1m.css} +9 -6
- package/cjs/local-nav/local-nav-menu/local-nav-menu.js +1 -1
- package/cjs/local-nav/local-nav-menu/local-nav-menu.js.map +1 -1
- package/cjs/local-nav/local-nav-menu/local-nav-menu.styles.js +1 -1
- package/cjs/local-nav/local-nav-menu/local-nav-menu.styles.js.map +1 -1
- package/cjs/local-nav/local-nav-menu/local-nav-menu.styles_67fcyc.css +8 -0
- package/cjs/menu/menu-content.js +1 -1
- package/cjs/menu/menu-content.js.map +1 -1
- package/cjs/menu/menu-content.styles.js +1 -1
- package/cjs/menu/menu-content.styles.js.map +1 -1
- package/cjs/menu/menu-content.styles_1r8oxtk.css +5 -0
- package/cjs/menu/menu-item.styles.js +1 -1
- package/cjs/menu/menu-item.styles.js.map +1 -1
- package/cjs/menu/{menu-item.styles_liyed8.css → menu-item.styles_eut2j9.css} +1 -1
- package/cjs/menu/menu-link.styles.js +1 -1
- package/cjs/menu/menu-link.styles.js.map +1 -1
- package/cjs/menu/menu-link.styles_rng7n7.css +2 -0
- package/cjs/menu/menu-section.js +1 -1
- package/cjs/menu/menu-section.js.map +1 -1
- package/cjs/menu/menu-section.styles.js +1 -1
- package/cjs/menu/menu-section.styles.js.map +1 -1
- package/cjs/menu/menu-section.styles_1n0ppxl.css +5 -0
- package/cjs/navbar/navbar-items.js +1 -1
- package/cjs/navbar/navbar-items.js.map +1 -1
- package/cjs/notification-banner/notification-banner-hoc.js +1 -1
- package/cjs/notification-banner/notification-banner-hoc.js.map +1 -1
- package/cjs/pagination/pagination.js +1 -1
- package/cjs/pagination/pagination.js.map +1 -1
- package/cjs/shared/dropdown-list/dropdown-label.js +1 -1
- package/cjs/shared/dropdown-list/dropdown-label.js.map +1 -1
- package/cjs/shared/fade-wrapper/fade-wrapper.js +1 -1
- package/cjs/shared/fade-wrapper/fade-wrapper.js.map +1 -1
- package/cjs/theme/tokens/colour.js +1 -1
- package/cjs/theme/tokens/colour.js.map +1 -1
- package/cjs/theme/tokens/radius.js +1 -1
- package/cjs/theme/tokens/radius.js.map +1 -1
- package/codemods/run-codemod.js +8 -2
- package/codemods/run-codemod.js.map +1 -1
- package/codemods/run-codemod.ts +13 -4
- package/drawer/drawer.d.ts +1 -1
- package/drawer/drawer.js +1 -1
- package/drawer/drawer.js.map +1 -1
- package/drawer/drawer.styles.d.ts +3 -0
- package/drawer/drawer.styles.js +1 -1
- package/drawer/drawer.styles.js.map +1 -1
- package/{cjs/drawer/drawer.styles_94hx3y.css → drawer/drawer.styles_a4bwe0.css} +6 -3
- package/drawer/types.d.ts +7 -0
- package/file-upload/file-list/file-list.js +1 -1
- package/file-upload/file-list/file-list.js.map +1 -1
- package/file-upload/file-list/file-list.styles.d.ts +0 -1
- package/file-upload/file-list/file-list.styles.js +1 -1
- package/file-upload/file-list/file-list.styles.js.map +1 -1
- package/file-upload/file-list/file-list.styles_1xbypnh.css +2 -0
- package/file-upload/file-list-item/file-item-actions.d.ts +30 -0
- package/file-upload/file-list-item/file-item-actions.js +2 -0
- package/file-upload/file-list-item/file-item-actions.js.map +1 -0
- package/file-upload/file-list-item/file-item-actions.styles.d.ts +6 -0
- package/file-upload/file-list-item/file-item-actions.styles.js +2 -0
- package/file-upload/file-list-item/file-item-actions.styles.js.map +1 -0
- package/file-upload/file-list-item/file-item-actions.styles_1quulgy.css +8 -0
- package/file-upload/file-list-item/file-item-details.d.ts +15 -0
- package/file-upload/file-list-item/file-item-details.js +2 -0
- package/file-upload/file-list-item/file-item-details.js.map +1 -0
- package/file-upload/file-list-item/file-item-details.styles.d.ts +7 -0
- package/file-upload/file-list-item/file-item-details.styles.js +2 -0
- package/file-upload/file-list-item/file-item-details.styles.js.map +1 -0
- package/file-upload/file-list-item/file-item-details.styles_1ce9akx.css +7 -0
- package/file-upload/file-list-item/file-list-item.d.ts +1 -7
- package/file-upload/file-list-item/file-list-item.js +1 -1
- package/file-upload/file-list-item/file-list-item.js.map +1 -1
- package/file-upload/file-list-item/file-list-item.styles.d.ts +6 -13
- package/file-upload/file-list-item/file-list-item.styles.js +1 -1
- package/file-upload/file-list-item/file-list-item.styles.js.map +1 -1
- package/file-upload/file-list-item/file-list-item.styles_x3a500.css +10 -0
- package/file-upload/file-list-item/types.d.ts +10 -3
- package/file-upload/file-list-item/use-truncated-name.d.ts +1 -0
- package/file-upload/file-list-item/use-truncated-name.js +2 -0
- package/file-upload/file-list-item/use-truncated-name.js.map +1 -0
- package/input-group/types.d.ts +4 -1
- package/input-select/types.d.ts +1 -0
- package/local-nav/local-nav-dropdown/local-nav-dropdown.js +1 -1
- package/local-nav/local-nav-dropdown/local-nav-dropdown.js.map +1 -1
- package/local-nav/local-nav-dropdown/local-nav-dropdown.styles.d.ts +3 -0
- package/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js +1 -1
- package/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js.map +1 -1
- package/local-nav/local-nav-dropdown/{local-nav-dropdown.styles_uhd4xl.css → local-nav-dropdown.styles_kpel1m.css} +9 -6
- package/local-nav/local-nav-menu/local-nav-menu.js +1 -1
- package/local-nav/local-nav-menu/local-nav-menu.js.map +1 -1
- package/local-nav/local-nav-menu/local-nav-menu.styles.d.ts +3 -0
- package/local-nav/local-nav-menu/local-nav-menu.styles.js +1 -1
- package/local-nav/local-nav-menu/local-nav-menu.styles.js.map +1 -1
- package/local-nav/local-nav-menu/local-nav-menu.styles_67fcyc.css +8 -0
- package/local-nav/types.d.ts +17 -0
- package/masked-input/types.d.ts +1 -2
- package/menu/menu-content.js +1 -1
- package/menu/menu-content.js.map +1 -1
- package/menu/menu-content.styles.d.ts +1 -0
- package/menu/menu-content.styles.js +1 -1
- package/menu/menu-content.styles.js.map +1 -1
- package/menu/menu-content.styles_1r8oxtk.css +5 -0
- package/menu/menu-item.styles.js +1 -1
- package/menu/menu-item.styles.js.map +1 -1
- package/menu/{menu-item.styles_liyed8.css → menu-item.styles_eut2j9.css} +1 -1
- package/menu/menu-link.styles.js +1 -1
- package/menu/menu-link.styles.js.map +1 -1
- package/menu/menu-link.styles_rng7n7.css +2 -0
- package/menu/menu-section.d.ts +1 -1
- package/menu/menu-section.js +1 -1
- package/menu/menu-section.js.map +1 -1
- package/menu/menu-section.styles.d.ts +7 -0
- package/menu/menu-section.styles.js +1 -1
- package/menu/menu-section.styles.js.map +1 -1
- package/menu/menu-section.styles_1n0ppxl.css +5 -0
- package/menu/menu.d.ts +1 -1
- package/menu/types.d.ts +10 -2
- package/navbar/navbar-items.js +1 -1
- package/navbar/navbar-items.js.map +1 -1
- package/navbar/types.d.ts +9 -0
- package/notification-banner/notification-banner-hoc.js +1 -1
- package/notification-banner/notification-banner-hoc.js.map +1 -1
- package/package.json +2 -3
- package/pagination/pagination.js +1 -1
- package/pagination/pagination.js.map +1 -1
- package/pagination/types.d.ts +8 -1
- package/select-histogram/types.d.ts +1 -0
- package/shared/dropdown-list/dropdown-label.d.ts +2 -2
- package/shared/dropdown-list/dropdown-label.js +1 -1
- package/shared/dropdown-list/dropdown-label.js.map +1 -1
- package/shared/dropdown-list/types.d.ts +6 -2
- package/shared/fade-wrapper/fade-wrapper.js +1 -1
- package/shared/fade-wrapper/fade-wrapper.js.map +1 -1
- package/shared/fade-wrapper/types.d.ts +1 -0
- package/shared/styles/index.d.ts +5 -0
- package/theme/styles/a11y-playground.css +52 -40
- package/theme/styles/bookingsg.css +52 -40
- package/theme/styles/careercompass.css +52 -40
- package/theme/styles/ccube.css +52 -40
- package/theme/styles/imda.css +52 -40
- package/theme/styles/lifesg.css +52 -40
- package/theme/styles/mylegacy.css +52 -40
- package/theme/styles/oneservice.css +52 -40
- package/theme/styles/pa.css +28 -22
- package/theme/styles/rbs.css +52 -40
- package/theme/styles/sgw-digital-lobby.css +52 -40
- package/theme/styles/smgs.css +52 -40
- package/theme/styles/spf.css +28 -27
- package/theme/styles/sportsg-orange.css +52 -40
- package/theme/styles/supportgowhere.css +52 -40
- package/theme/styles/tote-board.css +52 -40
- package/theme/styles/vica.css +52 -40
- package/theme/styles/websg.css +52 -40
- package/theme/styles/wise.css +52 -40
- package/theme/styles/wogaa.css +52 -40
- package/theme/tokens/colour.d.ts +6 -0
- package/theme/tokens/colour.js +1 -1
- package/theme/tokens/colour.js.map +1 -1
- package/theme/tokens/radius.d.ts +3 -0
- package/theme/tokens/radius.js +1 -1
- package/theme/tokens/radius.js.map +1 -1
- package/breadcrumb/breadcrumb.styles_1nl4aua.css +0 -18
- package/cjs/breadcrumb/breadcrumb.styles_1nl4aua.css +0 -18
- package/cjs/file-upload/file-item-edit.js +0 -2
- package/cjs/file-upload/file-item-edit.js.map +0 -1
- package/cjs/file-upload/file-item-edit.styles.js +0 -2
- package/cjs/file-upload/file-item-edit.styles.js.map +0 -1
- package/cjs/file-upload/file-item-edit.styles_19bvztn.css +0 -11
- package/cjs/file-upload/file-list/file-list.styles_1w7so98.css +0 -3
- package/cjs/file-upload/file-list-item/file-list-item.styles_kgtfke.css +0 -17
- package/cjs/local-nav/local-nav-menu/local-nav-menu.styles_pq19dh.css +0 -5
- package/cjs/menu/menu-content.styles_p7ijll.css +0 -2
- package/cjs/menu/menu-link.styles_hfxoez.css +0 -2
- package/cjs/menu/menu-section.styles_g7my4d.css +0 -3
- package/file-upload/file-item-edit.d.ts +0 -14
- package/file-upload/file-item-edit.js +0 -2
- package/file-upload/file-item-edit.js.map +0 -1
- package/file-upload/file-item-edit.styles.d.ts +0 -9
- package/file-upload/file-item-edit.styles.js +0 -2
- package/file-upload/file-item-edit.styles.js.map +0 -1
- package/file-upload/file-item-edit.styles_19bvztn.css +0 -11
- package/file-upload/file-list/file-list.styles_1w7so98.css +0 -3
- package/file-upload/file-list-item/file-list-item.styles_kgtfke.css +0 -17
- package/local-nav/local-nav-menu/local-nav-menu.styles_pq19dh.css +0 -5
- package/menu/menu-content.styles_p7ijll.css +0 -2
- package/menu/menu-link.styles_hfxoez.css +0 -2
- package/menu/menu-section.styles_g7my4d.css +0 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-item-actions.js","sources":["../../../../src/file-upload/file-list-item/file-item-actions.tsx"],"sourcesContent":["import { BinIcon } from \"@lifesg/react-icons/bin\";\nimport { PencilIcon } from \"@lifesg/react-icons/pencil\";\nimport clsx from \"clsx\";\n\nimport { Button } from \"../../button\";\nimport { ProgressBar } from \"../../shared/progress-bar\";\nimport * as styles from \"./file-item-actions.styles\";\n\n// =============================================================================\n// TYPES\n// =============================================================================\ninterface BaseProps {\n id: string;\n name: string;\n}\n\ninterface ErrorActionProps extends BaseProps {\n mode: \"error\";\n errorMessage?: string | React.ReactNode | undefined;\n onDelete: () => void;\n}\n\ninterface DisplayActionProps extends BaseProps {\n mode: \"display\";\n inline?: boolean | undefined;\n editable?: boolean | undefined;\n isLoading: boolean;\n progress: number;\n disabled: boolean;\n onDelete: () => void;\n onEdit?: (() => void) | undefined;\n onKeyDown?:\n | ((event: React.KeyboardEvent<HTMLButtonElement>) => void)\n | undefined;\n}\n\ninterface EditActionProps extends BaseProps {\n mode: \"edit\";\n hasThumbnail: boolean;\n disableSave: boolean;\n onSave: () => void;\n onCancel: () => void;\n}\n\ntype FileItemActionsProps =\n | ErrorActionProps\n | DisplayActionProps\n | EditActionProps;\n\n// =============================================================================\n// COMPONENT\n// =============================================================================\nexport const FileItemActions = (props: FileItemActionsProps) => {\n const { mode, id, name } = props;\n\n if (mode === \"error\") {\n return (\n <div className={styles.actionContainer}>\n <Button\n data-testid={`${id}-error-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}, error: ${props.errorMessage}`}\n onClick={props.onDelete}\n className={styles.iconButton}\n icon={<BinIcon aria-hidden />}\n />\n </div>\n );\n }\n\n if (mode === \"edit\") {\n return (\n <div\n className={clsx(\n styles.actionButtonsSection,\n props.hasThumbnail &&\n styles.actionButtonsSectionWithThumbnail\n )}\n >\n <Button\n data-testid={`${id}-save-button`}\n type=\"button\"\n sizeType=\"small\"\n disabled={props.disableSave}\n onClick={props.onSave}\n className={styles.actionButton}\n >\n Save\n </Button>\n <Button\n type=\"button\"\n sizeType=\"small\"\n styleType=\"secondary\"\n data-testid={`${id}-cancel-button`}\n onClick={props.onCancel}\n className={styles.actionButton}\n >\n Cancel\n </Button>\n </div>\n );\n }\n\n // Display mode\n if (props.inline) {\n return (\n <div className={styles.inlineActionContainer}>\n <Button\n key=\"edit\"\n data-testid={`${id}-edit-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`edit ${name}`}\n disabled={props.disabled}\n onClick={props.onEdit}\n onKeyDown={props.onKeyDown}\n icon={<PencilIcon aria-hidden />}\n className={styles.iconButton}\n />\n <Button\n key=\"delete\"\n data-testid={`${id}-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}`}\n disabled={props.disabled}\n onClick={props.onDelete}\n onKeyDown={props.onKeyDown}\n icon={<BinIcon aria-hidden />}\n className={styles.iconButton}\n />\n </div>\n );\n }\n\n const getActionContainerLayout = () => {\n if (props.isLoading) return \"loading\";\n if (props.editable) return \"editable\";\n return undefined;\n };\n\n let content: JSX.Element;\n\n if (props.isLoading) {\n content = (\n <ProgressBar\n progress={props.progress}\n data-testid={`${id}-progress-bar`}\n />\n );\n } else {\n content = (\n <>\n {props.editable && (\n <Button\n key=\"edit\"\n data-testid={`${id}-edit-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`edit ${name}`}\n disabled={props.disabled}\n onClick={props.onEdit}\n onKeyDown={props.onKeyDown}\n icon={<PencilIcon aria-hidden />}\n className={styles.iconButton}\n />\n )}\n <Button\n key=\"delete\"\n data-testid={`${id}-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}`}\n disabled={props.disabled}\n onClick={props.onDelete}\n onKeyDown={props.onKeyDown}\n icon={<BinIcon aria-hidden />}\n className={styles.iconButton}\n />\n </>\n );\n }\n\n return (\n <div\n className={styles.actionContainer}\n data-mobile-layout={getActionContainerLayout()}\n >\n {content}\n </div>\n );\n};\n"],"names":["props","mode","id","name","_jsx","className","styles.actionContainer","children","Button","type","styleType","sizeType","errorMessage","onClick","onDelete","styles.iconButton","icon","BinIcon","_jsxs","clsx","styles.actionButtonsSection","hasThumbnail","styles.actionButtonsSectionWithThumbnail","disabled","disableSave","onSave","styles.actionButton","onCancel","inline","styles.inlineActionContainer","onEdit","onKeyDown","PencilIcon","content","isLoading","ProgressBar","progress","_Fragment","editable"],"mappings":"gYAoDgCA,IAC5B,MAAMC,KAAEA,EAAIC,GAAEA,EAAEC,KAAEA,GAASH,EAE3B,GAAa,UAATC,EACA,OACIG,EAAAA,IAAA,MAAA,CAAKC,UAAWC,EAAAA,gBAAsBC,SAClCH,EAAAA,IAACI,EAAAA,OAAM,CAAA,cACU,GAAGN,wBAAwB,cAC5B,OACZO,KAAK,SACLC,UAAU,QACVC,SAAS,qBACG,UAAUR,aAAgBH,EAAMY,eAC5CC,QAASb,EAAMc,SACfT,UAAWU,EAAAA,WACXC,KAAMZ,EAAAA,IAACa,EAAAA,QAAO,CAAA,eAAA,QAM9B,GAAa,SAAThB,EACA,OACIiB,EAAAA,KAAA,MAAA,CACIb,UAAWc,EAAAA,QACPC,EAAAA,qBACApB,EAAMqB,cACFC,EAAAA,mCACPf,SAAA,CAEDH,EAAAA,IAACI,EAAAA,OAAM,CAAA,cACU,GAAGN,gBAChBO,KAAK,SACLE,SAAS,QACTY,SAAUvB,EAAMwB,YAChBX,QAASb,EAAMyB,OACfpB,UAAWqB,EAAAA,aAAmBnB,SAAA,SAIlCH,EAAAA,IAACI,SAAM,CACHC,KAAK,SACLE,SAAS,QACTD,UAAU,YAAW,cACR,GAAGR,kBAChBW,QAASb,EAAM2B,SACftB,UAAWqB,EAAAA,aAAmBnB,SAAA,cAS9C,GAAIP,EAAM4B,OACN,OACIV,EAAAA,KAAA,MAAA,CAAKb,UAAWwB,EAAAA,sBAA4BtB,SAAA,CACxCH,MAACI,EAAAA,OAAM,CAAA,cAEU,GAAGN,gBAAgB,cACpB,OACZO,KAAK,SACLC,UAAU,QACVC,SAAS,QAAO,aACJ,QAAQR,IACpBoB,SAAUvB,EAAMuB,SAChBV,QAASb,EAAM8B,OACfC,UAAW/B,EAAM+B,UACjBf,KAAMZ,EAAAA,IAAC4B,EAAAA,WAAU,CAAA,eAAA,IACjB3B,UAAWU,EAAAA,YAXP,QAaRX,EAAAA,IAACI,EAAAA,OAAM,CAAA,cAEU,GAAGN,kBAAkB,cACtB,OACZO,KAAK,SACLC,UAAU,QACVC,SAAS,QAAO,aACJ,UAAUR,IACtBoB,SAAUvB,EAAMuB,SAChBV,QAASb,EAAMc,SACfiB,UAAW/B,EAAM+B,UACjBf,KAAMZ,EAAAA,IAACa,UAAO,CAAA,eAAA,IACdZ,UAAWU,cAXP,aAuBpB,IAAIkB,EA8CJ,OA3CIA,EADAjC,EAAMkC,UAEF9B,EAAAA,IAAC+B,cAAW,CACRC,SAAUpC,EAAMoC,uBACH,GAAGlC,mBAKpBgB,EAAAA,KAAAmB,EAAAA,SAAA,CAAA9B,SAAA,CACKP,EAAMsC,UACHlC,MAACI,EAAAA,OAAM,CAAA,cAEU,GAAGN,gBAAgB,cACpB,OACZO,KAAK,SACLC,UAAU,QACVC,SAAS,QAAO,aACJ,QAAQR,IACpBoB,SAAUvB,EAAMuB,SAChBV,QAASb,EAAM8B,OACfC,UAAW/B,EAAM+B,UACjBf,KAAMZ,EAAAA,IAAC4B,EAAAA,WAAU,CAAA,eAAA,IACjB3B,UAAWU,EAAAA,YAXP,QAcZX,EAAAA,IAACI,EAAAA,OAAM,CAAA,cAEU,GAAGN,kBAAkB,cACtB,OACZO,KAAK,SACLC,UAAU,QACVC,SAAS,QAAO,aACJ,UAAUR,IACtBoB,SAAUvB,EAAMuB,SAChBV,QAASb,EAAMc,SACfiB,UAAW/B,EAAM+B,UACjBf,KAAMZ,EAAAA,IAACa,UAAO,CAAA,eAAA,IACdZ,UAAWU,EAAAA,YAXP,aAkBhBX,EAAAA,IAAA,MAAA,CACIC,UAAWC,EAAAA,gBAAsB,qBArDjCN,EAAMkC,UAAkB,UACxBlC,EAAMsC,SAAiB,gBAA3B,EAqDkD/B,SAE7C0B,GACC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";require("./file-item-actions.styles_1quulgy.css");exports.actionButton="a4qbgp8",exports.actionButtonsSection="ax57y32",exports.actionButtonsSectionWithThumbnail="a1r3bkt9",exports.actionContainer="a1j9d2dw",exports.iconButton="i1m4nw9n",exports.inlineActionContainer="i1c7erb1";
|
|
2
|
+
//# sourceMappingURL=file-item-actions.styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-item-actions.styles.js","sources":["../../../../src/file-upload/file-list-item/file-item-actions.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { MediaQuery, Spacing } from \"../../theme\";\n\nexport const actionContainer = css`\n width: 6rem;\n margin-left: ${Spacing[\"spacing-32\"]};\n display: flex;\n justify-content: flex-end;\n align-items: center;\n\n ${MediaQuery.MaxWidth.md} {\n width: fit-content;\n }\n\n &[data-mobile-layout=\"loading\"] {\n ${MediaQuery.MaxWidth.md} {\n margin-left: 0;\n margin-top: ${Spacing[\"spacing-16\"]};\n width: 100%;\n }\n }\n\n &[data-mobile-layout=\"editable\"] {\n ${MediaQuery.MaxWidth.md} {\n margin-left: 0;\n margin-top: ${Spacing[\"spacing-16\"]};\n align-self: flex-end;\n }\n }\n`;\n\nexport const inlineActionContainer = css`\n width: 100%;\n margin-top: ${Spacing[\"spacing-16\"]};\n display: flex;\n justify-content: flex-end;\n align-items: center;\n`;\n\nexport const actionButtonsSection = css`\n display: flex;\n justify-content: flex-end;\n\n ${MediaQuery.MaxWidth.md} {\n flex-direction: column;\n }\n`;\n\nexport const actionButtonsSectionWithThumbnail = css`\n margin-left: calc(\n 96px + ${Spacing[\"spacing-32\"]}\n ); // thumbnail width + right margin\n\n ${MediaQuery.MaxWidth.md} {\n margin-left: 0;\n }\n`;\n\nexport const actionButton = css`\n width: 7.5rem;\n\n &:not(:last-of-type) {\n margin-right: ${Spacing[\"spacing-16\"]};\n }\n\n ${MediaQuery.MaxWidth.md} {\n width: 100%;\n\n &:not(:last-of-type) {\n margin-bottom: ${Spacing[\"spacing-16\"]};\n }\n }\n`;\n\nexport const iconButton = css`\n min-width: unset;\n\n &:not(:last-child) {\n margin-right: ${Spacing[\"spacing-8\"]};\n }\n`;\n"],"names":[],"mappings":"8HA2DyB,uCAnBQ,oDASa,mCA7ClB,8BAuEL,yCA3CW"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
@layer fds{.a1j9d2dw{width:6rem;margin-left:var(--fds-spacing-32);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}:where(body.fds-breakpoint-md-max) .a1j9d2dw{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;}:where(body.fds-breakpoint-md-max) .a1j9d2dw[data-mobile-layout="loading"]{margin-left:0;margin-top:var(--fds-spacing-16);width:100%;}:where(body.fds-breakpoint-md-max) .a1j9d2dw[data-mobile-layout="editable"]{margin-left:0;margin-top:var(--fds-spacing-16);-webkit-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end;}
|
|
2
|
+
.i1c7erb1{width:100%;margin-top:var(--fds-spacing-16);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}
|
|
3
|
+
.ax57y32{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;}:where(body.fds-breakpoint-md-max) .ax57y32{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}
|
|
4
|
+
.a1r3bkt9{margin-left:calc(
|
|
5
|
+
96px + var(--fds-spacing-32)
|
|
6
|
+
);}:where(body.fds-breakpoint-md-max) .a1r3bkt9{margin-left:0;}
|
|
7
|
+
.a4qbgp8{width:7.5rem;}.a4qbgp8:not(:last-of-type){margin-right:var(--fds-spacing-16);}:where(body.fds-breakpoint-md-max) .a4qbgp8{width:100%;}:where(body.fds-breakpoint-md-max) .a4qbgp8:not(:last-of-type){margin-bottom:var(--fds-spacing-16);}
|
|
8
|
+
.i1m4nw9n{min-width:unset;}.i1m4nw9n:not(:last-child){margin-right:var(--fds-spacing-8);}}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var e=require("react/jsx-runtime"),i=require("@lifesg/react-icons/exclamation-circle-fill"),r=require("../../typography/index.js"),s=require("./file-item-details.styles.js");exports.FileItemDetails=({mode:a,formattedName:l,description:o,fileSize:c,errorMessage:d,isLoading:t,descriptionLabel:n,detailSectionRef:h,children:m})=>{var p;return"error"===a?e.jsxs("div",{ref:h,className:s.nameSection,children:[e.jsx(r.Typography.BodyMD,{weight:o?"semibold":"regular",children:l}),e.jsx(r.Typography.BodyMD,{className:s.descriptionFileSizeText,children:c}),d&&e.jsxs(r.Typography.BodySM,{className:s.errorMessage,weight:"semibold",children:[e.jsx(i.ExclamationCircleFillIcon,{className:s.errorIcon,"aria-hidden":!0}),d]})]}):e.jsxs("div",{ref:h,className:s.nameSection,children:[e.jsx(r.Typography.BodyMD,{weight:o?"semibold":"regular",children:l}),o&&e.jsxs(e.Fragment,{children:[e.jsx(r.Typography.BodyMD,{className:s.itemDescriptionLabel,children:null!==(p=null==n?void 0:n.children)&&void 0!==p?p:"Photo description"}),e.jsx(r.Typography.BodyMD,{className:s.itemDescriptionText,children:o})]}),!t&&e.jsx(r.Typography.BodyMD,{className:s.descriptionFileSizeText,children:c}),m]})};
|
|
2
|
+
//# sourceMappingURL=file-item-details.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-item-details.js","sources":["../../../../src/file-upload/file-list-item/file-item-details.tsx"],"sourcesContent":["import { ExclamationCircleFillIcon } from \"@lifesg/react-icons/exclamation-circle-fill\";\n\nimport type { FormLabelProps } from \"../../form/form-label/types\";\nimport { Typography } from \"../../typography\";\nimport * as styles from \"./file-item-details.styles\";\nimport type { FileItemMode } from \"./types\";\n\ninterface Props {\n mode: Exclude<FileItemMode, \"edit\">;\n formattedName: string | undefined;\n description: string | undefined;\n fileSize: string;\n errorMessage: string | React.ReactNode | undefined;\n isLoading: boolean;\n descriptionLabel?: FormLabelProps | undefined;\n detailSectionRef: React.Ref<HTMLDivElement>;\n children?: React.ReactNode;\n}\n\nexport const FileItemDetails = ({\n mode,\n formattedName,\n description,\n fileSize,\n errorMessage,\n isLoading,\n descriptionLabel,\n detailSectionRef,\n children,\n}: Props) => {\n if (mode === \"error\") {\n return (\n <div ref={detailSectionRef} className={styles.nameSection}>\n <Typography.BodyMD\n weight={description ? \"semibold\" : \"regular\"}\n >\n {formattedName}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.descriptionFileSizeText}>\n {fileSize}\n </Typography.BodyMD>\n {errorMessage && (\n <Typography.BodySM\n className={styles.errorMessage}\n weight=\"semibold\"\n >\n <ExclamationCircleFillIcon\n className={styles.errorIcon}\n aria-hidden\n />\n {errorMessage}\n </Typography.BodySM>\n )}\n </div>\n );\n }\n\n return (\n <div ref={detailSectionRef} className={styles.nameSection}>\n <Typography.BodyMD weight={description ? \"semibold\" : \"regular\"}>\n {formattedName}\n </Typography.BodyMD>\n {description && (\n <>\n <Typography.BodyMD className={styles.itemDescriptionLabel}>\n {descriptionLabel?.children ?? \"Photo description\"}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.itemDescriptionText}>\n {description}\n </Typography.BodyMD>\n </>\n )}\n {!isLoading && (\n <Typography.BodyMD className={styles.descriptionFileSizeText}>\n {fileSize}\n </Typography.BodyMD>\n )}\n {children}\n </div>\n );\n};\n"],"names":["mode","formattedName","description","fileSize","errorMessage","isLoading","descriptionLabel","detailSectionRef","children","_jsxs","ref","className","styles.nameSection","_jsx","Typography","BodyMD","weight","styles.descriptionFileSizeText","BodySM","styles.errorMessage","ExclamationCircleFillIcon","styles.errorIcon","styles.itemDescriptionLabel","_a","styles.itemDescriptionText"],"mappings":"mNAmB+B,EAC3BA,OACAC,gBACAC,cACAC,WACAC,eACAC,YACAC,mBACAC,mBACAC,qBAEA,MAAa,UAATR,EAEIS,OAAA,MAAA,CAAKC,IAAKH,EAAkBI,UAAWC,EAAAA,YAAkBJ,SAAA,CACrDK,EAAAA,IAACC,EAAAA,WAAWC,OAAM,CACdC,OAAQd,EAAc,WAAa,UAASM,SAE3CP,IAELY,MAACC,EAAAA,WAAWC,QAAOJ,UAAWM,EAAAA,wBAA8BT,SACvDL,IAEJC,GACGK,OAACK,EAAAA,WAAWI,OAAM,CACdP,UAAWQ,eACXH,OAAO,WAAUR,SAAA,CAEjBK,EAAAA,IAACO,EAAAA,0BAAyB,CACtBT,UAAWU,EAAAA,6BAGdjB,QAQjBK,EAAAA,YAAKC,IAAKH,EAAkBI,UAAWC,cAAkBJ,SAAA,CACrDK,EAAAA,IAACC,EAAAA,WAAWC,QAAOC,OAAQd,EAAc,WAAa,UAASM,SAC1DP,IAEJC,GACGO,EAAAA,2BACII,EAAAA,IAACC,EAAAA,WAAWC,OAAM,CAACJ,UAAWW,EAAAA,qBAA2Bd,SAC1B,QAA1Be,EAAAjB,eAAAA,EAAkBE,gBAAQ,IAAAe,EAAAA,EAAI,sBAEnCV,MAACC,EAAAA,WAAWC,QAAOJ,UAAWa,sBAA0BhB,SACnDN,QAIXG,GACEQ,EAAAA,IAACC,aAAWC,OAAM,CAACJ,UAAWM,EAAAA,iCACzBd,IAGRK,IACC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";require("./file-item-details.styles_1ce9akx.css");exports.descriptionFileSizeText="d1cbfa1y",exports.errorIcon="e1dtq2ug",exports.errorMessage="e1scdqz1",exports.itemDescriptionLabel="i11dywsu",exports.itemDescriptionText="i745c9",exports.nameSection="naum77y";
|
|
2
|
+
//# sourceMappingURL=file-item-details.styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-item-details.styles.js","sources":["../../../../src/file-upload/file-list-item/file-item-details.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Colour, Font, MediaQuery, Spacing } from \"../../theme\";\n\nexport const nameSection = css`\n display: flex;\n flex: 1;\n flex-direction: column;\n width: 100%;\n`;\n\nexport const extendedNameSection = css`\n display: flex;\n flex: 1;\n flex-direction: column;\n align-items: flex-start;\n\n ${MediaQuery.MaxWidth.md} {\n width: 100%;\n }\n`;\n\nexport const itemDescriptionLabel = css`\n ${Font[\"form-label\"]}\n font-weight: ${Font.Spec[\"weight-semibold\"]};\n color: ${Colour[\"text-subtle\"]};\n margin-top: ${Spacing[\"spacing-16\"]};\n`;\n\nexport const itemDescriptionText = css`\n margin-top: ${Spacing[\"spacing-4\"]};\n overflow-wrap: anywhere;\n`;\n\nexport const descriptionFileSizeText = css`\n color: ${Colour[\"text-subtler\"]};\n margin-top: ${Spacing[\"spacing-16\"]};\n`;\n\nexport const errorIcon = css`\n height: 1lh;\n width: 1em;\n flex-shrink: 0;\n color: ${Colour[\"icon-error-strong\"]};\n`;\n\nexport const errorMessage = css`\n color: ${Colour[\"text-error\"]};\n margin-top: ${Spacing[\"spacing-4\"]};\n display: flex;\n gap: ${Spacing[\"spacing-4\"]};\n`;\n"],"names":[],"mappings":"yIAkCoC,6BAKd,gCAOG,wCAxBQ,uCAOD,6BAzBR"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
@layer fds{.naum77y{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1;-ms-flex:1;flex:1;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;width:100%;}
|
|
2
|
+
.e13zkqng{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1;-ms-flex:1;flex:1;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;}:where(body.fds-breakpoint-md-max) .e13zkqng{width:100%;}
|
|
3
|
+
.i11dywsu{font-family:var(--fds-font-family-body);font-variant:var(--fds-font-variant);font-size:var(--fds-font-form-label-size);font-weight:var(--fds-font-weight-semibold);line-height:var(--fds-font-form-label-lh);letter-spacing:var(--fds-font-form-label-ls);font-weight:var(--fds-font-weight-semibold);color:var(--fds-colour-text-subtle);margin-top:var(--fds-spacing-16);}
|
|
4
|
+
.i745c9{margin-top:var(--fds-spacing-4);overflow-wrap:anywhere;}
|
|
5
|
+
.d1cbfa1y{color:var(--fds-colour-text-subtler);margin-top:var(--fds-spacing-16);}
|
|
6
|
+
.e1dtq2ug{height:1lh;width:1em;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;color:var(--fds-colour-icon-error-strong);}
|
|
7
|
+
.e1scdqz1{color:var(--fds-colour-text-error);margin-top:var(--fds-spacing-4);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;gap:var(--fds-spacing-4);}}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var e=require("react/jsx-runtime"),
|
|
1
|
+
"use strict";var e=require("react/jsx-runtime"),t=require("../../external/@dnd-kit/sortable/dist/sortable.esm.js"),i=require("../../external/@dnd-kit/utilities/dist/utilities.esm.js"),a=require("@lifesg/react-icons/drag-handle"),s=require("react"),r=require("../../form/index.js"),l=require("../../typography/index.js"),n=require("../context.js"),d=require("../helper.js"),o=require("./file-item-actions.js"),c=require("./file-item-details.js"),u=require("./file-list-item.styles.js"),m=require("./file-list-item-thumbnail.js"),p=require("./use-truncated-name.js");const b=s.memo((({fileItem:b,wrapperWidth:h,editable:f,sortable:x,disabled:g,readOnly:j,descriptionLabel:y,fileDescriptionMaxLength:S,descriptionRequired:v=!0,onDelete:D,onSave:I,onCancel:F,onBlur:q,onModeChange:N})=>{const{id:T,name:L,size:M,description:C,progress:E=1,errorMessage:R,thumbnailImageDataUrl:w,truncateText:H=!0}=b,{activeId:U}=s.useContext(n.FileUploadContext),$=s.useRef(null),z=p.useTruncatedName(L,h,H,$),A=()=>{if(R)return"error";return(null!=E?E:1)>=1&&f&&!C?"edit":"display"},[B,O]=s.useState(A),{attributes:P,listeners:k,setNodeRef:K,transform:_,transition:W}=t.useSortable({id:T,disabled:"edit"===B}),Y=s.useRef(null),[G,J]=s.useState(b.description||""),Q=E<1,V=d.FileUploadHelper.formatFileSizeDisplay(M),X=!!w||b.type===d.FileUploadHelper.PDF_MIME_TYPE,Z="display"===B&&!!C&&!!f,ee=!!x&&!j,te=g||!!U,ie=s.useMemo((()=>{const e=U?U===T?"self":"others":"none";return{itemState:te&&"none"===e?"disabled":ee&&"self"===e?"sortable-active":ee?"sortable":void 0,dragHandleState:"self"===e?"active":te?"disabled":void 0,boxState:"self"===e?"focused":te?"disabled":R?"error":void 0}}),[U,T,te,ee,R]),ae=v&&0===G.trim().length,se=s.useRef(B);se.current=B;const re=s.useRef(N);re.current=N,s.useEffect((()=>("edit"===B&&(null==N||N("edit")),()=>{var e;"edit"===se.current&&(null===(e=re.current)||void 0===e||e.call(re,"display"))})),[]),s.useEffect((()=>{if(R&&"error"!==B)"edit"===B&&(null==N||N("display")),O("error");else if(!R&&"error"===B){const e=A();"edit"===e&&(null==N||N("edit")),O(e)}}),[R]),s.useEffect((()=>{"edit"===B&&J(b.description||"")}),[B,b.description]);const le=()=>{O("edit"),null==N||N("edit")},ne=e=>{x&&e.stopPropagation()},de=()=>{Y.current&&(O("display"),null==N||N("display"),null==I||I(Y.current.value.trim()))},oe=()=>{O("display"),null==N||N("display"),null==F||F()},ce=e=>{J(e.target.value)},ue=e=>{null==q||q(e.target.value)};if("edit"===B)return e.jsxs("li",{"data-testid":`${T}-edit-display`,className:u.editItem,children:[e.jsxs("div",{className:u.editContentSection,children:[X&&e.jsx(m.FileListItemThumbnail,{thumbnailImageDataUrl:w,fileType:b.type}),e.jsxs("div",{className:u.editDetailsSection,children:[e.jsxs("div",{ref:$,className:u.editNameSection,children:[e.jsx(l.Typography.BodyMD,{className:u.editFileNameText,weight:"semibold",children:z}),e.jsx(l.Typography.BodyMD,{className:u.editFileSizeText,children:V})]}),e.jsx(r.Form.Textarea,{ref:Y,id:`${T}-description-textarea`,"data-testid":`${T}-textarea`,value:G,maxLength:S,onChange:ce,onBlur:ue,rows:3,label:null!=y?y:{children:"Photo description",subtitle:"Describe this photo to users who may not be able to see the image."}})]})]}),e.jsx(o.FileItemActions,{mode:"edit",id:T,name:L,hasThumbnail:X,disableSave:ae,onSave:de,onCancel:oe})]});const me={transform:i.CSS.Translate.toString(_),transition:W},pe=Object.assign(Object.assign({style:me},P),k),be=X?e.jsx(m.FileListItemThumbnail,{thumbnailImageDataUrl:w||"",fileType:b.type,"data-testid":`${T}-thumbnail`}):null;return e.jsxs("li",Object.assign({id:T,ref:K,className:u.item,"data-item-state":ie.itemState,"data-testid":`${T}-item`},ee?pe:{},{children:[ee&&e.jsx(a.DragHandleIcon,{"data-testid":`${T}-drag-handle`,className:u.dragHandleIcon,"data-drag-handle-state":ie.dragHandleState}),e.jsxs("div",{className:u.box,"data-box-state":ie.boxState,"data-stack-mobile":!R&&(Q||f),children:[e.jsxs("div",{className:u.contentSection,"data-has-thumbnail":"display"===B&&X,children:["display"===B&&be,e.jsx(c.FileItemDetails,{mode:B,formattedName:z,description:C,fileSize:V,errorMessage:R,isLoading:Q,descriptionLabel:y,detailSectionRef:$,children:!j&&Z&&e.jsx(o.FileItemActions,{mode:"display",inline:!0,id:T,name:L,editable:!!f,isLoading:Q,progress:E,disabled:te,onDelete:D,onEdit:le,onKeyDown:ne})})]}),!j&&!Z&&("error"===B?e.jsx(o.FileItemActions,{mode:"error",id:T,name:L,errorMessage:R,onDelete:D}):e.jsx(o.FileItemActions,{mode:"display",id:T,name:L,editable:!!f,isLoading:Q,progress:E,disabled:te,onDelete:D,onEdit:le,onKeyDown:ne}))]})]}))}));exports.FileListItem=b;
|
|
2
2
|
//# sourceMappingURL=file-list-item.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-list-item.js","sources":["../../../../src/file-upload/file-list-item/file-list-item.tsx"],"sourcesContent":["import { useSortable } from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { BinIcon } from \"@lifesg/react-icons/bin\";\nimport { DragHandleIcon as DSDragHandleIcon } from \"@lifesg/react-icons/drag-handle\";\nimport { ExclamationCircleFillIcon } from \"@lifesg/react-icons/exclamation-circle-fill\";\nimport { PencilIcon } from \"@lifesg/react-icons/pencil\";\nimport {\n memo,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\n\nimport { Button } from \"../../button\";\nimport type { FormLabelProps } from \"../../form/form-label/types\";\nimport { ProgressBar } from \"../../shared/progress-bar\";\nimport { Typography } from \"../../typography\";\nimport { StringHelper } from \"../../util\";\nimport { FileUploadContext } from \"../context\";\nimport { FileUploadHelper } from \"../helper\";\nimport type { ItemFocusType } from \"./file-list-item.styles\";\nimport * as styles from \"./file-list-item.styles\";\nimport { FileListItemThumbnail } from \"./file-list-item-thumbnail\";\nimport type { FileListItemProps } from \"./types\";\n\ninterface Props extends FileListItemProps {\n readOnly?: boolean | undefined;\n descriptionLabel?: FormLabelProps | undefined;\n}\n\nconst Component = ({\n fileItem,\n editable,\n sortable,\n wrapperWidth,\n disabled,\n readOnly,\n descriptionLabel,\n onDelete,\n onEditClick,\n}: Props) => {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const {\n id,\n name,\n size,\n description,\n progress = 1,\n errorMessage,\n thumbnailImageDataUrl,\n truncateText = true,\n } = fileItem;\n const [formattedName, setFormattedName] = useState<string>();\n const { activeId } = useContext(FileUploadContext);\n\n // Sortable mechanism\n const { attributes, listeners, setNodeRef, transform, transition } =\n useSortable({ id });\n const detailSectionRef = useRef<HTMLDivElement>(null);\n const style = {\n transform: CSS.Translate.toString(transform),\n transition,\n };\n\n const sortableProps = {\n style,\n ...attributes,\n ...listeners,\n };\n\n // Local variables\n const isLoading = progress < 1;\n const fileSize = FileUploadHelper.formatFileSizeDisplay(size);\n const hasInlineActions = !!description && !!editable;\n const focusType: ItemFocusType = activeId\n ? activeId === id\n ? \"self\"\n : \"others\"\n : \"none\";\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const getTruncatedText = useCallback(\n (value: string) => {\n if (!truncateText) return value;\n\n const widthOfElement =\n detailSectionRef && detailSectionRef.current\n ? detailSectionRef.current.getBoundingClientRect().width\n : 0;\n\n return StringHelper.truncateOneLine(\n value,\n widthOfElement,\n widthOfElement / 2,\n widthOfElement / 2 / 8, // Arbitrary\n 16 // Font size\n );\n },\n [truncateText]\n );\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n setFormattedName(getTruncatedText(name));\n }, [wrapperWidth, getTruncatedText, name]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleDelete = () => {\n onDelete();\n };\n\n const handleEdit = () => {\n if (onEditClick) {\n onEditClick();\n }\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n /**\n * Circumvent issue of keydown action activating the sort mechanism\n * rather than the actual action\n */\n if (sortable) {\n event.stopPropagation();\n }\n };\n\n const shouldDisable = () => disabled || !!activeId;\n\n const shouldEnableSort = () => !!sortable && !readOnly;\n\n const getItemState = () => {\n if (shouldDisable() && focusType === \"none\") {\n return \"disabled\";\n }\n\n if (shouldEnableSort() && focusType === \"self\") {\n return \"sortable-active\";\n }\n\n if (shouldEnableSort()) {\n return \"sortable\";\n }\n\n return undefined;\n };\n\n const getDragHandleState = () => {\n if (focusType === \"self\") {\n return \"active\";\n }\n\n if (shouldDisable()) {\n return \"disabled\";\n }\n\n return undefined;\n };\n\n const getBoxState = () => {\n if (focusType === \"self\") {\n return \"focused\";\n }\n\n if (shouldDisable()) {\n return \"disabled\";\n }\n\n if (errorMessage) {\n return \"error\";\n }\n\n return undefined;\n };\n\n const getActionContainerLayout = () => {\n if (!errorMessage && isLoading) {\n return \"loading\";\n }\n\n if (!errorMessage && editable) {\n return \"editable\";\n }\n\n return undefined;\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderNameDescription = () => (\n <>\n <Typography.BodyMD weight={description ? \"semibold\" : \"regular\"}>\n {formattedName}\n </Typography.BodyMD>\n {description && (\n <>\n <Typography.BodyMD className={styles.itemDescriptionLabel}>\n {descriptionLabel?.children ?? \"Photo description\"}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.itemDescriptionText}>\n {description}\n </Typography.BodyMD>\n </>\n )}\n </>\n );\n\n const renderErrorState = () => (\n <>\n <div ref={detailSectionRef} className={styles.nameSection}>\n {renderNameDescription()}\n {errorMessage && (\n <Typography.BodySM\n className={styles.desktopErrorMessage}\n weight=\"semibold\"\n >\n <ExclamationCircleFillIcon\n className={styles.errorIcon}\n aria-hidden\n />\n {errorMessage}\n </Typography.BodySM>\n )}\n </div>\n <div\n className={styles.fileSizeSection}\n data-mobile-visibility={isLoading ? \"hidden\" : \"expand\"}\n >\n <Typography.BodyMD className={styles.fileSizeText}>\n {fileSize}\n </Typography.BodyMD>\n </div>\n {errorMessage && (\n <Typography.BodySM\n className={styles.mobileErrorMessage}\n weight=\"semibold\"\n >\n <ExclamationCircleFillIcon\n className={styles.errorIcon}\n aria-hidden\n />\n {errorMessage}\n </Typography.BodySM>\n )}\n </>\n );\n\n const renderInlineActions = () => (\n <div className={styles.inlineActionContainer}>\n <Button\n key=\"edit\"\n data-testid={`${id}-edit-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`edit ${name}`}\n disabled={shouldDisable()}\n onClick={handleEdit}\n onKeyDown={handleKeyDown}\n icon={<PencilIcon aria-hidden />}\n className={styles.iconButton}\n />\n <Button\n key=\"delete\"\n data-testid={`${id}-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}`}\n disabled={shouldDisable()}\n onClick={handleDelete}\n onKeyDown={handleKeyDown}\n icon={<BinIcon aria-hidden />}\n className={styles.iconButton}\n />\n </div>\n );\n\n const renderDescriptionContent = () => (\n <div ref={detailSectionRef} className={styles.extendedNameSection}>\n <Typography.BodyMD weight=\"semibold\">\n {formattedName}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.itemDescriptionLabel}>\n {descriptionLabel?.children ?? \"Photo description\"}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.itemDescriptionText}>\n {description}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.descriptionFileSizeText}>\n {fileSize}\n </Typography.BodyMD>\n {!readOnly && hasInlineActions && renderInlineActions()}\n </div>\n );\n\n const renderFileContent = (thumbnailImageDataUrl?: string) => {\n const shouldShowThumbnail =\n !!thumbnailImageDataUrl ||\n fileItem.type === FileUploadHelper.PDF_MIME_TYPE;\n\n const thumbnail = shouldShowThumbnail ? (\n <FileListItemThumbnail\n thumbnailImageDataUrl={thumbnailImageDataUrl || \"\"}\n fileType={fileItem.type}\n data-testid={`${id}-thumbnail`}\n />\n ) : null;\n\n if (hasInlineActions) {\n return (\n <>\n {thumbnail}\n {renderDescriptionContent()}\n </>\n );\n }\n\n return (\n <>\n {thumbnail}\n <div ref={detailSectionRef} className={styles.nameSection}>\n {renderNameDescription()}\n {!isLoading && (\n <Typography.BodyMD\n className={styles.descriptionFileSizeText}\n >\n {fileSize}\n </Typography.BodyMD>\n )}\n </div>\n </>\n );\n };\n\n const renderContents = () => {\n const shouldShowThumbnail =\n !!thumbnailImageDataUrl ||\n fileItem.type === FileUploadHelper.PDF_MIME_TYPE;\n\n const content = errorMessage\n ? renderErrorState()\n : renderFileContent(thumbnailImageDataUrl);\n\n return (\n <div\n className={styles.contentSection}\n data-has-thumbnail={shouldShowThumbnail}\n >\n {content}\n </div>\n );\n };\n\n const renderActions = () => {\n let content: JSX.Element;\n\n if (errorMessage) {\n content = (\n <Button\n data-testid={`${id}-error-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}, error: ${errorMessage}`}\n onClick={handleDelete}\n className={styles.iconButton}\n icon={<BinIcon aria-hidden />}\n />\n );\n } else if (isLoading) {\n content = (\n <ProgressBar\n progress={progress}\n data-testid={`${id}-progress-bar`}\n />\n );\n } else {\n content = (\n <>\n {editable && (\n <Button\n key=\"edit\"\n data-testid={`${id}-edit-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`edit ${name}`}\n disabled={shouldDisable()}\n onClick={handleEdit}\n onKeyDown={handleKeyDown}\n icon={<PencilIcon aria-hidden />}\n className={styles.iconButton}\n />\n )}\n <Button\n key=\"delete\"\n data-testid={`${id}-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}`}\n disabled={shouldDisable()}\n onClick={handleDelete}\n onKeyDown={handleKeyDown}\n icon={<BinIcon aria-hidden />}\n className={styles.iconButton}\n />\n </>\n );\n }\n\n return (\n <div\n className={styles.actionContainer}\n data-mobile-layout={getActionContainerLayout()}\n >\n {content}\n </div>\n );\n };\n\n return (\n <li\n id={id}\n ref={setNodeRef}\n className={styles.item}\n data-item-state={getItemState()}\n data-testid={`${id}-item`}\n {...(shouldEnableSort() ? sortableProps : {})}\n >\n {shouldEnableSort() && (\n <DSDragHandleIcon\n data-testid={`${id}-drag-handle`}\n className={styles.dragHandleIcon}\n data-drag-handle-state={getDragHandleState()}\n />\n )}\n <div\n className={styles.box}\n data-box-state={getBoxState()}\n data-stack-mobile={!errorMessage && (isLoading || editable)}\n >\n {renderContents()}\n {!readOnly && !hasInlineActions && renderActions()}\n </div>\n </li>\n );\n};\n\nexport const FileListItem = memo(Component);\n"],"names":["FileListItem","memo","fileItem","editable","sortable","wrapperWidth","disabled","readOnly","descriptionLabel","onDelete","onEditClick","id","name","size","description","progress","errorMessage","thumbnailImageDataUrl","truncateText","formattedName","setFormattedName","useState","activeId","useContext","FileUploadContext","attributes","listeners","setNodeRef","transform","transition","useSortable","detailSectionRef","useRef","style","CSS","Translate","toString","sortableProps","isLoading","fileSize","FileUploadHelper","formatFileSizeDisplay","hasInlineActions","focusType","getTruncatedText","useCallback","value","widthOfElement","current","getBoundingClientRect","width","StringHelper","truncateOneLine","useEffect","handleDelete","handleEdit","handleKeyDown","event","stopPropagation","shouldDisable","shouldEnableSort","renderNameDescription","_jsxs","_Fragment","children","_jsx","Typography","BodyMD","weight","className","styles.itemDescriptionLabel","_a","styles.itemDescriptionText","Object","assign","ref","styles.item","DSDragHandleIcon","styles.dragHandleIcon","styles.box","shouldShowThumbnail","type","PDF_MIME_TYPE","content","styles.nameSection","BodySM","styles.desktopErrorMessage","ExclamationCircleFillIcon","styles.errorIcon","styles.fileSizeSection","styles.fileSizeText","styles.mobileErrorMessage","thumbnail","FileListItemThumbnail","fileType","styles.extendedNameSection","styles.descriptionFileSizeText","styles.inlineActionContainer","Button","styleType","sizeType","onClick","onKeyDown","icon","PencilIcon","styles.iconButton","BinIcon","renderFileContent","styles.contentSection","renderContents","ProgressBar","styles.actionContainer","renderActions"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"file-list-item.js","sources":["../../../../src/file-upload/file-list-item/file-list-item.tsx"],"sourcesContent":["import { useSortable } from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { DragHandleIcon as DSDragHandleIcon } from \"@lifesg/react-icons/drag-handle\";\nimport { memo, useContext, useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { Form } from \"../../form\";\nimport { Typography } from \"../../typography\";\nimport { FileUploadContext } from \"../context\";\nimport { FileUploadHelper } from \"../helper\";\nimport { FileItemActions } from \"./file-item-actions\";\nimport { FileItemDetails } from \"./file-item-details\";\nimport * as styles from \"./file-list-item.styles\";\nimport { FileListItemThumbnail } from \"./file-list-item-thumbnail\";\nimport type { FileItemMode, FileListItemProps } from \"./types\";\nimport { useTruncatedName } from \"./use-truncated-name\";\n\nconst Component = ({\n fileItem,\n wrapperWidth,\n editable,\n sortable,\n disabled,\n readOnly,\n descriptionLabel,\n fileDescriptionMaxLength,\n descriptionRequired = true,\n onDelete,\n onSave,\n onCancel,\n onBlur,\n onModeChange,\n}: FileListItemProps) => {\n const {\n id,\n name,\n size,\n description,\n progress = 1,\n errorMessage,\n thumbnailImageDataUrl,\n truncateText = true,\n } = fileItem;\n\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const { activeId } = useContext(FileUploadContext);\n const detailSectionRef = useRef<HTMLDivElement>(null);\n const formattedName = useTruncatedName(\n name,\n wrapperWidth,\n truncateText,\n detailSectionRef\n );\n\n const computeMode = (): FileItemMode => {\n if (errorMessage) return \"error\";\n\n const isUploaded = (progress ?? 1) >= 1;\n if (isUploaded && editable && !description) return \"edit\";\n\n return \"display\";\n };\n\n const [currentMode, setCurrentMode] = useState<FileItemMode>(computeMode);\n\n // Sortable mechanism\n const { attributes, listeners, setNodeRef, transform, transition } =\n useSortable({ id, disabled: currentMode === \"edit\" });\n\n // Edit mode state\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const [currentDescription, setCurrentDescription] = useState(\n fileItem.description || \"\"\n );\n\n // =========================================================================\n // DERIVED STATE\n // =========================================================================\n const isLoading = progress < 1;\n const fileSize = FileUploadHelper.formatFileSizeDisplay(size);\n const shouldShowThumbnail =\n !!thumbnailImageDataUrl ||\n fileItem.type === FileUploadHelper.PDF_MIME_TYPE;\n\n const hasInlineActions =\n currentMode === \"display\" && !!description && !!editable;\n const shouldEnableSort = !!sortable && !readOnly;\n const isDisabled = disabled || !!activeId;\n\n const visualStates = useMemo(() => {\n const focusType = activeId\n ? activeId === id\n ? \"self\"\n : \"others\"\n : \"none\";\n\n const itemState = (() => {\n if (isDisabled && focusType === \"none\") return \"disabled\";\n if (shouldEnableSort && focusType === \"self\")\n return \"sortable-active\";\n if (shouldEnableSort) return \"sortable\";\n return undefined;\n })();\n\n const dragHandleState = (() => {\n if (focusType === \"self\") return \"active\";\n if (isDisabled) return \"disabled\";\n return undefined;\n })();\n\n const boxState = (() => {\n if (focusType === \"self\") return \"focused\";\n if (isDisabled) return \"disabled\";\n if (errorMessage) return \"error\";\n return undefined;\n })();\n\n return { itemState, dragHandleState, boxState };\n }, [activeId, id, isDisabled, shouldEnableSort, errorMessage]);\n\n const disableSave =\n descriptionRequired && currentDescription.trim().length === 0;\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n const currentModeRef = useRef(currentMode);\n currentModeRef.current = currentMode;\n const onModeChangeRef = useRef(onModeChange);\n onModeChangeRef.current = onModeChange;\n\n useEffect(() => {\n if (currentMode === \"edit\") {\n onModeChange?.(\"edit\");\n }\n return () => {\n if (currentModeRef.current === \"edit\") {\n onModeChangeRef.current?.(\"display\");\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n useEffect(() => {\n if (errorMessage && currentMode !== \"error\") {\n if (currentMode === \"edit\") {\n onModeChange?.(\"display\");\n }\n setCurrentMode(\"error\");\n } else if (!errorMessage && currentMode === \"error\") {\n const nextMode = computeMode();\n if (nextMode === \"edit\") {\n onModeChange?.(\"edit\");\n }\n setCurrentMode(nextMode);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [errorMessage]);\n\n useEffect(() => {\n if (currentMode === \"edit\") {\n setCurrentDescription(fileItem.description || \"\");\n }\n }, [currentMode, fileItem.description]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleEdit = () => {\n setCurrentMode(\"edit\");\n onModeChange?.(\"edit\");\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n /**\n * Circumvent issue of keydown action activating the sort mechanism\n * rather than the actual action\n */\n if (sortable) {\n event.stopPropagation();\n }\n };\n\n const handleSave = () => {\n if (textareaRef.current) {\n setCurrentMode(\"display\");\n onModeChange?.(\"display\");\n onSave?.(textareaRef.current.value.trim());\n }\n };\n\n const handleCancel = () => {\n setCurrentMode(\"display\");\n onModeChange?.(\"display\");\n onCancel?.();\n };\n\n const handleTextareaChange = (\n event: React.ChangeEvent<HTMLTextAreaElement>\n ) => {\n setCurrentDescription(event.target.value);\n };\n\n const handleTextareaBlur = (\n event: React.FocusEvent<HTMLTextAreaElement>\n ) => {\n onBlur?.(event.target.value);\n };\n\n // =========================================================================\n // RENDER: EDIT MODE\n // =========================================================================\n if (currentMode === \"edit\") {\n return (\n <li data-testid={`${id}-edit-display`} className={styles.editItem}>\n <div className={styles.editContentSection}>\n {shouldShowThumbnail && (\n <FileListItemThumbnail\n thumbnailImageDataUrl={thumbnailImageDataUrl}\n fileType={fileItem.type}\n />\n )}\n <div className={styles.editDetailsSection}>\n <div\n ref={detailSectionRef}\n className={styles.editNameSection}\n >\n <Typography.BodyMD\n className={styles.editFileNameText}\n weight=\"semibold\"\n >\n {formattedName}\n </Typography.BodyMD>\n <Typography.BodyMD\n className={styles.editFileSizeText}\n >\n {fileSize}\n </Typography.BodyMD>\n </div>\n <Form.Textarea\n ref={textareaRef}\n id={`${id}-description-textarea`}\n data-testid={`${id}-textarea`}\n value={currentDescription}\n maxLength={fileDescriptionMaxLength}\n onChange={handleTextareaChange}\n onBlur={handleTextareaBlur}\n rows={3}\n label={\n descriptionLabel ?? {\n children: \"Photo description\",\n subtitle:\n \"Describe this photo to users who may not be able to see the image.\",\n }\n }\n />\n </div>\n </div>\n <FileItemActions\n mode=\"edit\"\n id={id}\n name={name}\n hasThumbnail={shouldShowThumbnail}\n disableSave={disableSave}\n onSave={handleSave}\n onCancel={handleCancel}\n />\n </li>\n );\n }\n\n // =========================================================================\n // RENDER: DISPLAY / ERROR MODE\n // =========================================================================\n const sortableStyle = {\n transform: CSS.Translate.toString(transform),\n transition,\n };\n\n const sortableProps = {\n style: sortableStyle,\n ...attributes,\n ...listeners,\n };\n\n const thumbnail = shouldShowThumbnail ? (\n <FileListItemThumbnail\n thumbnailImageDataUrl={thumbnailImageDataUrl || \"\"}\n fileType={fileItem.type}\n data-testid={`${id}-thumbnail`}\n />\n ) : null;\n\n return (\n <li\n id={id}\n ref={setNodeRef}\n className={styles.item}\n data-item-state={visualStates.itemState}\n data-testid={`${id}-item`}\n {...(shouldEnableSort ? sortableProps : {})}\n >\n {shouldEnableSort && (\n <DSDragHandleIcon\n data-testid={`${id}-drag-handle`}\n className={styles.dragHandleIcon}\n data-drag-handle-state={visualStates.dragHandleState}\n />\n )}\n <div\n className={styles.box}\n data-box-state={visualStates.boxState}\n data-stack-mobile={!errorMessage && (isLoading || editable)}\n >\n <div\n className={styles.contentSection}\n data-has-thumbnail={\n currentMode === \"display\" && shouldShowThumbnail\n }\n >\n {currentMode === \"display\" && thumbnail}\n <FileItemDetails\n mode={currentMode}\n formattedName={formattedName}\n description={description}\n fileSize={fileSize}\n errorMessage={errorMessage}\n isLoading={isLoading}\n descriptionLabel={descriptionLabel}\n detailSectionRef={detailSectionRef}\n >\n {!readOnly && hasInlineActions && (\n <FileItemActions\n mode=\"display\"\n inline\n id={id}\n name={name}\n editable={!!editable}\n isLoading={isLoading}\n progress={progress}\n disabled={isDisabled}\n onDelete={onDelete}\n onEdit={handleEdit}\n onKeyDown={handleKeyDown}\n />\n )}\n </FileItemDetails>\n </div>\n {!readOnly &&\n !hasInlineActions &&\n (currentMode === \"error\" ? (\n <FileItemActions\n mode=\"error\"\n id={id}\n name={name}\n errorMessage={errorMessage}\n onDelete={onDelete}\n />\n ) : (\n <FileItemActions\n mode=\"display\"\n id={id}\n name={name}\n editable={!!editable}\n isLoading={isLoading}\n progress={progress}\n disabled={isDisabled}\n onDelete={onDelete}\n onEdit={handleEdit}\n onKeyDown={handleKeyDown}\n />\n ))}\n </div>\n </li>\n );\n};\n\nexport const FileListItem = memo(Component);\n"],"names":["FileListItem","memo","fileItem","wrapperWidth","editable","sortable","disabled","readOnly","descriptionLabel","fileDescriptionMaxLength","descriptionRequired","onDelete","onSave","onCancel","onBlur","onModeChange","id","name","size","description","progress","errorMessage","thumbnailImageDataUrl","truncateText","activeId","useContext","FileUploadContext","detailSectionRef","useRef","formattedName","useTruncatedName","computeMode","currentMode","setCurrentMode","useState","attributes","listeners","setNodeRef","transform","transition","useSortable","textareaRef","currentDescription","setCurrentDescription","isLoading","fileSize","FileUploadHelper","formatFileSizeDisplay","shouldShowThumbnail","type","PDF_MIME_TYPE","hasInlineActions","shouldEnableSort","isDisabled","visualStates","useMemo","focusType","itemState","dragHandleState","boxState","disableSave","trim","length","currentModeRef","current","onModeChangeRef","useEffect","_a","call","nextMode","handleEdit","handleKeyDown","event","stopPropagation","handleSave","value","handleCancel","handleTextareaChange","target","handleTextareaBlur","_jsxs","className","styles.editItem","children","styles.editContentSection","_jsx","FileListItemThumbnail","fileType","styles.editDetailsSection","ref","styles.editNameSection","Typography","BodyMD","styles.editFileNameText","weight","styles.editFileSizeText","Form","Textarea","maxLength","onChange","rows","label","subtitle","FileItemActions","mode","hasThumbnail","sortableStyle","CSS","Translate","toString","sortableProps","Object","assign","style","thumbnail","styles.item","DSDragHandleIcon","styles.dragHandleIcon","styles.box","styles.contentSection","FileItemDetails","inline","onEdit","onKeyDown"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";require("./file-list-item.
|
|
1
|
+
"use strict";require("./file-list-item.styles_x3a500.css");exports.box="bivlkvo",exports.contentSection="c1jm950n",exports.dragHandleIcon="d1wv8fjl",exports.editContentSection="eqb8x5u",exports.editDetailsSection="eddx9rr",exports.editFileNameText="ek38w4a",exports.editFileSizeText="elwke9e",exports.editItem="e18pxk0j",exports.editNameSection="e1dhzflv",exports.item="i14h64yt";
|
|
2
2
|
//# sourceMappingURL=file-list-item.styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-list-item.styles.js","sources":["../../../../src/file-upload/file-list-item/file-list-item.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport {\n Border,\n Colour,\n
|
|
1
|
+
{"version":3,"file":"file-list-item.styles.js","sources":["../../../../src/file-upload/file-list-item/file-list-item.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport {\n Border,\n Colour,\n MediaQuery,\n Radius,\n Shadow,\n Spacing,\n} from \"../../theme\";\n\n// =============================================================================\n// EDIT MODE STYLES\n// =============================================================================\n\nexport const editItem = css`\n display: flex;\n flex-direction: column;\n padding: ${Spacing[\"spacing-32\"]};\n background: ${Colour[\"bg-primary-subtlest\"]};\n border: ${Border[\"width-010\"]} ${Border.solid} ${Colour.border};\n border-radius: ${Radius[\"sm\"]};\n\n &:not(:last-child) {\n margin-bottom: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const editContentSection = css`\n display: flex;\n align-items: flex-start;\n margin-bottom: ${Spacing[\"spacing-16\"]};\n width: 100%;\n`;\n\nexport const editDetailsSection = css`\n display: flex;\n flex: 1;\n flex-direction: column;\n`;\n\nexport const editNameSection = css`\n width: 100%;\n display: flex;\n justify-content: space-between;\n margin-bottom: ${Spacing[\"spacing-16\"]};\n\n ${MediaQuery.MaxWidth.md} {\n flex-direction: column;\n justify-content: flex-start;\n }\n`;\n\nexport const editFileNameText = css`\n display: flex;\n flex: 1;\n margin-right: ${Spacing[\"spacing-16\"]};\n\n ${MediaQuery.MaxWidth.md} {\n margin-right: 0;\n margin-bottom: ${Spacing[\"spacing-8\"]};\n }\n`;\n\nexport const editFileSizeText = css`\n color: ${Colour[\"text-subtler\"]};\n`;\n\n// =============================================================================\n// DISPLAY / ERROR MODE STYLES\n// =============================================================================\n\nexport type ItemFocusType = \"self\" | \"others\" | \"none\";\n\nexport const item = css`\n display: flex;\n align-items: center;\n width: 100%;\n border: none;\n\n &:not(:last-child) {\n margin-bottom: ${Spacing[\"spacing-16\"]};\n }\n &[data-item-state=\"disabled\"] {\n cursor: not-allowed;\n }\n\n &[data-item-state=\"sortable\"] {\n &:hover {\n cursor: grab;\n }\n\n // Following recommendation by the library for touch events\n // https://docs.dndkit.com/api-documentation/sensors/touch#recommendations\n touch-action: manipulation;\n }\n\n &[data-item-state=\"sortable-active\"] {\n cursor: grabbing;\n\n // Following recommendation by the library for touch events\n // https://docs.dndkit.com/api-documentation/sensors/touch#recommendations\n touch-action: manipulation;\n }\n`;\n\nexport const dragHandleIcon = css`\n margin-right: ${Spacing[\"spacing-16\"]};\n height: 1.5rem;\n width: 1.5rem;\n color: ${Colour[\"icon\"]};\n\n &[data-drag-handle-state=\"active\"] {\n color: ${Colour[\"icon-primary\"]};\n }\n\n &[data-drag-handle-state=\"disabled\"] {\n color: ${Colour[\"icon-disabled\"]};\n }\n`;\n\nexport const box = css`\n background: ${Colour[\"bg-primary-subtlest\"]};\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n border-radius: ${Radius[\"sm\"]};\n padding: ${Spacing[\"spacing-16\"]} ${Spacing[\"spacing-32\"]};\n display: flex;\n align-items: center;\n width: 100%;\n\n ${MediaQuery.MaxWidth.md} {\n padding: ${Spacing[\"spacing-16\"]};\n }\n\n &[data-box-state=\"focused\"] {\n border-color: ${Colour[\"border-focus\"]};\n box-shadow: ${Shadow[\"xs-focus-strong\"]};\n }\n\n &[data-box-state=\"disabled\"] {\n border-color: ${Colour[\"border-disabled\"]};\n }\n\n &[data-box-state=\"error\"] {\n background: ${Colour[\"bg-error\"]};\n border-color: ${Colour[\"border-error\"]};\n }\n\n &[data-stack-mobile=\"true\"] {\n ${MediaQuery.MaxWidth.md} {\n flex-direction: column;\n align-items: flex-start;\n }\n }\n`;\n\nexport const contentSection = css`\n display: flex;\n flex: 1;\n align-items: center;\n\n ${MediaQuery.MaxWidth.md} {\n flex-direction: column;\n width: 100%;\n align-items: flex-start;\n }\n\n &[data-has-thumbnail=\"true\"] {\n align-items: center;\n\n ${MediaQuery.MaxWidth.md} {\n flex-direction: row;\n align-items: center;\n }\n }\n`;\n"],"names":[],"mappings":"iHAyHgB,iCAmCW,kCAlDA,sCA9EI,qCAOA,mCAkBF,mCAWA,2BAjDR,mCA0BO,wBAiCX"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
@layer fds{.e18pxk0j{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding:var(--fds-spacing-32);background:var(--fds-colour-bg-primary-subtlest);border:var(--fds-border-width-010) var(--fds-border-style-solid) var(--fds-colour-border);border-radius:var(--fds-radius-sm);}.e18pxk0j:not(:last-child){margin-bottom:var(--fds-spacing-16);}
|
|
2
|
+
.eqb8x5u{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;margin-bottom:var(--fds-spacing-16);width:100%;}
|
|
3
|
+
.eddx9rr{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1;-ms-flex:1;flex:1;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}
|
|
4
|
+
.e1dhzflv{width:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:space-between;-webkit-justify-content:space-between;justify-content:space-between;margin-bottom:var(--fds-spacing-16);}:where(body.fds-breakpoint-md-max) .e1dhzflv{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start;}
|
|
5
|
+
.ek38w4a{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1;-ms-flex:1;flex:1;margin-right:var(--fds-spacing-16);}:where(body.fds-breakpoint-md-max) .ek38w4a{margin-right:0;margin-bottom:var(--fds-spacing-8);}
|
|
6
|
+
.elwke9e{color:var(--fds-colour-text-subtler);}
|
|
7
|
+
.i14h64yt{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;width:100%;border:none;}.i14h64yt:not(:last-child){margin-bottom:var(--fds-spacing-16);}.i14h64yt[data-item-state="disabled"]{cursor:not-allowed;}.i14h64yt[data-item-state="sortable"]{touch-action:manipulation;}.i14h64yt[data-item-state="sortable"]:hover{cursor:-webkit-grab;cursor:grab;}.i14h64yt[data-item-state="sortable-active"]{cursor:-webkit-grabbing;cursor:grabbing;touch-action:manipulation;}
|
|
8
|
+
.d1wv8fjl{margin-right:var(--fds-spacing-16);height:1.5rem;width:1.5rem;color:var(--fds-colour-icon);}.d1wv8fjl[data-drag-handle-state="active"]{color:var(--fds-colour-icon-primary);}.d1wv8fjl[data-drag-handle-state="disabled"]{color:var(--fds-colour-icon-disabled);}
|
|
9
|
+
.bivlkvo{background:var(--fds-colour-bg-primary-subtlest);border:var(--fds-border-width-010) var(--fds-border-style-solid) var(--fds-colour-border);border-radius:var(--fds-radius-sm);padding:var(--fds-spacing-16) var(--fds-spacing-32);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;width:100%;}:where(body.fds-breakpoint-md-max) .bivlkvo{padding:var(--fds-spacing-16);}.bivlkvo[data-box-state="focused"]{border-color:var(--fds-colour-border-focus);box-shadow:var(--fds-shadow-xs-focus-strong);}.bivlkvo[data-box-state="disabled"]{border-color:var(--fds-colour-border-disabled);}.bivlkvo[data-box-state="error"]{background:var(--fds-colour-bg-error);border-color:var(--fds-colour-border-error);}:where(body.fds-breakpoint-md-max) .bivlkvo[data-stack-mobile="true"]{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;}
|
|
10
|
+
.c1jm950n{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1;-ms-flex:1;flex:1;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}:where(body.fds-breakpoint-md-max) .c1jm950n{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;width:100%;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;}.c1jm950n[data-has-thumbnail="true"]{-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}:where(body.fds-breakpoint-md-max) .c1jm950n[data-has-thumbnail="true"]{-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var e=require("react");require("../../util/calendar-helper.js"),require("../../external/dayjs/dayjs.min.js"),require("../../util/simple-id-generator.js");var r=require("../../util/string-helper.js");require("@react-aria/live-announcer"),exports.useTruncatedName=function(t,n,u,i){const[a,s]=e.useState(),c=e.useCallback((e=>{if(!u)return e;const t=(null==i?void 0:i.current)?i.current.getBoundingClientRect().width:0;return r.StringHelper.truncateOneLine(e,t,t/2,t/2/8,16)}),[u,i]);return e.useEffect((()=>{s(c(t))}),[n,c,t]),a};
|
|
2
|
+
//# sourceMappingURL=use-truncated-name.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-truncated-name.js","sources":["../../../../src/file-upload/file-list-item/use-truncated-name.ts"],"sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\n\nimport { StringHelper } from \"../../util\";\n\nexport function useTruncatedName(\n name: string,\n wrapperWidth: number,\n truncateText: boolean,\n elementRef: React.RefObject<HTMLElement | null>\n): string | undefined {\n const [formattedName, setFormattedName] = useState<string>();\n\n const getTruncatedText = useCallback(\n (value: string) => {\n if (!truncateText) return value;\n\n const widthOfElement = elementRef?.current\n ? elementRef.current.getBoundingClientRect().width\n : 0;\n\n return StringHelper.truncateOneLine(\n value,\n widthOfElement,\n widthOfElement / 2,\n widthOfElement / 2 / 8,\n 16\n );\n },\n [truncateText, elementRef]\n );\n\n useEffect(() => {\n setFormattedName(getTruncatedText(name));\n }, [wrapperWidth, getTruncatedText, name]);\n\n return formattedName;\n}\n"],"names":["name","wrapperWidth","truncateText","elementRef","formattedName","setFormattedName","useState","getTruncatedText","useCallback","value","widthOfElement","current","getBoundingClientRect","width","StringHelper","truncateOneLine","useEffect"],"mappings":"mRAIM,SACFA,EACAC,EACAC,EACAC,GAEA,MAAOC,EAAeC,GAAoBC,aAEpCC,EAAmBC,eACpBC,IACG,IAAKP,EAAc,OAAOO,EAE1B,MAAMC,GAAiBP,aAAU,EAAVA,EAAYQ,SAC7BR,EAAWQ,QAAQC,wBAAwBC,MAC3C,EAEN,OAAOC,eAAaC,gBAChBN,EACAC,EACAA,EAAiB,EACjBA,EAAiB,EAAI,EACrB,GACH,GAEL,CAACR,EAAcC,IAOnB,OAJAa,EAAAA,WAAU,KACNX,EAAiBE,EAAiBP,GAAM,GACzC,CAACC,EAAcM,EAAkBP,IAE7BI,CACX"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var e=require("react/jsx-runtime"),t=require("@lifesg/react-icons/chevron-down"),n=require("@lifesg/react-icons/tick"),r=require("clsx"),s=require("react");require("../../theme/theme-provider/index.js"),require("../../theme/theme-provider/context.js"),require("../../theme/tokens/border.js"),require("../../theme/tokens/colour.js"),require("../../theme/tokens/font.js"),require("../../theme/tokens/media-query.js");var i=require("../../theme/utils/use-apply-styles.js");require("../../theme/utils/use-media-query.js");var a=require("../../typography/index.js");require("../../util/calendar-helper.js"),require("../../external/dayjs/dayjs.min.js");var
|
|
1
|
+
"use strict";var e=require("react/jsx-runtime"),t=require("@lifesg/react-icons/chevron-down"),n=require("@lifesg/react-icons/tick"),r=require("clsx"),s=require("react");require("../../theme/theme-provider/index.js"),require("../../theme/theme-provider/context.js"),require("../../theme/tokens/border.js"),require("../../theme/tokens/colour.js"),require("../../theme/tokens/font.js"),require("../../theme/tokens/media-query.js");var i=require("../../theme/utils/use-apply-styles.js");require("../../theme/utils/use-media-query.js");var a=require("../../typography/index.js");require("../../util/calendar-helper.js"),require("../../external/dayjs/dayjs.min.js");var l=require("../../util/simple-id-generator.js");require("../../util/string-helper.js"),require("@react-aria/live-announcer");var d=require("./local-nav-dropdown.styles.js");function o(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var c=o(r);const u=o(s).default.forwardRef((({defaultLabel:r,stickyOffset:o=0,onNavItemSelect:u,items:f,selectedItemIndex:v,id:h,"data-testid":x,className:w,renderItem:y},j)=>{const g=s.useRef(null),b=s.useRef(null),I=s.useRef(null),k=s.useRef(null),q=s.useRef([]),[E,S]=s.useState(!1),[L,N]=s.useState(!1),[D,C]=s.useState(0),[A,R]=s.useState(0),[$,W]=s.useState(0),[B,H]=s.useState(0),T=x||"local-nav-dropdown",z=l.useId();s.useImperativeHandle(j,(()=>I.current)),i.useApplyStyle(I,{[d.tokens.navWrapper.stickyOffset]:`${o}px`,[d.tokens.navWrapper.sideMargin]:`${$}px`}),i.useApplyStyle(k,{[d.tokens.navItemList.viewportHeight]:D-A-o+"px"});const K="number"==typeof v&&v>=0&&E?f[v].title:r;s.useEffect((()=>{if(b.current){const e=b.current.getBoundingClientRect().height;R(e)}}),[]),s.useEffect((()=>(M(),()=>{O("remove")})),[]),s.useEffect((()=>{O(L&&E?"add":"remove")}),[L,E]),s.useEffect((()=>{C(window.innerHeight);const e=()=>{C(window.innerHeight)};return window.addEventListener("resize",e),()=>window.removeEventListener("resize",e)}),[]),s.useEffect((()=>{const e=new IntersectionObserver((e=>{const[t]=e;S(!t.isIntersecting)}),{threshold:1,rootMargin:`-${o}px 0px 0px 0px`});return g.current&&e.observe(g.current),()=>e.disconnect()}),[o]),s.useEffect((()=>{const e=()=>{const e=null==I?void 0:I.current;if(e){const t=e.getBoundingClientRect(),n=document.body.clientWidth-t.right,r=t.left,s=Math.max(n,r);W(s)}};return e(),window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}}),[]),s.useEffect((()=>{var e;L&&(null===(e=q.current[B])||void 0===e||e.focus())}),[L,B]);const M=()=>{if(!document.getElementById(m)){const e=document.createElement("style");e.id=m;const t=document.documentElement.clientWidth,n=window.innerWidth-t;e.innerHTML=`\n\t\t\t\t.${p} {\n\t\t\t\t\toverflow: hidden;\n\t\t\t\t\tpadding-right: ${n}px !important;\n\t\t\t\t\t-ms-overflow-style: none;\n\t\t\t\t\tscrollbar-width: none;\n\t\t\t\t}\n\n\t\t\t\t.${p}::-webkit-scrollbar {\n\t\t\t\t\tdisplay: none;\n\t\t\t\t}\n\t\t\t`,document.body.appendChild(e)}},O=e=>{const t=document.body.classList.contains(p);"add"!==e||t?"remove"===e&&t&&document.body.classList.remove(p):document.body.classList.add(p)},U=(e,t)=>{const{key:n}=e;"Enter"!==n&&" "!==n||(e.preventDefault(),t(e))};return e.jsxs(e.Fragment,{children:[e.jsx("span",{ref:g,"data-testid":"sticky-ref"}),e.jsxs("nav",{ref:I,id:h,"data-testid":T,className:c.default(d.navWrapper,E&&d.navWrapperStickied,w),children:[e.jsxs("div",{ref:b,role:"button",onClick:()=>{N((e=>!e))},onKeyDown:e=>{const{key:t}=e;"ArrowDown"===t?(e.preventDefault(),L||N(!0),H(0)):"ArrowUp"===t?(e.preventDefault(),L||N(!0),H(f.length-1)):"Enter"===t||" "===t?(e.preventDefault(),N(!0),H(0)):("Tab"===t||"Escape"===t)&&N(!1)},"data-testid":`${T}-label`,className:c.default(d.navSelect,L&&d.navSelectExpanded),"aria-haspopup":"true","aria-expanded":L,"aria-controls":z,tabIndex:0,children:[e.jsx(a.Typography.BodyBL,{weight:"semibold",children:K}),e.jsx(t.ChevronDownIcon,{className:c.default(d.navSelectIcon,L&&d.navSelectIconExpanded)})]}),L&&e.jsx("ul",{ref:k,id:z,role:"menu",onKeyDown:e=>{var t;const{key:n}=e;if("ArrowDown"===n){e.preventDefault();const t=(B+1)%f.length;H(t)}else if("ArrowUp"===n){e.preventDefault();const t=B>0?B-1:f.length-1;H(t)}else"Tab"===n?N(!1):"Escape"===n&&(N(!1),null===(t=b.current)||void 0===t||t.focus())},"data-testid":`${T}-dropdown-list`,className:d.navItemList,children:f.map(((t,r)=>(({handleClick:t,isSelected:r,item:s,renderItem:i,index:a})=>{const{id:l,title:o,titleAddon:u}=s;return i?e.jsx("li",{id:l,role:"menuitem",onClick:t,onKeyDown:e=>U(e,t),"aria-current":!!r||void 0,tabIndex:-1,ref:e=>{q.current[a]=e},children:i(s,{selected:r,stickied:E})},a):e.jsxs("li",{id:l,role:"menuitem",className:c.default(d.navItem,r&&E&&d.navItemSelected),onClick:t,onKeyDown:e=>U(e,t),"aria-current":!!r||void 0,tabIndex:-1,ref:e=>{q.current[a]=e},children:[r&&e.jsx("span",{className:d.leftAddon,children:e.jsx(n.TickIcon,{className:d.tickIcon})}),u?e.jsxs("span",{className:d.titleContainer,children:[u.left&&e.jsx("span",{className:d.leftAddon,children:u.left}),e.jsx("div",{className:c.default(d.navItemLabel,r&&d.navItemLabelSelected),children:o}),u.right&&e.jsx("span",{className:d.rightAddon,children:u.right})]}):e.jsx("div",{className:c.default(d.navItemLabel,r&&d.navItemLabelSelected),children:o})]},a)})({handleClick:e=>((e,t,n)=>{u&&u(e,t,n),N(!1)})(e,t,r),isSelected:r===v,item:t,renderItem:y,index:r})))}),L&&E&&e.jsx("div",{className:d.backdrop,onClick:()=>{N(!1)}})]})]})})),m="lifesg-ds-local-nav-dropdown-stylesheet",p="lifesg-ds-local-nav-dropdown-open";exports.LocalNavDropdown=u;
|
|
2
2
|
//# sourceMappingURL=local-nav-dropdown.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-nav-dropdown.js","sources":["../../../../src/local-nav/local-nav-dropdown/local-nav-dropdown.tsx"],"sourcesContent":["import { ChevronDownIcon } from \"@lifesg/react-icons/chevron-down\";\nimport { TickIcon } from \"@lifesg/react-icons/tick\";\nimport clsx from \"clsx\";\nimport React, { useEffect, useImperativeHandle, useRef, useState } from \"react\";\n\nimport { useApplyStyle } from \"../../theme\";\nimport { Typography } from \"../../typography\";\nimport { useId } from \"../../util\";\nimport type { LocalNavDropdownItemComponentProps } from \"../internal-types\";\nimport type { LocalNavDropdownProps, LocalNavItemProps } from \"../types\";\nimport * as styles from \"./local-nav-dropdown.styles\";\n\nconst Component = (\n {\n defaultLabel,\n stickyOffset = 0,\n onNavItemSelect,\n items,\n selectedItemIndex,\n id,\n \"data-testid\": testId,\n className,\n renderItem,\n }: LocalNavDropdownProps,\n ref: React.Ref<HTMLElement>\n): JSX.Element => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const detectStickyRef = useRef<HTMLSpanElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n const navWrapperRef = useRef<HTMLElement>(null);\n const navItemListRef = useRef<HTMLUListElement>(null);\n const listItemRefs = useRef<(HTMLLIElement | null)[]>([]);\n const [isStickied, setIsStickied] = useState<boolean>(false);\n const [isDropdownExpanded, setIsDropdownExpanded] =\n useState<boolean>(false);\n const [viewportHeight, setViewportHeight] = useState(0);\n const [dropdowntHeight, setDropdownHeight] = useState(0);\n const [dynamicMargin, setDynamicMargin] = useState(0);\n const [focusedIndex, setFocusedIndex] = useState(0);\n const navTestId = testId || \"local-nav-dropdown\";\n const dropdownListId = useId();\n\n useImperativeHandle(ref, () => navWrapperRef.current!);\n\n useApplyStyle(navWrapperRef, {\n [styles.tokens.navWrapper.stickyOffset]: `${stickyOffset}px`,\n [styles.tokens.navWrapper.sideMargin]: `${dynamicMargin}px`,\n });\n\n useApplyStyle(navItemListRef, {\n [styles.tokens.navItemList.viewportHeight]: `${\n viewportHeight - dropdowntHeight - stickyOffset\n }px`,\n });\n\n const labelText =\n typeof selectedItemIndex === \"number\" &&\n selectedItemIndex >= 0 &&\n isStickied\n ? items[selectedItemIndex].title\n : defaultLabel;\n\n // =============================================================================\n // EFFECTS, EVENT LISTENERS\n // ============================================================================\n\n useEffect(() => {\n if (dropdownRef.current) {\n const dropdownHeight =\n dropdownRef.current.getBoundingClientRect().height;\n setDropdownHeight(dropdownHeight);\n }\n }, []);\n\n useEffect(() => {\n addStylesheetForDocumentBody();\n return () => {\n applyBodyStyleClass(\"remove\");\n };\n }, []);\n\n useEffect(() => {\n if (isDropdownExpanded && isStickied) {\n applyBodyStyleClass(\"add\");\n } else {\n applyBodyStyleClass(\"remove\");\n }\n }, [isDropdownExpanded, isStickied]);\n\n useEffect(() => {\n setViewportHeight(window.innerHeight);\n const handleResize = () => {\n setViewportHeight(window.innerHeight);\n };\n window.addEventListener(\"resize\", handleResize);\n return () => window.removeEventListener(\"resize\", handleResize);\n }, []);\n\n useEffect(() => {\n const callback = (entries: IntersectionObserverEntry[]) => {\n const [entry] = entries;\n setIsStickied(!entry.isIntersecting);\n };\n\n const observer = new IntersectionObserver(callback, {\n threshold: 1,\n rootMargin: `-${stickyOffset}px 0px 0px 0px`,\n });\n\n if (detectStickyRef.current) {\n observer.observe(detectStickyRef.current);\n }\n\n return () => observer.disconnect();\n }, [stickyOffset]);\n\n useEffect(() => {\n const adjustPadding = () => {\n const dropdown = navWrapperRef?.current;\n if (dropdown) {\n const dropdownRect = dropdown.getBoundingClientRect();\n const spaceToRight =\n document.body.clientWidth - dropdownRect.right;\n const spaceToLeft = dropdownRect.left;\n // Calculate the padding needed to balance the dropdown in the viewport\n const sidePadding = Math.max(spaceToRight, spaceToLeft);\n setDynamicMargin(sidePadding);\n }\n };\n adjustPadding();\n\n window.addEventListener(\"resize\", adjustPadding);\n\n return () => {\n window.removeEventListener(\"resize\", adjustPadding);\n };\n }, []);\n\n useEffect(() => {\n if (isDropdownExpanded) {\n listItemRefs.current[focusedIndex]?.focus();\n }\n }, [isDropdownExpanded, focusedIndex]);\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n\n const addStylesheetForDocumentBody = () => {\n /**\n * This stylesheet is to manipulate the <body>. We only add once\n */\n if (!document.getElementById(STYLESHEET_ID)) {\n const overlayStyleSheet = document.createElement(\"style\");\n overlayStyleSheet.id = STYLESHEET_ID;\n\n const documentWidth = document.documentElement.clientWidth;\n const windowWidth = window.innerWidth;\n const scrollBarWidth = windowWidth - documentWidth;\n\n overlayStyleSheet.innerHTML = `\n\t\t\t\t.${DROPDOWN_OPEN_CLASSNAME} {\n\t\t\t\t\toverflow: hidden;\n\t\t\t\t\tpadding-right: ${scrollBarWidth}px !important;\n\t\t\t\t\t-ms-overflow-style: none;\n\t\t\t\t\tscrollbar-width: none;\n\t\t\t\t}\n\n\t\t\t\t.${DROPDOWN_OPEN_CLASSNAME}::-webkit-scrollbar {\n\t\t\t\t\tdisplay: none;\n\t\t\t\t}\n\t\t\t`;\n\n document.body.appendChild(overlayStyleSheet);\n }\n };\n\n const applyBodyStyleClass = (action: \"add\" | \"remove\") => {\n const isOverlayStyleClassApplied = document.body.classList.contains(\n DROPDOWN_OPEN_CLASSNAME\n );\n\n if (action === \"add\" && !isOverlayStyleClassApplied) {\n document.body.classList.add(DROPDOWN_OPEN_CLASSNAME);\n } else if (action === \"remove\" && isOverlayStyleClassApplied) {\n document.body.classList.remove(DROPDOWN_OPEN_CLASSNAME);\n }\n };\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n\n const handleToggleDropdown = () => {\n setIsDropdownExpanded((prev) => !prev);\n };\n\n const handleDismissBackdrop = () => {\n setIsDropdownExpanded(false);\n };\n\n const handleNavItemClick = (\n e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>,\n item: LocalNavItemProps,\n index: number\n ) => {\n if (onNavItemSelect) {\n onNavItemSelect(e, item, index);\n }\n setIsDropdownExpanded(false);\n };\n\n const handleNavItemKeyDown = (\n e: React.KeyboardEvent<HTMLElement>,\n handleClick: (\n e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>\n ) => void\n ) => {\n const { key } = e;\n\n if (key === \"Enter\" || key === \" \") {\n e.preventDefault();\n handleClick(e);\n }\n };\n\n const handleNavSelectKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n const { key } = e;\n\n if (key === \"ArrowDown\") {\n e.preventDefault();\n if (!isDropdownExpanded) {\n setIsDropdownExpanded(true);\n }\n setFocusedIndex(0);\n } else if (key === \"ArrowUp\") {\n e.preventDefault();\n if (!isDropdownExpanded) {\n setIsDropdownExpanded(true);\n }\n setFocusedIndex(items.length - 1);\n } else if (key === \"Enter\" || key === \" \") {\n e.preventDefault();\n setIsDropdownExpanded(true);\n setFocusedIndex(0);\n } else if (key === \"Tab\") {\n setIsDropdownExpanded(false);\n } else if (key === \"Escape\") {\n setIsDropdownExpanded(false);\n }\n };\n\n const handleNavItemListKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n const { key } = e;\n\n if (key === \"ArrowDown\") {\n e.preventDefault();\n const nextIndex = (focusedIndex + 1) % items.length;\n setFocusedIndex(nextIndex);\n } else if (key === \"ArrowUp\") {\n e.preventDefault();\n const prevIndex =\n focusedIndex > 0 ? focusedIndex - 1 : items.length - 1;\n setFocusedIndex(prevIndex);\n } else if (key === \"Tab\") {\n setIsDropdownExpanded(false);\n } else if (key === \"Escape\") {\n setIsDropdownExpanded(false);\n dropdownRef.current?.focus();\n }\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n\n const renderDropdownNavItem = ({\n handleClick,\n isSelected,\n item,\n renderItem,\n index,\n }: LocalNavDropdownItemComponentProps) => {\n const { id, title } = item;\n\n if (renderItem) {\n return (\n <li\n id={id}\n key={index}\n role=\"menuitem\"\n onClick={handleClick}\n onKeyDown={(e) => handleNavItemKeyDown(e, handleClick)}\n aria-current={isSelected ? true : undefined}\n tabIndex={-1}\n ref={(el) => {\n listItemRefs.current[index] = el;\n }}\n >\n {renderItem(item, {\n selected: isSelected,\n stickied: isStickied,\n })}\n </li>\n );\n }\n\n return (\n <li\n id={id}\n key={index}\n role=\"menuitem\"\n className={clsx(\n styles.navItem,\n isSelected && isStickied && styles.navItemSelected\n )}\n onClick={handleClick}\n onKeyDown={(e) => handleNavItemKeyDown(e, handleClick)}\n aria-current={isSelected ? true : undefined}\n tabIndex={-1}\n ref={(el) => {\n listItemRefs.current[index] = el as HTMLLIElement;\n }}\n >\n {isSelected && <TickIcon className={styles.tickIcon} />}\n <div\n className={clsx(\n styles.navItemLabel,\n isSelected && styles.navItemLabelSelected\n )}\n >\n {title}\n </div>\n </li>\n );\n };\n\n return (\n <>\n <span ref={detectStickyRef} data-testid={\"sticky-ref\"} />\n <nav\n ref={navWrapperRef}\n id={id}\n data-testid={navTestId}\n className={clsx(\n styles.navWrapper,\n isStickied && styles.navWrapperStickied,\n className\n )}\n >\n <div\n ref={dropdownRef}\n role=\"button\"\n onClick={handleToggleDropdown}\n onKeyDown={handleNavSelectKeyDown}\n data-testid={`${navTestId}-label`}\n className={clsx(\n styles.navSelect,\n isDropdownExpanded && styles.navSelectExpanded\n )}\n aria-haspopup=\"true\"\n aria-expanded={isDropdownExpanded}\n aria-controls={dropdownListId}\n tabIndex={0}\n >\n <Typography.BodyBL weight=\"semibold\">\n {labelText}\n </Typography.BodyBL>\n <ChevronDownIcon\n className={clsx(\n styles.navSelectIcon,\n isDropdownExpanded && styles.navSelectIconExpanded\n )}\n />\n </div>\n {isDropdownExpanded && (\n <ul\n ref={navItemListRef}\n id={dropdownListId}\n role=\"menu\"\n onKeyDown={handleNavItemListKeyDown}\n data-testid={`${navTestId}-dropdown-list`}\n className={styles.navItemList}\n >\n {items.map((item, i) =>\n renderDropdownNavItem({\n handleClick: (e) =>\n handleNavItemClick(e, item, i),\n isSelected: i === selectedItemIndex,\n item,\n renderItem,\n index: i,\n })\n )}\n </ul>\n )}\n {isDropdownExpanded && isStickied && (\n <div\n className={styles.backdrop}\n onClick={handleDismissBackdrop}\n />\n )}\n </nav>\n </>\n );\n};\n// @catalog\n/**\n * A collapsible dropdown used for in-page navigation on mobile viewports.\n *\n * Use `LocalNavDropdown` when the page has multiple named sections and screen\n * width is insufficient for a persistent sidebar.\n *\n * @remarks\n * This component adopts a fundamentally different interaction model from\n * `LocalNavMenu`: it collapses into a single trigger button and uses a menu\n * overlay, making it suited for mobile while `LocalNavMenu` suits desktop.\n * @keywords in-page navigation, sections\n */\nexport const LocalNavDropdown = React.forwardRef(Component);\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\nconst STYLESHEET_ID = \"lifesg-ds-local-nav-dropdown-stylesheet\";\nconst DROPDOWN_OPEN_CLASSNAME = \"lifesg-ds-local-nav-dropdown-open\";\n"],"names":["LocalNavDropdown","React","forwardRef","defaultLabel","stickyOffset","onNavItemSelect","items","selectedItemIndex","id","testId","className","renderItem","ref","detectStickyRef","useRef","dropdownRef","navWrapperRef","navItemListRef","listItemRefs","isStickied","setIsStickied","useState","isDropdownExpanded","setIsDropdownExpanded","viewportHeight","setViewportHeight","dropdowntHeight","setDropdownHeight","dynamicMargin","setDynamicMargin","focusedIndex","setFocusedIndex","navTestId","dropdownListId","useId","useImperativeHandle","current","useApplyStyle","styles.tokens","navWrapper","sideMargin","navItemList","labelText","title","useEffect","dropdownHeight","getBoundingClientRect","height","addStylesheetForDocumentBody","applyBodyStyleClass","window","innerHeight","handleResize","addEventListener","removeEventListener","observer","IntersectionObserver","entries","entry","isIntersecting","threshold","rootMargin","observe","disconnect","adjustPadding","dropdown","dropdownRect","spaceToRight","document","body","clientWidth","right","spaceToLeft","left","sidePadding","Math","max","_a","focus","getElementById","STYLESHEET_ID","overlayStyleSheet","createElement","documentWidth","documentElement","scrollBarWidth","innerWidth","innerHTML","DROPDOWN_OPEN_CLASSNAME","appendChild","action","isOverlayStyleClassApplied","classList","contains","remove","add","handleNavItemKeyDown","e","handleClick","key","preventDefault","_jsxs","_Fragment","children","_jsx","clsx","styles.navWrapper","styles.navWrapperStickied","role","onClick","prev","onKeyDown","length","styles.navSelect","styles.navSelectExpanded","tabIndex","Typography","BodyBL","weight","ChevronDownIcon","styles.navSelectIcon","styles.navSelectIconExpanded","nextIndex","prevIndex","styles.navItemList","map","item","i","isSelected","index","undefined","el","selected","stickied","styles.navItem","styles.navItemSelected","TickIcon","styles.tickIcon","styles.navItemLabel","styles.navItemLabelSelected","renderDropdownNavItem","handleNavItemClick","styles.backdrop"],"mappings":"u5BAYA,MAyZaA,OAAmBC,QAAMC,YAzZpB,EAEVC,eACAC,eAAe,EACfC,kBACAC,QACAC,oBACAC,KACA,cAAeC,EACfC,YACAC,cAEJC,KAKA,MAAMC,EAAkBC,EAAAA,OAAwB,MAC1CC,EAAcD,EAAAA,OAAuB,MACrCE,EAAgBF,EAAAA,OAAoB,MACpCG,EAAiBH,EAAAA,OAAyB,MAC1CI,EAAeJ,EAAAA,OAAiC,KAC/CK,EAAYC,GAAiBC,EAAAA,UAAkB,IAC/CC,EAAoBC,GACvBF,EAAAA,UAAkB,IACfG,EAAgBC,GAAqBJ,EAAAA,SAAS,IAC9CK,EAAiBC,GAAqBN,EAAAA,SAAS,IAC/CO,EAAeC,GAAoBR,EAAAA,SAAS,IAC5CS,EAAcC,GAAmBV,EAAAA,SAAS,GAC3CW,EAAYvB,GAAU,qBACtBwB,EAAiBC,EAAAA,QAEvBC,EAAAA,oBAAoBvB,GAAK,IAAMI,EAAcoB,UAE7CC,EAAAA,cAAcrB,EAAe,CACzB,CAACsB,EAAAA,OAAcC,WAAWnC,cAAe,GAAGA,MAC5C,CAACkC,EAAAA,OAAcC,WAAWC,YAAa,GAAGZ,QAG9CS,EAAAA,cAAcpB,EAAgB,CAC1B,CAACqB,EAAAA,OAAcG,YAAYjB,gBACvBA,EAAiBE,EAAkBtB,EADK,OAKhD,MAAMsC,EAC2B,iBAAtBnC,GACPA,GAAqB,GACrBY,EACMb,EAAMC,GAAmBoC,MACzBxC,EAMVyC,EAAAA,WAAU,KACN,GAAI7B,EAAYqB,QAAS,CACrB,MAAMS,EACF9B,EAAYqB,QAAQU,wBAAwBC,OAChDpB,EAAkBkB,EACtB,IACD,IAEHD,EAAAA,WAAU,KACNI,IACO,KACHC,EAAoB,SAAS,IAElC,IAEHL,EAAAA,WAAU,KAEFK,EADA3B,GAAsBH,EACF,MAEA,SACxB,GACD,CAACG,EAAoBH,IAExByB,EAAAA,WAAU,KACNnB,EAAkByB,OAAOC,aACzB,MAAMC,EAAe,KACjB3B,EAAkByB,OAAOC,YAAY,EAGzC,OADAD,OAAOG,iBAAiB,SAAUD,GAC3B,IAAMF,OAAOI,oBAAoB,SAAUF,EAAa,GAChE,IAEHR,EAAAA,WAAU,KACN,MAKMW,EAAW,IAAIC,sBALHC,IACd,MAAOC,GAASD,EAChBrC,GAAesC,EAAMC,eAAe,GAGY,CAChDC,UAAW,EACXC,WAAY,IAAIzD,oBAOpB,OAJIS,EAAgBuB,SAChBmB,EAASO,QAAQjD,EAAgBuB,SAG9B,IAAMmB,EAASQ,YAAY,GACnC,CAAC3D,IAEJwC,EAAAA,WAAU,KACN,MAAMoB,EAAgB,KAClB,MAAMC,EAAWjD,aAAa,EAAbA,EAAeoB,QAChC,GAAI6B,EAAU,CACV,MAAMC,EAAeD,EAASnB,wBACxBqB,EACFC,SAASC,KAAKC,YAAcJ,EAAaK,MACvCC,EAAcN,EAAaO,KAE3BC,EAAcC,KAAKC,IAAIT,EAAcK,GAC3C3C,EAAiB6C,EACrB,GAMJ,OAJAV,IAEAd,OAAOG,iBAAiB,SAAUW,GAE3B,KACHd,OAAOI,oBAAoB,SAAUU,EAAc,CACtD,GACF,IAEHpB,EAAAA,WAAU,WACFtB,IACkC,QAAlCuD,EAAA3D,EAAakB,QAAQN,UAAa,IAAA+C,GAAAA,EAAEC,QACxC,GACD,CAACxD,EAAoBQ,IAMxB,MAAMkB,EAA+B,KAIjC,IAAKoB,SAASW,eAAeC,GAAgB,CACzC,MAAMC,EAAoBb,SAASc,cAAc,SACjDD,EAAkBzE,GAAKwE,EAEvB,MAAMG,EAAgBf,SAASgB,gBAAgBd,YAEzCe,EADcnC,OAAOoC,WACUH,EAErCF,EAAkBM,UAAY,cACnCC,8DAEeH,iHAKfG,sEAKKpB,SAASC,KAAKoB,YAAYR,EAC9B,GAGEhC,EAAuByC,IACzB,MAAMC,EAA6BvB,SAASC,KAAKuB,UAAUC,SACvDL,GAGW,QAAXE,GAAqBC,EAEH,WAAXD,GAAuBC,GAC9BvB,SAASC,KAAKuB,UAAUE,OAAON,GAF/BpB,SAASC,KAAKuB,UAAUG,IAAIP,EAGhC,EA0BEQ,EAAuB,CACzBC,EACAC,KAIA,MAAMC,IAAEA,GAAQF,EAEJ,UAARE,GAA2B,MAARA,IACnBF,EAAEG,iBACFF,EAAYD,GAChB,EAkHJ,OACII,OAAAC,EAAAA,SAAA,CAAAC,SAAA,CACIC,EAAAA,IAAA,OAAA,CAAM5F,IAAKC,EAAe,cAAe,eACzCwF,EAAAA,YACIzF,IAAKI,EACLR,GAAIA,EAAE,cACOwB,EACbtB,UAAW+F,EAAAA,QACPC,EAAAA,WACAvF,GAAcwF,qBACdjG,GACH6F,SAAA,CAEDF,EAAAA,KAAA,MAAA,CACIzF,IAAKG,EACL6F,KAAK,SACLC,QAhKa,KACzBtF,GAAuBuF,IAAUA,GAAK,EAgK1BC,UAhIgBd,IAC5B,MAAME,IAAEA,GAAQF,EAEJ,cAARE,GACAF,EAAEG,iBACG9E,GACDC,GAAsB,GAE1BQ,EAAgB,IACD,YAARoE,GACPF,EAAEG,iBACG9E,GACDC,GAAsB,GAE1BQ,EAAgBzB,EAAM0G,OAAS,IAChB,UAARb,GAA2B,MAARA,GAC1BF,EAAEG,iBACF7E,GAAsB,GACtBQ,EAAgB,KACD,QAARoE,GAEQ,WAARA,IADP5E,GAAsB,EAG1B,EAyG6C,cACpB,GAAGS,UAChBtB,UAAW+F,EAAAA,QACPQ,YACA3F,GAAsB4F,EAAAA,mCAEZ,OAAM,gBACL5F,EAAkB,gBAClBW,EACfkF,SAAU,EAACZ,SAAA,CAEXC,MAACY,EAAAA,WAAWC,OAAM,CAACC,OAAO,WAAUf,SAC/B7D,IAEL8D,EAAAA,IAACe,EAAAA,gBAAe,CACZ7G,UAAW+F,EAAAA,QACPe,gBACAlG,GAAsBmG,EAAAA,4BAIjCnG,GACGkF,EAAAA,IAAA,KAAA,CACI5F,IAAKK,EACLT,GAAIyB,EACJ2E,KAAK,OACLG,UAhIcd,UAC9B,MAAME,IAAEA,GAAQF,EAEhB,GAAY,cAARE,EAAqB,CACrBF,EAAEG,iBACF,MAAMsB,GAAa5F,EAAe,GAAKxB,EAAM0G,OAC7CjF,EAAgB2F,EACpB,MAAO,GAAY,YAARvB,EAAmB,CAC1BF,EAAEG,iBACF,MAAMuB,EACF7F,EAAe,EAAIA,EAAe,EAAIxB,EAAM0G,OAAS,EACzDjF,EAAgB4F,EACpB,KAAmB,QAARxB,EACP5E,GAAsB,GACP,WAAR4E,IACP5E,GAAsB,GACH,QAAnBsD,EAAA9D,EAAYqB,eAAO,IAAAyC,GAAAA,EAAEC,QACzB,EA+GmD,cACtB,GAAG9C,kBAChBtB,UAAWkH,EAAAA,YAAkBrB,SAE5BjG,EAAMuH,KAAI,CAACC,EAAMC,IA5GR,GAC1B7B,cACA8B,aACAF,OACAnH,aACAsH,YAEA,MAAMzH,GAAEA,EAAEmC,MAAEA,GAAUmF,EAEtB,OAAInH,EAEI6F,YACIhG,GAAIA,EAEJoG,KAAK,WACLC,QAASX,EACTa,UAAYd,GAAMD,EAAqBC,EAAGC,oBAC5B8B,QAAoBE,EAClCf,UAAU,EACVvG,IAAMuH,IACFjH,EAAakB,QAAQ6F,GAASE,CAAE,EACnC5B,SAEA5F,EAAWmH,EAAM,CACdM,SAAUJ,EACVK,SAAUlH,KAZT8G,GAmBb5B,EAAAA,KAAA,KAAA,CACI7F,GAAIA,EAEJoG,KAAK,WACLlG,UAAW+F,EAAAA,QACP6B,EAAAA,QACAN,GAAc7G,GAAcoH,EAAAA,iBAEhC1B,QAASX,EACTa,UAAYd,GAAMD,EAAqBC,EAAGC,GAAY,iBACxC8B,QAAoBE,EAClCf,UAAU,EACVvG,IAAMuH,IACFjH,EAAakB,QAAQ6F,GAASE,CAAmB,EACpD5B,SAAA,CAEAyB,GAAcxB,EAAAA,IAACgC,WAAQ,CAAC9H,UAAW+H,EAAAA,WACpCjC,MAAA,MAAA,CACI9F,UAAW+F,EAAAA,QACPiC,eACAV,GAAcW,EAAAA,sBACjBpC,SAEA5D,MArBAsF,EAuBJ,EAoDWW,CAAsB,CAClB1C,YAAcD,GAzLf,EACvBA,EACA6B,EACAG,KAEI5H,GACAA,EAAgB4F,EAAG6B,EAAMG,GAE7B1G,GAAsB,EAAM,EAkLAsH,CAAmB5C,EAAG6B,EAAMC,GAChCC,WAAYD,IAAMxH,EAClBuH,OACAnH,aACAsH,MAAOF,QAKtBzG,GAAsBH,GACnBqF,EAAAA,IAAA,MAAA,CACI9F,UAAWoI,EAAAA,SACXjC,QA1MU,KAC1BtF,GAAsB,EAAM,SA6MzB,IAqBLyD,EAAgB,0CAChBQ,EAA0B"}
|
|
1
|
+
{"version":3,"file":"local-nav-dropdown.js","sources":["../../../../src/local-nav/local-nav-dropdown/local-nav-dropdown.tsx"],"sourcesContent":["import { ChevronDownIcon } from \"@lifesg/react-icons/chevron-down\";\nimport { TickIcon } from \"@lifesg/react-icons/tick\";\nimport clsx from \"clsx\";\nimport React, { useEffect, useImperativeHandle, useRef, useState } from \"react\";\n\nimport { useApplyStyle } from \"../../theme\";\nimport { Typography } from \"../../typography\";\nimport { useId } from \"../../util\";\nimport type { LocalNavDropdownItemComponentProps } from \"../internal-types\";\nimport type { LocalNavDropdownProps, LocalNavItemProps } from \"../types\";\nimport * as styles from \"./local-nav-dropdown.styles\";\n\nconst Component = (\n {\n defaultLabel,\n stickyOffset = 0,\n onNavItemSelect,\n items,\n selectedItemIndex,\n id,\n \"data-testid\": testId,\n className,\n renderItem,\n }: LocalNavDropdownProps,\n ref: React.Ref<HTMLElement>\n): JSX.Element => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const detectStickyRef = useRef<HTMLSpanElement>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n const navWrapperRef = useRef<HTMLElement>(null);\n const navItemListRef = useRef<HTMLUListElement>(null);\n const listItemRefs = useRef<(HTMLLIElement | null)[]>([]);\n const [isStickied, setIsStickied] = useState<boolean>(false);\n const [isDropdownExpanded, setIsDropdownExpanded] =\n useState<boolean>(false);\n const [viewportHeight, setViewportHeight] = useState(0);\n const [dropdowntHeight, setDropdownHeight] = useState(0);\n const [dynamicMargin, setDynamicMargin] = useState(0);\n const [focusedIndex, setFocusedIndex] = useState(0);\n const navTestId = testId || \"local-nav-dropdown\";\n const dropdownListId = useId();\n\n useImperativeHandle(ref, () => navWrapperRef.current!);\n\n useApplyStyle(navWrapperRef, {\n [styles.tokens.navWrapper.stickyOffset]: `${stickyOffset}px`,\n [styles.tokens.navWrapper.sideMargin]: `${dynamicMargin}px`,\n });\n\n useApplyStyle(navItemListRef, {\n [styles.tokens.navItemList.viewportHeight]: `${\n viewportHeight - dropdowntHeight - stickyOffset\n }px`,\n });\n\n const labelText =\n typeof selectedItemIndex === \"number\" &&\n selectedItemIndex >= 0 &&\n isStickied\n ? items[selectedItemIndex].title\n : defaultLabel;\n\n // =============================================================================\n // EFFECTS, EVENT LISTENERS\n // ============================================================================\n\n useEffect(() => {\n if (dropdownRef.current) {\n const dropdownHeight =\n dropdownRef.current.getBoundingClientRect().height;\n setDropdownHeight(dropdownHeight);\n }\n }, []);\n\n useEffect(() => {\n addStylesheetForDocumentBody();\n return () => {\n applyBodyStyleClass(\"remove\");\n };\n }, []);\n\n useEffect(() => {\n if (isDropdownExpanded && isStickied) {\n applyBodyStyleClass(\"add\");\n } else {\n applyBodyStyleClass(\"remove\");\n }\n }, [isDropdownExpanded, isStickied]);\n\n useEffect(() => {\n setViewportHeight(window.innerHeight);\n const handleResize = () => {\n setViewportHeight(window.innerHeight);\n };\n window.addEventListener(\"resize\", handleResize);\n return () => window.removeEventListener(\"resize\", handleResize);\n }, []);\n\n useEffect(() => {\n const callback = (entries: IntersectionObserverEntry[]) => {\n const [entry] = entries;\n setIsStickied(!entry.isIntersecting);\n };\n\n const observer = new IntersectionObserver(callback, {\n threshold: 1,\n rootMargin: `-${stickyOffset}px 0px 0px 0px`,\n });\n\n if (detectStickyRef.current) {\n observer.observe(detectStickyRef.current);\n }\n\n return () => observer.disconnect();\n }, [stickyOffset]);\n\n useEffect(() => {\n const adjustPadding = () => {\n const dropdown = navWrapperRef?.current;\n if (dropdown) {\n const dropdownRect = dropdown.getBoundingClientRect();\n const spaceToRight =\n document.body.clientWidth - dropdownRect.right;\n const spaceToLeft = dropdownRect.left;\n // Calculate the padding needed to balance the dropdown in the viewport\n const sidePadding = Math.max(spaceToRight, spaceToLeft);\n setDynamicMargin(sidePadding);\n }\n };\n adjustPadding();\n\n window.addEventListener(\"resize\", adjustPadding);\n\n return () => {\n window.removeEventListener(\"resize\", adjustPadding);\n };\n }, []);\n\n useEffect(() => {\n if (isDropdownExpanded) {\n listItemRefs.current[focusedIndex]?.focus();\n }\n }, [isDropdownExpanded, focusedIndex]);\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n\n const addStylesheetForDocumentBody = () => {\n /**\n * This stylesheet is to manipulate the <body>. We only add once\n */\n if (!document.getElementById(STYLESHEET_ID)) {\n const overlayStyleSheet = document.createElement(\"style\");\n overlayStyleSheet.id = STYLESHEET_ID;\n\n const documentWidth = document.documentElement.clientWidth;\n const windowWidth = window.innerWidth;\n const scrollBarWidth = windowWidth - documentWidth;\n\n overlayStyleSheet.innerHTML = `\n\t\t\t\t.${DROPDOWN_OPEN_CLASSNAME} {\n\t\t\t\t\toverflow: hidden;\n\t\t\t\t\tpadding-right: ${scrollBarWidth}px !important;\n\t\t\t\t\t-ms-overflow-style: none;\n\t\t\t\t\tscrollbar-width: none;\n\t\t\t\t}\n\n\t\t\t\t.${DROPDOWN_OPEN_CLASSNAME}::-webkit-scrollbar {\n\t\t\t\t\tdisplay: none;\n\t\t\t\t}\n\t\t\t`;\n\n document.body.appendChild(overlayStyleSheet);\n }\n };\n\n const applyBodyStyleClass = (action: \"add\" | \"remove\") => {\n const isOverlayStyleClassApplied = document.body.classList.contains(\n DROPDOWN_OPEN_CLASSNAME\n );\n\n if (action === \"add\" && !isOverlayStyleClassApplied) {\n document.body.classList.add(DROPDOWN_OPEN_CLASSNAME);\n } else if (action === \"remove\" && isOverlayStyleClassApplied) {\n document.body.classList.remove(DROPDOWN_OPEN_CLASSNAME);\n }\n };\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n\n const handleToggleDropdown = () => {\n setIsDropdownExpanded((prev) => !prev);\n };\n\n const handleDismissBackdrop = () => {\n setIsDropdownExpanded(false);\n };\n\n const handleNavItemClick = (\n e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>,\n item: LocalNavItemProps,\n index: number\n ) => {\n if (onNavItemSelect) {\n onNavItemSelect(e, item, index);\n }\n setIsDropdownExpanded(false);\n };\n\n const handleNavItemKeyDown = (\n e: React.KeyboardEvent<HTMLElement>,\n handleClick: (\n e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>\n ) => void\n ) => {\n const { key } = e;\n\n if (key === \"Enter\" || key === \" \") {\n e.preventDefault();\n handleClick(e);\n }\n };\n\n const handleNavSelectKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n const { key } = e;\n\n if (key === \"ArrowDown\") {\n e.preventDefault();\n if (!isDropdownExpanded) {\n setIsDropdownExpanded(true);\n }\n setFocusedIndex(0);\n } else if (key === \"ArrowUp\") {\n e.preventDefault();\n if (!isDropdownExpanded) {\n setIsDropdownExpanded(true);\n }\n setFocusedIndex(items.length - 1);\n } else if (key === \"Enter\" || key === \" \") {\n e.preventDefault();\n setIsDropdownExpanded(true);\n setFocusedIndex(0);\n } else if (key === \"Tab\") {\n setIsDropdownExpanded(false);\n } else if (key === \"Escape\") {\n setIsDropdownExpanded(false);\n }\n };\n\n const handleNavItemListKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n const { key } = e;\n\n if (key === \"ArrowDown\") {\n e.preventDefault();\n const nextIndex = (focusedIndex + 1) % items.length;\n setFocusedIndex(nextIndex);\n } else if (key === \"ArrowUp\") {\n e.preventDefault();\n const prevIndex =\n focusedIndex > 0 ? focusedIndex - 1 : items.length - 1;\n setFocusedIndex(prevIndex);\n } else if (key === \"Tab\") {\n setIsDropdownExpanded(false);\n } else if (key === \"Escape\") {\n setIsDropdownExpanded(false);\n dropdownRef.current?.focus();\n }\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n\n const renderDropdownNavItem = ({\n handleClick,\n isSelected,\n item,\n renderItem,\n index,\n }: LocalNavDropdownItemComponentProps) => {\n const { id, title, titleAddon } = item;\n\n if (renderItem) {\n return (\n <li\n id={id}\n key={index}\n role=\"menuitem\"\n onClick={handleClick}\n onKeyDown={(e) => handleNavItemKeyDown(e, handleClick)}\n aria-current={isSelected ? true : undefined}\n tabIndex={-1}\n ref={(el) => {\n listItemRefs.current[index] = el;\n }}\n >\n {renderItem(item, {\n selected: isSelected,\n stickied: isStickied,\n })}\n </li>\n );\n }\n\n return (\n <li\n id={id}\n key={index}\n role=\"menuitem\"\n className={clsx(\n styles.navItem,\n isSelected && isStickied && styles.navItemSelected\n )}\n onClick={handleClick}\n onKeyDown={(e) => handleNavItemKeyDown(e, handleClick)}\n aria-current={isSelected ? true : undefined}\n tabIndex={-1}\n ref={(el) => {\n listItemRefs.current[index] = el as HTMLLIElement;\n }}\n >\n {isSelected && (\n <span className={styles.leftAddon}>\n <TickIcon className={styles.tickIcon} />\n </span>\n )}\n {titleAddon ? (\n <span className={styles.titleContainer}>\n {titleAddon.left && (\n <span className={styles.leftAddon}>\n {titleAddon.left}\n </span>\n )}\n <div\n className={clsx(\n styles.navItemLabel,\n isSelected && styles.navItemLabelSelected\n )}\n >\n {title}\n </div>\n {titleAddon.right && (\n <span className={styles.rightAddon}>\n {titleAddon.right}\n </span>\n )}\n </span>\n ) : (\n <div\n className={clsx(\n styles.navItemLabel,\n isSelected && styles.navItemLabelSelected\n )}\n >\n {title}\n </div>\n )}\n </li>\n );\n };\n\n return (\n <>\n <span ref={detectStickyRef} data-testid={\"sticky-ref\"} />\n <nav\n ref={navWrapperRef}\n id={id}\n data-testid={navTestId}\n className={clsx(\n styles.navWrapper,\n isStickied && styles.navWrapperStickied,\n className\n )}\n >\n <div\n ref={dropdownRef}\n role=\"button\"\n onClick={handleToggleDropdown}\n onKeyDown={handleNavSelectKeyDown}\n data-testid={`${navTestId}-label`}\n className={clsx(\n styles.navSelect,\n isDropdownExpanded && styles.navSelectExpanded\n )}\n aria-haspopup=\"true\"\n aria-expanded={isDropdownExpanded}\n aria-controls={dropdownListId}\n tabIndex={0}\n >\n <Typography.BodyBL weight=\"semibold\">\n {labelText}\n </Typography.BodyBL>\n <ChevronDownIcon\n className={clsx(\n styles.navSelectIcon,\n isDropdownExpanded && styles.navSelectIconExpanded\n )}\n />\n </div>\n {isDropdownExpanded && (\n <ul\n ref={navItemListRef}\n id={dropdownListId}\n role=\"menu\"\n onKeyDown={handleNavItemListKeyDown}\n data-testid={`${navTestId}-dropdown-list`}\n className={styles.navItemList}\n >\n {items.map((item, i) =>\n renderDropdownNavItem({\n handleClick: (e) =>\n handleNavItemClick(e, item, i),\n isSelected: i === selectedItemIndex,\n item,\n renderItem,\n index: i,\n })\n )}\n </ul>\n )}\n {isDropdownExpanded && isStickied && (\n <div\n className={styles.backdrop}\n onClick={handleDismissBackdrop}\n />\n )}\n </nav>\n </>\n );\n};\n// @catalog\n/**\n * A collapsible dropdown used for in-page navigation on mobile viewports.\n *\n * Use `LocalNavDropdown` when the page has multiple named sections and screen\n * width is insufficient for a persistent sidebar.\n *\n * @remarks\n * This component adopts a fundamentally different interaction model from\n * `LocalNavMenu`: it collapses into a single trigger button and uses a menu\n * overlay, making it suited for mobile while `LocalNavMenu` suits desktop.\n * @keywords in-page navigation, sections\n */\nexport const LocalNavDropdown = React.forwardRef(Component);\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\nconst STYLESHEET_ID = \"lifesg-ds-local-nav-dropdown-stylesheet\";\nconst DROPDOWN_OPEN_CLASSNAME = \"lifesg-ds-local-nav-dropdown-open\";\n"],"names":["LocalNavDropdown","React","forwardRef","defaultLabel","stickyOffset","onNavItemSelect","items","selectedItemIndex","id","testId","className","renderItem","ref","detectStickyRef","useRef","dropdownRef","navWrapperRef","navItemListRef","listItemRefs","isStickied","setIsStickied","useState","isDropdownExpanded","setIsDropdownExpanded","viewportHeight","setViewportHeight","dropdowntHeight","setDropdownHeight","dynamicMargin","setDynamicMargin","focusedIndex","setFocusedIndex","navTestId","dropdownListId","useId","useImperativeHandle","current","useApplyStyle","styles.tokens","navWrapper","sideMargin","navItemList","labelText","title","useEffect","dropdownHeight","getBoundingClientRect","height","addStylesheetForDocumentBody","applyBodyStyleClass","window","innerHeight","handleResize","addEventListener","removeEventListener","observer","IntersectionObserver","entries","entry","isIntersecting","threshold","rootMargin","observe","disconnect","adjustPadding","dropdown","dropdownRect","spaceToRight","document","body","clientWidth","right","spaceToLeft","left","sidePadding","Math","max","_a","focus","getElementById","STYLESHEET_ID","overlayStyleSheet","createElement","documentWidth","documentElement","scrollBarWidth","innerWidth","innerHTML","DROPDOWN_OPEN_CLASSNAME","appendChild","action","isOverlayStyleClassApplied","classList","contains","remove","add","handleNavItemKeyDown","e","handleClick","key","preventDefault","_jsxs","_Fragment","children","_jsx","clsx","styles.navWrapper","styles.navWrapperStickied","role","onClick","prev","onKeyDown","length","styles.navSelect","styles.navSelectExpanded","tabIndex","Typography","BodyBL","weight","ChevronDownIcon","styles.navSelectIcon","styles.navSelectIconExpanded","nextIndex","prevIndex","styles.navItemList","map","item","i","isSelected","index","titleAddon","undefined","el","selected","stickied","styles.navItem","styles.navItemSelected","styles.leftAddon","TickIcon","styles.tickIcon","styles.titleContainer","styles.navItemLabel","styles.navItemLabelSelected","styles.rightAddon","renderDropdownNavItem","handleNavItemClick","styles.backdrop"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";require("./local-nav-dropdown.
|
|
1
|
+
"use strict";require("./local-nav-dropdown.styles_kpel1m.css");exports.backdrop="b7u5vs",exports.leftAddon="lc4nyiy",exports.navItem="n1rgfmu8",exports.navItemLabel="neqsxqe",exports.navItemLabelSelected="ns92rya",exports.navItemList="ny6lx9v",exports.navItemSelected="n122w1r6",exports.navSelect="n1fsscye",exports.navSelectExpanded="n10li8ea",exports.navSelectIcon="nczumix",exports.navSelectIconExpanded="n1mayi9n",exports.navWrapper="nb4z8rf",exports.navWrapperStickied="n1y3g4t3",exports.rightAddon="rhuuy8a",exports.tickIcon="tp844yu",exports.titleContainer="t1lmzf88",exports.tokens={navWrapper:{stickyOffset:"--fds-internal-localNavDropdown-navWrapper-stickyOffset",sideMargin:"--fds-internal-localNavDropdown-navWrapper-sideMargin"},navItemList:{viewportHeight:"--fds-internal-localNavDropdown-navItemList-viewportHeight"}};
|
|
2
2
|
//# sourceMappingURL=local-nav-dropdown.styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-nav-dropdown.styles.js","sources":["../../../../src/local-nav/local-nav-dropdown/local-nav-dropdown.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Border, Colour, Font, Motion, Radius, Spacing } from \"../../theme\";\n\nexport const tokens = {\n navWrapper: {\n stickyOffset: \"--fds-internal-localNavDropdown-navWrapper-stickyOffset\",\n sideMargin: \"--fds-internal-localNavDropdown-navWrapper-sideMargin\",\n },\n navItemList: {\n viewportHeight:\n \"--fds-internal-localNavDropdown-navItemList-viewportHeight\",\n },\n};\n\n// -----------------------------------------------------------------------------\n// NAV SELECT\n// -----------------------------------------------------------------------------\n\nexport const navSelectIcon = css`\n color: ${Colour[\"icon\"]};\n transition: transform ${Motion[\"duration-250\"]} ${Motion[\"ease-default\"]};\n transform: rotate(0deg);\n`;\n\nexport const navSelectIconExpanded = css`\n transform: rotate(180deg);\n`;\n\nexport const navSelect = css`\n cursor: pointer;\n background: ${Colour[\"bg\"]};\n padding: ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-16\"]};\n overflow: hidden;\n box-shadow: 0 0 ${Border[\"width-010\"]} ${Border[\"width-010\"]}\n ${Colour[\"border\"]};\n border-radius: ${Radius[\"sm\"]};\n display: flex;\n justify-content: space-between;\n align-items: center;\n transition: all ${Motion[\"duration-250\"]} ${Motion[\"ease-default\"]};\n transition-property: background, border-radius, box-shadow, transform;\n\n &:focus-visible {\n outline: 2px solid ${Colour[\"focus-ring\"]};\n outline-offset: 2px;\n border-radius: ${Radius[\"sm\"]};\n }\n`;\n\nexport const navSelectExpanded = css`\n border-bottom-left-radius: ${Radius[\"none\"]};\n border-bottom-right-radius: ${Radius[\"none\"]};\n`;\n\n// -----------------------------------------------------------------------------\n// NAV ITEMS\n// -----------------------------------------------------------------------------\n\nexport const navItem = css`\n padding: ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-8\"]}\n ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-32\"]};\n background: ${Colour[\"bg\"]};\n /* Ensures that the tick mark is positioned relative to the selected item */\n position: relative;\n display: flex;\n /* Vertically align text and tick */\n align-items: center;\n\n &:focus-visible {\n outline: 2px solid ${Colour[\"focus-ring\"]};\n outline-offset: 0px;\n border-radius: ${Radius[\"sm\"]};\n }\n`;\n\nexport const navItemSelected = css`\n padding: ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-8\"]}\n ${Spacing[\"spacing-12\"]} 0;\n background: ${Colour[\"bg-primary-subtlest\"]};\n`;\n\nexport const navItemList = css`\n ${tokens.navItemList.viewportHeight}: initial;\n transition: all ${Motion[\"duration-250\"]} ${Motion[\"ease-default\"]};\n transform-origin: top;\n list-style-type: none;\n padding: 0 ${Spacing[\"spacing-8\"]};\n margin: 0;\n background: ${Colour[\"bg\"]};\n cursor: pointer;\n box-shadow: 0 0 ${Border[\"width-010\"]} ${Border[\"width-010\"]}\n ${Colour[\"border\"]};\n border-bottom-right-radius: ${Radius[\"sm\"]};\n border-bottom-left-radius: ${Radius[\"sm\"]};\n /* Enables vertical scrolling */\n overflow-y: auto;\n /* Set a max height for the dropdown list */\n max-height: var(${tokens.navItemList.viewportHeight});\n`;\n\nexport const navItemLabel = css`\n ${Font[\"body-baseline-regular\"]}\n color: ${Colour[\"text\"]};\n`;\n\nexport const navItemLabelSelected = css`\n color: ${Colour[\"text-selected\"]};\n`;\n\nexport const tickIcon = css`\n color: ${Colour[\"icon-selected\"]};\n margin: 0 ${Spacing[\"spacing-8\"]};\n`;\n\n// -----------------------------------------------------------------------------\n// MAIN\n// -----------------------------------------------------------------------------\n\nexport const backdrop = css`\n position: fixed;\n top: 0;\n right: 0;\n left: 0;\n bottom: 0;\n background-color: ${Colour[\"overlay-strong\"]};\n z-index: -1;\n`;\n\nexport const navWrapper = css`\n ${tokens.navWrapper.stickyOffset}: initial;\n ${tokens.navWrapper.sideMargin}: initial;\n display: block;\n position: sticky;\n top: var(${tokens.navWrapper.stickyOffset});\n width: 100%;\n z-index: 10;\n`;\n\nexport const navWrapperStickied = css`\n .${navSelect} {\n margin: 0 calc(var(${tokens.navWrapper.sideMargin}, 0px) * -1);\n padding: ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-16\"]};\n border-radius: ${Radius[\"none\"]};\n }\n\n .${navItemList} {\n margin-left: calc(var(${tokens.navWrapper.sideMargin}, 0px) * -1);\n margin-right: calc(var(${tokens.navWrapper.sideMargin}, 0px) * -1);\n border-bottom-left-radius: ${Radius[\"sm\"]};\n border-bottom-right-radius: ${Radius[\"sm\"]};\n }\n`;\n"],"names":["navWrapper","stickyOffset","sideMargin","navItemList","viewportHeight"],"mappings":"
|
|
1
|
+
{"version":3,"file":"local-nav-dropdown.styles.js","sources":["../../../../src/local-nav/local-nav-dropdown/local-nav-dropdown.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Border, Colour, Font, Motion, Radius, Spacing } from \"../../theme\";\n\nexport const tokens = {\n navWrapper: {\n stickyOffset: \"--fds-internal-localNavDropdown-navWrapper-stickyOffset\",\n sideMargin: \"--fds-internal-localNavDropdown-navWrapper-sideMargin\",\n },\n navItemList: {\n viewportHeight:\n \"--fds-internal-localNavDropdown-navItemList-viewportHeight\",\n },\n};\n\n// -----------------------------------------------------------------------------\n// NAV SELECT\n// -----------------------------------------------------------------------------\n\nexport const navSelectIcon = css`\n color: ${Colour[\"icon\"]};\n transition: transform ${Motion[\"duration-250\"]} ${Motion[\"ease-default\"]};\n transform: rotate(0deg);\n`;\n\nexport const navSelectIconExpanded = css`\n transform: rotate(180deg);\n`;\n\nexport const navSelect = css`\n cursor: pointer;\n background: ${Colour[\"bg\"]};\n padding: ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-16\"]};\n overflow: hidden;\n box-shadow: 0 0 ${Border[\"width-010\"]} ${Border[\"width-010\"]}\n ${Colour[\"border\"]};\n border-radius: ${Radius[\"sm\"]};\n display: flex;\n justify-content: space-between;\n align-items: center;\n transition: all ${Motion[\"duration-250\"]} ${Motion[\"ease-default\"]};\n transition-property: background, border-radius, box-shadow, transform;\n\n &:focus-visible {\n outline: 2px solid ${Colour[\"focus-ring\"]};\n outline-offset: 2px;\n border-radius: ${Radius[\"sm\"]};\n }\n`;\n\nexport const navSelectExpanded = css`\n border-bottom-left-radius: ${Radius[\"none\"]};\n border-bottom-right-radius: ${Radius[\"none\"]};\n`;\n\n// -----------------------------------------------------------------------------\n// NAV ITEMS\n// -----------------------------------------------------------------------------\n\nexport const navItem = css`\n padding: ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-8\"]}\n ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-32\"]};\n background: ${Colour[\"bg\"]};\n /* Ensures that the tick mark is positioned relative to the selected item */\n position: relative;\n display: flex;\n /* Vertically align text and tick */\n align-items: center;\n\n &:focus-visible {\n outline: 2px solid ${Colour[\"focus-ring\"]};\n outline-offset: 0px;\n border-radius: ${Radius[\"sm\"]};\n }\n`;\n\nexport const navItemSelected = css`\n padding: ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-8\"]}\n ${Spacing[\"spacing-12\"]} 0;\n background: ${Colour[\"bg-primary-subtlest\"]};\n`;\n\nexport const navItemList = css`\n ${tokens.navItemList.viewportHeight}: initial;\n transition: all ${Motion[\"duration-250\"]} ${Motion[\"ease-default\"]};\n transform-origin: top;\n list-style-type: none;\n padding: 0 ${Spacing[\"spacing-8\"]};\n margin: 0;\n background: ${Colour[\"bg\"]};\n cursor: pointer;\n box-shadow: 0 0 ${Border[\"width-010\"]} ${Border[\"width-010\"]}\n ${Colour[\"border\"]};\n border-bottom-right-radius: ${Radius[\"sm\"]};\n border-bottom-left-radius: ${Radius[\"sm\"]};\n /* Enables vertical scrolling */\n overflow-y: auto;\n /* Set a max height for the dropdown list */\n max-height: var(${tokens.navItemList.viewportHeight});\n`;\n\nexport const titleContainer = css`\n display: flex;\n align-items: center;\n gap: ${Spacing[\"spacing-8\"]};\n flex: 1;\n`;\n\n/* Keeps the left addon aligned with the first line when the title wraps. */\nexport const leftAddon = css`\n display: inline-flex;\n align-items: center;\n align-self: flex-start;\n min-height: ${Font.Spec[\"body-lh-baseline\"]};\n`;\n\n/* Flushed right; stays vertically centred against the (possibly wrapped) title. */\nexport const rightAddon = css`\n display: inline-flex;\n align-items: center;\n margin-left: auto;\n`;\n\nexport const navItemLabel = css`\n ${Font[\"body-baseline-regular\"]}\n color: ${Colour[\"text\"]};\n`;\n\nexport const navItemLabelSelected = css`\n color: ${Colour[\"text-selected\"]};\n`;\n\nexport const tickIcon = css`\n color: ${Colour[\"icon-selected\"]};\n margin: 0 ${Spacing[\"spacing-8\"]};\n`;\n\n// -----------------------------------------------------------------------------\n// MAIN\n// -----------------------------------------------------------------------------\n\nexport const backdrop = css`\n position: fixed;\n top: 0;\n right: 0;\n left: 0;\n bottom: 0;\n background-color: ${Colour[\"overlay-strong\"]};\n z-index: -1;\n`;\n\nexport const navWrapper = css`\n ${tokens.navWrapper.stickyOffset}: initial;\n ${tokens.navWrapper.sideMargin}: initial;\n display: block;\n position: sticky;\n top: var(${tokens.navWrapper.stickyOffset});\n width: 100%;\n z-index: 10;\n`;\n\nexport const navWrapperStickied = css`\n .${navSelect} {\n margin: 0 calc(var(${tokens.navWrapper.sideMargin}, 0px) * -1);\n padding: ${Spacing[\"spacing-12\"]} ${Spacing[\"spacing-16\"]};\n border-radius: ${Radius[\"none\"]};\n }\n\n .${navItemList} {\n margin-left: calc(var(${tokens.navWrapper.sideMargin}, 0px) * -1);\n margin-right: calc(var(${tokens.navWrapper.sideMargin}, 0px) * -1);\n border-bottom-left-radius: ${Radius[\"sm\"]};\n border-bottom-right-radius: ${Radius[\"sm\"]};\n }\n`;\n"],"names":["navWrapper","stickyOffset","sideMargin","navItemList","viewportHeight"],"mappings":"4HA6IqB,2BAhCC,0BAlDF,gCAgEK,uCAKQ,8BA9CT,kCANI,6BA/CN,qCAqBQ,iCA/BJ,wCAMQ,8BA8HX,qCAUQ,8BA5CR,2BAeF,iCA/BM,0BAjGL,CAClBA,WAAY,CACRC,aAAc,0DACdC,WAAY,yDAEhBC,YAAa,CACTC,eACI"}
|
|
@@ -5,9 +5,12 @@
|
|
|
5
5
|
.n1rgfmu8{padding:var(--fds-spacing-12) var(--fds-spacing-8) var(--fds-spacing-12) var(--fds-spacing-32);background:var(--fds-colour-bg);position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.n1rgfmu8:focus-visible{outline:2px solid var(--fds-colour-focus-ring);outline-offset:0px;border-radius:var(--fds-radius-sm);}
|
|
6
6
|
.n122w1r6{padding:var(--fds-spacing-12) var(--fds-spacing-8) var(--fds-spacing-12) 0;background:var(--fds-colour-bg-primary-subtlest);}
|
|
7
7
|
.ny6lx9v{--fds-internal-localNavDropdown-navItemList-viewportHeight:initial;-webkit-transition:all var(--fds-motion-duration-250) var(--fds-motion-timing-ease-default);transition:all var(--fds-motion-duration-250) var(--fds-motion-timing-ease-default);transform-origin:top;list-style-type:none;padding:0 var(--fds-spacing-8);margin:0;background:var(--fds-colour-bg);cursor:pointer;box-shadow:0 0 var(--fds-border-width-010) var(--fds-border-width-010) var(--fds-colour-border);border-bottom-right-radius:var(--fds-radius-sm);border-bottom-left-radius:var(--fds-radius-sm);overflow-y:auto;max-height:var(--fds-internal-localNavDropdown-navItemList-viewportHeight);}
|
|
8
|
-
.
|
|
9
|
-
.
|
|
10
|
-
.
|
|
11
|
-
.
|
|
12
|
-
.ns92rya{
|
|
13
|
-
.
|
|
8
|
+
.t1lmzf88{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;gap:var(--fds-spacing-8);-webkit-flex:1;-ms-flex:1;flex:1;}
|
|
9
|
+
.lc4nyiy{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start;min-height:var(--fds-font-body-lh-baseline);}
|
|
10
|
+
.rhuuy8a{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin-left:auto;}
|
|
11
|
+
.neqsxqe{font-family:var(--fds-font-family-body);font-variant:var(--fds-font-variant);font-size:var(--fds-font-body-size-baseline);font-weight:var(--fds-font-weight-regular);line-height:var(--fds-font-body-lh-baseline);letter-spacing:var(--fds-font-body-ls-baseline);color:var(--fds-colour-text);}
|
|
12
|
+
.ns92rya{color:var(--fds-colour-text-selected);}
|
|
13
|
+
.tp844yu{color:var(--fds-colour-icon-selected);margin:0 var(--fds-spacing-8);}
|
|
14
|
+
.b7u5vs{position:fixed;top:0;right:0;left:0;bottom:0;background-color:var(--fds-colour-overlay-strong);z-index:-1;}
|
|
15
|
+
.nb4z8rf{--fds-internal-localNavDropdown-navWrapper-stickyOffset:initial;--fds-internal-localNavDropdown-navWrapper-sideMargin:initial;display:block;position:-webkit-sticky;position:sticky;top:var(--fds-internal-localNavDropdown-navWrapper-stickyOffset);width:100%;z-index:10;}
|
|
16
|
+
.n1y3g4t3 .n1fsscye{margin:0 calc(var(--fds-internal-localNavDropdown-navWrapper-sideMargin, 0px) * -1);padding:var(--fds-spacing-12) var(--fds-spacing-16);border-radius:var(--fds-radius-none);}.n1y3g4t3 .ny6lx9v{margin-left:calc(var(--fds-internal-localNavDropdown-navWrapper-sideMargin, 0px) * -1);margin-right:calc(var(--fds-internal-localNavDropdown-navWrapper-sideMargin, 0px) * -1);border-bottom-left-radius:var(--fds-radius-sm);border-bottom-right-radius:var(--fds-radius-sm);}}
|