@lifesg/react-design-system 4.0.0-alpha.11 → 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-download/file-download.js +1 -1
- package/cjs/file-download/file-download.js.map +1 -1
- package/cjs/file-download/file-list-card/file-list-card.js +1 -1
- package/cjs/file-download/file-list-card/file-list-card.js.map +1 -1
- package/cjs/file-download/file-list-card/file-list-card.styles.js +1 -1
- package/cjs/file-download/file-list-card/file-list-card.styles.js.map +1 -1
- package/cjs/file-download/file-list-card/file-list-card.styles_lzbqkk.css +18 -0
- 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/file-upload/helper.js +1 -1
- package/cjs/file-upload/helper.js.map +1 -1
- package/cjs/footer/footer-disclaimer-links-data.js +1 -1
- package/cjs/footer/footer-disclaimer-links-data.js.map +1 -1
- package/cjs/footer/footer.styles.js +1 -1
- package/cjs/footer/footer.styles.js.map +1 -1
- package/{footer/footer.styles_1msorhc.css → cjs/footer/footer.styles_14hnlcq.css} +4 -4
- package/cjs/fullscreen-image-carousel/fullscreen-image-carousel.js +1 -1
- package/cjs/fullscreen-image-carousel/fullscreen-image-carousel.js.map +1 -1
- package/cjs/index.js +1 -1
- 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/masthead/sgds-day.css +0 -1
- package/cjs/masthead/sgds-night.css +0 -1
- 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/navbar/navbar-logo-data.js +1 -1
- package/cjs/navbar/navbar-logo-data.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/index.js +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/cjs/theme/types.js +1 -1
- package/cjs/theme/types.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-download/file-download.d.ts +1 -1
- package/file-download/file-download.js +1 -1
- package/file-download/file-download.js.map +1 -1
- package/file-download/file-list-card/file-list-card.d.ts +1 -1
- package/file-download/file-list-card/file-list-card.js +1 -1
- package/file-download/file-list-card/file-list-card.js.map +1 -1
- package/file-download/file-list-card/file-list-card.styles.d.ts +2 -0
- package/file-download/file-list-card/file-list-card.styles.js +1 -1
- package/file-download/file-list-card/file-list-card.styles.js.map +1 -1
- package/file-download/file-list-card/file-list-card.styles_lzbqkk.css +18 -0
- package/file-download/file-list-card/types.d.ts +1 -0
- package/file-download/types.d.ts +13 -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/file-upload/helper.d.ts +30 -0
- package/file-upload/helper.js +1 -1
- package/file-upload/helper.js.map +1 -1
- package/footer/footer-disclaimer-links-data.js +1 -1
- package/footer/footer-disclaimer-links-data.js.map +1 -1
- package/footer/footer.styles.js +1 -1
- package/footer/footer.styles.js.map +1 -1
- package/{cjs/footer/footer.styles_1msorhc.css → footer/footer.styles_14hnlcq.css} +4 -4
- package/fullscreen-image-carousel/fullscreen-image-carousel.d.ts +1 -1
- package/fullscreen-image-carousel/fullscreen-image-carousel.js +1 -1
- package/fullscreen-image-carousel/fullscreen-image-carousel.js.map +1 -1
- package/fullscreen-image-carousel/types.d.ts +37 -0
- package/index.js +1 -1
- 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/masthead/sgds-day.css +0 -1
- package/masthead/sgds-night.css +0 -1
- 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/navbar-logo-data.js +1 -1
- package/navbar/navbar-logo-data.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/index.js +1 -1
- 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 +791 -0
- 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/theme-provider/preset.d.ts +2 -0
- 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/theme/types.d.ts +9 -3
- package/theme/types.js +1 -1
- package/theme/types.js.map +1 -1
- package/breadcrumb/breadcrumb.styles_1nl4aua.css +0 -18
- package/cjs/breadcrumb/breadcrumb.styles_1nl4aua.css +0 -18
- package/cjs/file-download/file-list-card/file-list-card.styles_18j2gut.css +0 -16
- 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-download/file-list-card/file-list-card.styles_18j2gut.css +0 -16
- 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
|
@@ -1,12 +1,19 @@
|
|
|
1
|
+
import type { FormLabelProps } from "../../form/form-label/types";
|
|
1
2
|
import type { FileItemProps } from "../types";
|
|
3
|
+
export type FileItemMode = "display" | "edit" | "error";
|
|
2
4
|
export interface FileListItemProps {
|
|
3
5
|
fileItem: FileItemProps;
|
|
4
6
|
wrapperWidth: number;
|
|
5
|
-
/** If specified, the edit buttons will be rendered */
|
|
6
7
|
editable?: boolean | undefined;
|
|
7
|
-
/** If specified, drag handles will be rendered */
|
|
8
8
|
sortable?: boolean | undefined;
|
|
9
9
|
disabled?: boolean | undefined;
|
|
10
|
+
readOnly?: boolean | undefined;
|
|
11
|
+
descriptionLabel?: FormLabelProps | undefined;
|
|
12
|
+
fileDescriptionMaxLength?: number | undefined;
|
|
13
|
+
descriptionRequired?: boolean | undefined;
|
|
10
14
|
onDelete: () => void;
|
|
11
|
-
|
|
15
|
+
onSave?: ((description: string) => void) | undefined;
|
|
16
|
+
onCancel?: (() => void) | undefined;
|
|
17
|
+
onBlur?: ((value: string) => void) | undefined;
|
|
18
|
+
onModeChange?: ((mode: FileItemMode) => void) | undefined;
|
|
12
19
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useTruncatedName(name: string, wrapperWidth: number, truncateText: boolean, elementRef: React.RefObject<HTMLElement | null>): string | undefined;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{useState as r,useCallback as t,useEffect as e}from"react";import"../../util/calendar-helper.js";import"../../external/dayjs/dayjs.min.js";import"../../util/simple-id-generator.js";import{StringHelper as n}from"../../util/string-helper.js";import"@react-aria/live-announcer";function i(i,o,u,a){const[l,c]=r(),m=t((r=>{if(!u)return r;const t=(null==a?void 0:a.current)?a.current.getBoundingClientRect().width:0;return n.truncateOneLine(r,t,t/2,t/2/8,16)}),[u,a]);return e((()=>{c(m(i))}),[o,m,i]),l}export{i as useTruncatedName};
|
|
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":["useTruncatedName","name","wrapperWidth","truncateText","elementRef","formattedName","setFormattedName","useState","getTruncatedText","useCallback","value","widthOfElement","current","getBoundingClientRect","width","StringHelper","truncateOneLine","useEffect"],"mappings":"yRAIM,SAAUA,EACZC,EACAC,EACAC,EACAC,GAEA,MAAOC,EAAeC,GAAoBC,IAEpCC,EAAmBC,GACpBC,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,GAAU,KACNX,EAAiBE,EAAiBP,GAAM,GACzC,CAACC,EAAcM,EAAkBP,IAE7BI,CACX"}
|
package/file-upload/helper.d.ts
CHANGED
|
@@ -1,6 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a file's thumbnail slot should be rendered.
|
|
3
|
+
*
|
|
4
|
+
* - `image` — a thumbnail was supplied; render it at `src`
|
|
5
|
+
* - `pdf-icon` — a PDF with no thumbnail; render the PDF badge borderless
|
|
6
|
+
* - `none` — nothing to show; render no thumbnail slot at all
|
|
7
|
+
*/
|
|
8
|
+
export type FileThumbnailDisplay = {
|
|
9
|
+
type: "image";
|
|
10
|
+
src: string;
|
|
11
|
+
} | {
|
|
12
|
+
type: "pdf-icon";
|
|
13
|
+
} | {
|
|
14
|
+
type: "none";
|
|
15
|
+
};
|
|
1
16
|
export declare class FileUploadHelper {
|
|
2
17
|
static readonly PDF_MIME_TYPE = "application/pdf";
|
|
3
18
|
static readonly PDF_ICON_URL = "https://assets.life.gov.sg/react-design-system/img/upload/pdf.svg";
|
|
4
19
|
static formatFileSizeDisplay(size?: number): string;
|
|
5
20
|
static isSupportedImageType(type: string): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Decides how a file's thumbnail slot should render, given its MIME type
|
|
23
|
+
* and any thumbnail the consumer supplied.
|
|
24
|
+
*
|
|
25
|
+
* Lives on `FileUploadHelper` so `FileUpload` can adopt it later. Today
|
|
26
|
+
* only `FileDownload` calls it: `FileUpload` still decides this inline in
|
|
27
|
+
* `file-list-item-thumbnail.tsx`, and the two do NOT yet agree — for a
|
|
28
|
+
* non-PDF with no thumbnail this returns `"none"` while `FileUpload`
|
|
29
|
+
* renders an `<img>` with an empty `src`. Do not read this as an invariant
|
|
30
|
+
* the two components already share.
|
|
31
|
+
*
|
|
32
|
+
* Callers render the result with their own markup, because their thumbnails
|
|
33
|
+
* change size at different breakpoints.
|
|
34
|
+
*/
|
|
35
|
+
static resolveThumbnailDisplay(mimeType: string | undefined, thumbnailImageDataUrl: string | undefined): FileThumbnailDisplay;
|
|
6
36
|
}
|
package/file-upload/helper.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
class e{static formatFileSizeDisplay(e){if(!e||0===e)return"0 KB";const
|
|
1
|
+
class e{static formatFileSizeDisplay(e){if(!e||0===e)return"0 KB";const t=Math.floor(Math.log(e)/Math.log(1024));return`${Number(e/Math.pow(1024,t)).toFixed(0)} ${["B","KB","MB","GB","TB","PB","EB","ZB","YB"][t]}`}static isSupportedImageType(e){return["image/avif","image/gif","image/jpeg","image/png","image/svg+xml","image/webp"].includes(e)}static resolveThumbnailDisplay(t,i){return i?{type:"image",src:i}:t===e.PDF_MIME_TYPE?{type:"pdf-icon"}:{type:"none"}}}e.PDF_MIME_TYPE="application/pdf",e.PDF_ICON_URL="https://assets.life.gov.sg/react-design-system/img/upload/pdf.svg";export{e as FileUploadHelper};
|
|
2
2
|
//# sourceMappingURL=helper.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helper.js","sources":["../../src/file-upload/helper.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"helper.js","sources":["../../src/file-upload/helper.ts"],"sourcesContent":["/**\n * How a file's thumbnail slot should be rendered.\n *\n * - `image` — a thumbnail was supplied; render it at `src`\n * - `pdf-icon` — a PDF with no thumbnail; render the PDF badge borderless\n * - `none` — nothing to show; render no thumbnail slot at all\n */\nexport type FileThumbnailDisplay =\n | { type: \"image\"; src: string }\n | { type: \"pdf-icon\" }\n | { type: \"none\" };\n\nexport class FileUploadHelper {\n public static readonly PDF_MIME_TYPE = \"application/pdf\";\n public static readonly PDF_ICON_URL =\n \"https://assets.life.gov.sg/react-design-system/img/upload/pdf.svg\";\n\n // Adapted from https://stackoverflow.com/questions/15900485/correct-way-to-convert-size-in-size-to-kb-mb-gb-in-javascript\n public static formatFileSizeDisplay(size?: number) {\n if (!size || size === 0) return \"0 KB\";\n\n const sizes = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\n\n const index: number = Math.floor(Math.log(size) / Math.log(1024));\n\n const value = Number(size / Math.pow(1024, index)).toFixed(0);\n const measurement = sizes[index];\n\n return `${value} ${measurement}`;\n }\n\n public static isSupportedImageType(type: string): boolean {\n /** Currently only images supported by html <img> */\n const acceptedImageTypes = [\n \"image/avif\",\n \"image/gif\",\n \"image/jpeg\",\n \"image/png\",\n \"image/svg+xml\",\n \"image/webp\",\n ];\n\n return acceptedImageTypes.includes(type);\n }\n\n /**\n * Decides how a file's thumbnail slot should render, given its MIME type\n * and any thumbnail the consumer supplied.\n *\n * Lives on `FileUploadHelper` so `FileUpload` can adopt it later. Today\n * only `FileDownload` calls it: `FileUpload` still decides this inline in\n * `file-list-item-thumbnail.tsx`, and the two do NOT yet agree — for a\n * non-PDF with no thumbnail this returns `\"none\"` while `FileUpload`\n * renders an `<img>` with an empty `src`. Do not read this as an invariant\n * the two components already share.\n *\n * Callers render the result with their own markup, because their thumbnails\n * change size at different breakpoints.\n */\n public static resolveThumbnailDisplay(\n mimeType: string | undefined,\n thumbnailImageDataUrl: string | undefined\n ): FileThumbnailDisplay {\n if (thumbnailImageDataUrl) {\n return { type: \"image\", src: thumbnailImageDataUrl };\n }\n\n if (mimeType === FileUploadHelper.PDF_MIME_TYPE) {\n return { type: \"pdf-icon\" };\n }\n\n return { type: \"none\" };\n }\n}\n"],"names":["FileUploadHelper","formatFileSizeDisplay","size","index","Math","floor","log","Number","pow","toFixed","isSupportedImageType","type","includes","resolveThumbnailDisplay","mimeType","thumbnailImageDataUrl","src","PDF_MIME_TYPE","PDF_ICON_URL"],"mappings":"MAYaA,EAMF,4BAAOC,CAAsBC,GAChC,IAAKA,GAAiB,IAATA,EAAY,MAAO,OAEhC,MAEMC,EAAgBC,KAAKC,MAAMD,KAAKE,IAAIJ,GAAQE,KAAKE,IAAI,OAK3D,MAAO,GAHOC,OAAOL,EAAOE,KAAKI,IAAI,KAAML,IAAQM,QAAQ,MAJ7C,CAAC,IAAK,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,MAKpCN,IAG9B,CAEO,2BAAOO,CAAqBC,GAW/B,MAT2B,CACvB,aACA,YACA,aACA,YACA,gBACA,cAGsBC,SAASD,EACvC,CAgBO,8BAAOE,CACVC,EACAC,GAEA,OAAIA,EACO,CAAEJ,KAAM,QAASK,IAAKD,GAG7BD,IAAad,EAAiBiB,cACvB,CAAEN,KAAM,YAGZ,CAAEA,KAAM,OACnB,EA3DuBX,EAAAiB,cAAgB,kBAChBjB,EAAAkB,aACnB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e={privacy:{href:"https://www.life.gov.sg/privacy-statement",target:"_blank",rel:"noopener"},termsOfUse:{href:"https://www.life.gov.sg/terms-of-use",target:"_blank",rel:"noopener"},reportVulnerability:{href:"https://tech.gov.sg/report_vulnerability",target:"_blank",rel:"noopener",external:!0}},r={privacy:{href:"https://assets.life.gov.sg/bookingsg/BSG_Privacy_Policy.pdf",target:"_blank",rel:"noopener"},termsOfUse:{href:"https://assets.life.gov.sg/bookingsg/BSG_Terms_of_Use.pdf",target:"_blank",rel:"noopener"},reportVulnerability:{href:"https://tech.gov.sg/report_vulnerability",target:"_blank",rel:"noopener",external:!0}},t={privacy:{href:"https://www.imda.gov.sg/privacy-statement",target:"_blank",rel:"noopener"},termsOfUse:{href:"https://www.imda.gov.sg/terms-of-use",target:"_blank",rel:"noopener"},reportVulnerability:{href:"https://www.tech.gov.sg/report_vulnerability",target:"_blank",rel:"noopener",external:!0}},o={privacy:{href:"https://mylegacy.life.gov.sg/privacy-statement",target:"_blank",rel:"noopener"},termsOfUse:{href:"https://mylegacy.life.gov.sg/terms-of-use",target:"_blank",rel:"noopener"},reportVulnerability:{href:"https://tech.gov.sg/report_vulnerability",target:"_blank",rel:"noopener",external:!0}},n={privacy:{href:"https://www.police.gov.sg/Privacy-Statement",target:"_blank",rel:"noopener"},termsOfUse:{href:"https://www.police.gov.sg/Terms-of-Use",target:"_blank",rel:"noopener"},reportVulnerability:{href:"https://www.tech.gov.sg/report-vulnerability",target:"_blank",rel:"noopener",external:!0}},a={privacy:{href:"https://supportgowhere.life.gov.sg/privacy-statement.pdf",target:"_blank",rel:"noopener"},termsOfUse:{href:"https://supportgowhere.life.gov.sg/terms-of-use.pdf",target:"_blank",rel:"noopener"},reportVulnerability:{href:"https://www.tech.gov.sg/report_vulnerability",target:"_blank",rel:"noopener",external:!0}},
|
|
1
|
+
const e={privacy:{href:"https://www.life.gov.sg/privacy-statement",target:"_blank",rel:"noopener"},termsOfUse:{href:"https://www.life.gov.sg/terms-of-use",target:"_blank",rel:"noopener"},reportVulnerability:{href:"https://tech.gov.sg/report_vulnerability",target:"_blank",rel:"noopener",external:!0}},r={privacy:{href:"https://assets.life.gov.sg/bookingsg/BSG_Privacy_Policy.pdf",target:"_blank",rel:"noopener"},termsOfUse:{href:"https://assets.life.gov.sg/bookingsg/BSG_Terms_of_Use.pdf",target:"_blank",rel:"noopener"},reportVulnerability:{href:"https://tech.gov.sg/report_vulnerability",target:"_blank",rel:"noopener",external:!0}},t={privacy:{href:"https://www.imda.gov.sg/privacy-statement",target:"_blank",rel:"noopener"},termsOfUse:{href:"https://www.imda.gov.sg/terms-of-use",target:"_blank",rel:"noopener"},reportVulnerability:{href:"https://www.tech.gov.sg/report_vulnerability",target:"_blank",rel:"noopener",external:!0}},o={privacy:{href:"https://mylegacy.life.gov.sg/privacy-statement",target:"_blank",rel:"noopener"},termsOfUse:{href:"https://mylegacy.life.gov.sg/terms-of-use",target:"_blank",rel:"noopener"},reportVulnerability:{href:"https://tech.gov.sg/report_vulnerability",target:"_blank",rel:"noopener",external:!0}},n={privacy:{href:"https://www.police.gov.sg/Privacy-Statement",target:"_blank",rel:"noopener"},termsOfUse:{href:"https://www.police.gov.sg/Terms-of-Use",target:"_blank",rel:"noopener"},reportVulnerability:{href:"https://www.tech.gov.sg/report-vulnerability",target:"_blank",rel:"noopener",external:!0}},s={privacy:{href:"https://www.sportsingapore.gov.sg/privacy/",target:"_blank",rel:"noopener"},termsOfUse:{href:"https://www.sportsingapore.gov.sg/terms-of-use/",target:"_blank",rel:"noopener"},reportVulnerability:{href:"https://www.tech.gov.sg/report_vulnerability",target:"_blank",rel:"noopener",external:!0}},a={privacy:{href:"https://supportgowhere.life.gov.sg/privacy-statement.pdf",target:"_blank",rel:"noopener"},termsOfUse:{href:"https://supportgowhere.life.gov.sg/terms-of-use.pdf",target:"_blank",rel:"noopener"},reportVulnerability:{href:"https://www.tech.gov.sg/report_vulnerability",target:"_blank",rel:"noopener",external:!0}},l=l=>{switch(l){case"bookingsg":return r;case"imda":return t;case"mylegacy":return o;case"spf":return n;case"sportsg-orange":return s;case"supportgowhere":return a;default:return e}};export{l as getDefaultDisclaimerLinks};
|
|
2
2
|
//# sourceMappingURL=footer-disclaimer-links-data.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"footer-disclaimer-links-data.js","sources":["../../src/footer/footer-disclaimer-links-data.tsx"],"sourcesContent":["import type { ThemeType } from \"../theme/types\";\nimport type { InternalDisclaimerLinks } from \"./footer-helper\";\n\nconst BaseDisclaimerLinks: InternalDisclaimerLinks = {\n privacy: {\n href: \"https://www.life.gov.sg/privacy-statement\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n termsOfUse: {\n href: \"https://www.life.gov.sg/terms-of-use\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n reportVulnerability: {\n href: \"https://tech.gov.sg/report_vulnerability\",\n target: \"_blank\",\n rel: \"noopener\",\n external: true,\n },\n};\n\nconst BookingSgDisclaimerLinks: InternalDisclaimerLinks = {\n privacy: {\n href: \"https://assets.life.gov.sg/bookingsg/BSG_Privacy_Policy.pdf\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n termsOfUse: {\n href: \"https://assets.life.gov.sg/bookingsg/BSG_Terms_of_Use.pdf\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n reportVulnerability: {\n href: \"https://tech.gov.sg/report_vulnerability\",\n target: \"_blank\",\n rel: \"noopener\",\n external: true,\n },\n};\n\nconst IMDADisclaimerLinks: InternalDisclaimerLinks = {\n privacy: {\n href: \"https://www.imda.gov.sg/privacy-statement\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n termsOfUse: {\n href: \"https://www.imda.gov.sg/terms-of-use\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n reportVulnerability: {\n href: \"https://www.tech.gov.sg/report_vulnerability\",\n target: \"_blank\",\n rel: \"noopener\",\n external: true,\n },\n};\n\nconst MyLegacyDisclaimerLinks: InternalDisclaimerLinks = {\n privacy: {\n href: \"https://mylegacy.life.gov.sg/privacy-statement\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n termsOfUse: {\n href: \"https://mylegacy.life.gov.sg/terms-of-use\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n reportVulnerability: {\n href: \"https://tech.gov.sg/report_vulnerability\",\n target: \"_blank\",\n rel: \"noopener\",\n external: true,\n },\n};\n\nconst SPFDisclaimerLinks: InternalDisclaimerLinks = {\n privacy: {\n href: \"https://www.police.gov.sg/Privacy-Statement\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n termsOfUse: {\n href: \"https://www.police.gov.sg/Terms-of-Use\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n reportVulnerability: {\n href: \"https://www.tech.gov.sg/report-vulnerability\",\n target: \"_blank\",\n rel: \"noopener\",\n external: true,\n },\n};\n\nconst SupportGoWhereDisclaimerLinks: InternalDisclaimerLinks = {\n privacy: {\n href: \"https://supportgowhere.life.gov.sg/privacy-statement.pdf\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n termsOfUse: {\n href: \"https://supportgowhere.life.gov.sg/terms-of-use.pdf\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n reportVulnerability: {\n href: \"https://www.tech.gov.sg/report_vulnerability\",\n target: \"_blank\",\n rel: \"noopener\",\n external: true,\n },\n};\n\nexport const getDefaultDisclaimerLinks = (resourceScheme?: ThemeType) => {\n switch (resourceScheme) {\n case \"bookingsg\":\n return BookingSgDisclaimerLinks;\n case \"imda\":\n return IMDADisclaimerLinks;\n case \"mylegacy\":\n return MyLegacyDisclaimerLinks;\n case \"spf\":\n return SPFDisclaimerLinks;\n case \"supportgowhere\":\n return SupportGoWhereDisclaimerLinks;\n default:\n return BaseDisclaimerLinks;\n }\n};\n"],"names":["BaseDisclaimerLinks","privacy","href","target","rel","termsOfUse","reportVulnerability","external","BookingSgDisclaimerLinks","IMDADisclaimerLinks","MyLegacyDisclaimerLinks","SPFDisclaimerLinks","SupportGoWhereDisclaimerLinks","getDefaultDisclaimerLinks","resourceScheme"],"mappings":"AAGA,MAAMA,EAA+C,CACjDC,QAAS,CACLC,KAAM,4CACNC,OAAQ,SACRC,IAAK,YAETC,WAAY,CACRH,KAAM,uCACNC,OAAQ,SACRC,IAAK,YAETE,oBAAqB,CACjBJ,KAAM,2CACNC,OAAQ,SACRC,IAAK,WACLG,UAAU,IAIZC,EAAoD,CACtDP,QAAS,CACLC,KAAM,8DACNC,OAAQ,SACRC,IAAK,YAETC,WAAY,CACRH,KAAM,4DACNC,OAAQ,SACRC,IAAK,YAETE,oBAAqB,CACjBJ,KAAM,2CACNC,OAAQ,SACRC,IAAK,WACLG,UAAU,IAIZE,EAA+C,CACjDR,QAAS,CACLC,KAAM,4CACNC,OAAQ,SACRC,IAAK,YAETC,WAAY,CACRH,KAAM,uCACNC,OAAQ,SACRC,IAAK,YAETE,oBAAqB,CACjBJ,KAAM,+CACNC,OAAQ,SACRC,IAAK,WACLG,UAAU,IAIZG,EAAmD,CACrDT,QAAS,CACLC,KAAM,iDACNC,OAAQ,SACRC,IAAK,YAETC,WAAY,CACRH,KAAM,4CACNC,OAAQ,SACRC,IAAK,YAETE,oBAAqB,CACjBJ,KAAM,2CACNC,OAAQ,SACRC,IAAK,WACLG,UAAU,IAIZI,EAA8C,CAChDV,QAAS,CACLC,KAAM,8CACNC,OAAQ,SACRC,IAAK,YAETC,WAAY,CACRH,KAAM,yCACNC,OAAQ,SACRC,IAAK,YAETE,oBAAqB,CACjBJ,KAAM,+CACNC,OAAQ,SACRC,IAAK,WACLG,UAAU,IAIZK,EAAyD,
|
|
1
|
+
{"version":3,"file":"footer-disclaimer-links-data.js","sources":["../../src/footer/footer-disclaimer-links-data.tsx"],"sourcesContent":["import type { ThemeType } from \"../theme/types\";\nimport type { InternalDisclaimerLinks } from \"./footer-helper\";\n\nconst BaseDisclaimerLinks: InternalDisclaimerLinks = {\n privacy: {\n href: \"https://www.life.gov.sg/privacy-statement\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n termsOfUse: {\n href: \"https://www.life.gov.sg/terms-of-use\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n reportVulnerability: {\n href: \"https://tech.gov.sg/report_vulnerability\",\n target: \"_blank\",\n rel: \"noopener\",\n external: true,\n },\n};\n\nconst BookingSgDisclaimerLinks: InternalDisclaimerLinks = {\n privacy: {\n href: \"https://assets.life.gov.sg/bookingsg/BSG_Privacy_Policy.pdf\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n termsOfUse: {\n href: \"https://assets.life.gov.sg/bookingsg/BSG_Terms_of_Use.pdf\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n reportVulnerability: {\n href: \"https://tech.gov.sg/report_vulnerability\",\n target: \"_blank\",\n rel: \"noopener\",\n external: true,\n },\n};\n\nconst IMDADisclaimerLinks: InternalDisclaimerLinks = {\n privacy: {\n href: \"https://www.imda.gov.sg/privacy-statement\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n termsOfUse: {\n href: \"https://www.imda.gov.sg/terms-of-use\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n reportVulnerability: {\n href: \"https://www.tech.gov.sg/report_vulnerability\",\n target: \"_blank\",\n rel: \"noopener\",\n external: true,\n },\n};\n\nconst MyLegacyDisclaimerLinks: InternalDisclaimerLinks = {\n privacy: {\n href: \"https://mylegacy.life.gov.sg/privacy-statement\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n termsOfUse: {\n href: \"https://mylegacy.life.gov.sg/terms-of-use\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n reportVulnerability: {\n href: \"https://tech.gov.sg/report_vulnerability\",\n target: \"_blank\",\n rel: \"noopener\",\n external: true,\n },\n};\n\nconst SPFDisclaimerLinks: InternalDisclaimerLinks = {\n privacy: {\n href: \"https://www.police.gov.sg/Privacy-Statement\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n termsOfUse: {\n href: \"https://www.police.gov.sg/Terms-of-Use\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n reportVulnerability: {\n href: \"https://www.tech.gov.sg/report-vulnerability\",\n target: \"_blank\",\n rel: \"noopener\",\n external: true,\n },\n};\n\nconst SportSGOrangeWhereDisclaimerLinks: InternalDisclaimerLinks = {\n privacy: {\n href: \"https://www.sportsingapore.gov.sg/privacy/\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n termsOfUse: {\n href: \"https://www.sportsingapore.gov.sg/terms-of-use/\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n reportVulnerability: {\n href: \"https://www.tech.gov.sg/report_vulnerability\",\n target: \"_blank\",\n rel: \"noopener\",\n external: true,\n },\n};\n\nconst SupportGoWhereDisclaimerLinks: InternalDisclaimerLinks = {\n privacy: {\n href: \"https://supportgowhere.life.gov.sg/privacy-statement.pdf\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n termsOfUse: {\n href: \"https://supportgowhere.life.gov.sg/terms-of-use.pdf\",\n target: \"_blank\",\n rel: \"noopener\",\n },\n reportVulnerability: {\n href: \"https://www.tech.gov.sg/report_vulnerability\",\n target: \"_blank\",\n rel: \"noopener\",\n external: true,\n },\n};\n\nexport const getDefaultDisclaimerLinks = (resourceScheme?: ThemeType) => {\n switch (resourceScheme) {\n case \"bookingsg\":\n return BookingSgDisclaimerLinks;\n case \"imda\":\n return IMDADisclaimerLinks;\n case \"mylegacy\":\n return MyLegacyDisclaimerLinks;\n case \"spf\":\n return SPFDisclaimerLinks;\n case \"sportsg-orange\":\n return SportSGOrangeWhereDisclaimerLinks;\n case \"supportgowhere\":\n return SupportGoWhereDisclaimerLinks;\n default:\n return BaseDisclaimerLinks;\n }\n};\n"],"names":["BaseDisclaimerLinks","privacy","href","target","rel","termsOfUse","reportVulnerability","external","BookingSgDisclaimerLinks","IMDADisclaimerLinks","MyLegacyDisclaimerLinks","SPFDisclaimerLinks","SportSGOrangeWhereDisclaimerLinks","SupportGoWhereDisclaimerLinks","getDefaultDisclaimerLinks","resourceScheme"],"mappings":"AAGA,MAAMA,EAA+C,CACjDC,QAAS,CACLC,KAAM,4CACNC,OAAQ,SACRC,IAAK,YAETC,WAAY,CACRH,KAAM,uCACNC,OAAQ,SACRC,IAAK,YAETE,oBAAqB,CACjBJ,KAAM,2CACNC,OAAQ,SACRC,IAAK,WACLG,UAAU,IAIZC,EAAoD,CACtDP,QAAS,CACLC,KAAM,8DACNC,OAAQ,SACRC,IAAK,YAETC,WAAY,CACRH,KAAM,4DACNC,OAAQ,SACRC,IAAK,YAETE,oBAAqB,CACjBJ,KAAM,2CACNC,OAAQ,SACRC,IAAK,WACLG,UAAU,IAIZE,EAA+C,CACjDR,QAAS,CACLC,KAAM,4CACNC,OAAQ,SACRC,IAAK,YAETC,WAAY,CACRH,KAAM,uCACNC,OAAQ,SACRC,IAAK,YAETE,oBAAqB,CACjBJ,KAAM,+CACNC,OAAQ,SACRC,IAAK,WACLG,UAAU,IAIZG,EAAmD,CACrDT,QAAS,CACLC,KAAM,iDACNC,OAAQ,SACRC,IAAK,YAETC,WAAY,CACRH,KAAM,4CACNC,OAAQ,SACRC,IAAK,YAETE,oBAAqB,CACjBJ,KAAM,2CACNC,OAAQ,SACRC,IAAK,WACLG,UAAU,IAIZI,EAA8C,CAChDV,QAAS,CACLC,KAAM,8CACNC,OAAQ,SACRC,IAAK,YAETC,WAAY,CACRH,KAAM,yCACNC,OAAQ,SACRC,IAAK,YAETE,oBAAqB,CACjBJ,KAAM,+CACNC,OAAQ,SACRC,IAAK,WACLG,UAAU,IAIZK,EAA6D,CAC/DX,QAAS,CACLC,KAAM,6CACNC,OAAQ,SACRC,IAAK,YAETC,WAAY,CACRH,KAAM,kDACNC,OAAQ,SACRC,IAAK,YAETE,oBAAqB,CACjBJ,KAAM,+CACNC,OAAQ,SACRC,IAAK,WACLG,UAAU,IAIZM,EAAyD,CAC3DZ,QAAS,CACLC,KAAM,2DACNC,OAAQ,SACRC,IAAK,YAETC,WAAY,CACRH,KAAM,sDACNC,OAAQ,SACRC,IAAK,YAETE,oBAAqB,CACjBJ,KAAM,+CACNC,OAAQ,SACRC,IAAK,WACLG,UAAU,IAILO,EAA6BC,IACtC,OAAQA,GACJ,IAAK,YACD,OAAOP,EACX,IAAK,OACD,OAAOC,EACX,IAAK,WACD,OAAOC,EACX,IAAK,MACD,OAAOC,EACX,IAAK,iBACD,OAAOC,EACX,IAAK,iBACD,OAAOC,EACX,QACI,OAAOb"}
|
package/footer/footer.styles.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"./footer.
|
|
1
|
+
import"./footer.styles_14hnlcq.css";const l="b1ozupxm",s="f1b3ng0m",t="f1f7a2pi",o="t1nab4kr",e="l1t4stq",b="l14ev7f9",g={bookingsg:"b1rsy8ww",ccube:"csv4pll",lifesg:"l1m4savg",mylegacy:"m6zlk1a",supportgowhere:"sdqdit1"},c="l1guit5j",n="l1dnmj9w",p="a1r2lyba",r="b1ni5lnl",a="bakpusz",m="cb1d27e",f="cntgl6w",i="d2vgmpj";export{p as addonSection,l as baseFooter,r as bottomSection,a as bottomSectionContent,m as copyrightSection,f as copyrightText,i as disclaimerTextLink,s as footerLink,t as fullWidthDivider,n as linkSection,c as linkSectionWrapper,b as logoImage,e as logoSection,g as logoSize,o as topSection};
|
|
2
2
|
//# sourceMappingURL=footer.styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"footer.styles.js","sources":["../../src/footer/footer.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { ComponentToken, MediaQuery, Spacing } from \"../theme\";\nimport type { ThemeType } from \"../theme/types\";\n\n// =============================================================================\n// GENERIC\n// =============================================================================\n\nexport const baseFooter = css`\n background: ${ComponentToken.Footer[\"colour-bg\"]};\n`;\n\nexport const footerLink = css`\n color: ${ComponentToken.Footer[\"link-colour-text\"]};\n\n &:hover {\n color: ${ComponentToken.Footer[\"link-colour-text-hover\"]};\n }\n`;\n\n// =============================================================================\n// TOP SECTION\n// =============================================================================\n\nexport const fullWidthDivider = css`\n width: 100%;\n`;\n\nexport const topSection = css`\n padding: ${Spacing[\"spacing-64\"]} 0;\n\n ${MediaQuery.MaxWidth.lg} {\n padding: ${Spacing[\"spacing-32\"]} 0;\n\n [data-id=\"container\"] {\n flex-direction: column;\n gap: ${Spacing[\"spacing-32\"]};\n }\n }\n`;\n\nexport const logoSection = css`\n display: flex;\n width: fit-content;\n margin-right: ${Spacing[\"spacing-64\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n width: 100%;\n margin-right: 0;\n }\n`;\n\nexport const logoImage = css`\n max-height: 4rem;\n max-width: 100%;\n object-fit: contain;\n`;\n\nexport const logoSize: Partial<Record<ThemeType, string>> = {\n
|
|
1
|
+
{"version":3,"file":"footer.styles.js","sources":["../../src/footer/footer.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { ComponentToken, MediaQuery, Spacing } from \"../theme\";\nimport type { ThemeType } from \"../theme/types\";\n\n// =============================================================================\n// GENERIC\n// =============================================================================\n\nexport const baseFooter = css`\n background: ${ComponentToken.Footer[\"colour-bg\"]};\n`;\n\nexport const footerLink = css`\n color: ${ComponentToken.Footer[\"link-colour-text\"]};\n\n &:hover {\n color: ${ComponentToken.Footer[\"link-colour-text-hover\"]};\n }\n`;\n\n// =============================================================================\n// TOP SECTION\n// =============================================================================\n\nexport const fullWidthDivider = css`\n width: 100%;\n`;\n\nexport const topSection = css`\n padding: ${Spacing[\"spacing-64\"]} 0;\n\n ${MediaQuery.MaxWidth.lg} {\n padding: ${Spacing[\"spacing-32\"]} 0;\n\n [data-id=\"container\"] {\n flex-direction: column;\n gap: ${Spacing[\"spacing-32\"]};\n }\n }\n`;\n\nexport const logoSection = css`\n display: flex;\n width: fit-content;\n margin-right: ${Spacing[\"spacing-64\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n width: 100%;\n margin-right: 0;\n }\n`;\n\nexport const logoImage = css`\n max-height: 4rem;\n max-width: 100%;\n object-fit: contain;\n`;\n\nexport const logoSize: Partial<Record<ThemeType, string>> = {\n bookingsg: css`\n width: 4rem;\n `,\n ccube: css`\n width: 10rem;\n `,\n lifesg: css`\n width: 4rem;\n `,\n mylegacy: css`\n width: 10rem;\n max-height: 2rem;\n `,\n supportgowhere: css`\n width: 10rem;\n `,\n};\n\nexport const linkSectionWrapper = css`\n display: flex;\n gap: ${Spacing[\"spacing-32\"]};\n flex: 1 1 auto;\n max-width: calc(32% + ${Spacing[\"spacing-32\"]});\n\n ${MediaQuery.MaxWidth.lg} {\n max-width: 100%;\n }\n`;\n\nexport const linkSection = css`\n flex: 1 1 50%;\n list-style-type: none;\n\n &:nth-of-type(2) {\n // 2nd col\n grid-column: 7 / span 4;\n }\n\n li {\n &:not(:last-child) {\n margin-bottom: ${Spacing[\"spacing-8\"]};\n }\n\n a {\n display: inline-block;\n }\n }\n\n ${MediaQuery.MaxWidth.lg} {\n // first col\n grid-column: 1 / span 6;\n\n &:nth-of-type(2) {\n // 2nd col\n grid-column: 7 / span 6;\n }\n }\n\n ${MediaQuery.MaxWidth.md} {\n // first col\n grid-column: 1 / span 4;\n\n &:nth-of-type(2) {\n // 2nd col\n grid-column: 5 / span 4;\n }\n }\n`;\n\nexport const addonSection = css`\n flex: 0 1 33%;\n margin-left: auto;\n\n ${MediaQuery.MaxWidth.lg} {\n flex: 1 1 100%;\n margin-left: 0;\n }\n`;\n\n// =============================================================================\n// BOTTOM SECTION\n// =============================================================================\n\nexport const bottomSection = css`\n padding: ${Spacing[\"spacing-20\"]} 0;\n\n [data-id=\"container\"] {\n column-gap: ${Spacing[\"spacing-32\"]};\n }\n\n ${MediaQuery.MaxWidth.lg} {\n border-top: none;\n padding: ${Spacing[\"spacing-16\"]} 0;\n\n [data-id=\"container\"] {\n flex-direction: column;\n }\n }\n`;\n\nexport const bottomSectionContent = css`\n flex: 1 1 50%;\n display: flex;\n\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: column;\n gap: ${Spacing[\"spacing-8\"]};\n &:not(:last-child) {\n margin-right: 0;\n }\n }\n`;\n\nexport const copyrightSection = css`\n justify-content: flex-end;\n\n ${MediaQuery.MaxWidth.lg} {\n margin-top: ${Spacing[\"spacing-16\"]};\n justify-content: flex-start;\n }\n`;\n\nexport const copyrightText = css`\n color: ${ComponentToken.Footer[\"colour-text\"]};\n`;\n\nexport const disclaimerTextLink = css`\n color: ${ComponentToken.Footer[\"disclaimer-link-colour-text\"]};\n &:not(:last-child) {\n margin-right: ${Spacing[\"spacing-16\"]};\n }\n\n &:hover {\n color: ${ComponentToken.Footer[\"disclaimer-link-colour-text-hover\"]};\n }\n\n ${MediaQuery.MaxWidth.lg} {\n &:not(:last-child) {\n margin-right: 0;\n }\n }\n`;\n"],"names":["baseFooter","footerLink","fullWidthDivider","topSection","logoSection","logoImage","logoSize","bookingsg","ccube","lifesg","mylegacy","supportgowhere","linkSectionWrapper","linkSection","addonSection","bottomSection","bottomSectionContent","copyrightSection","copyrightText","disclaimerTextLink"],"mappings":"0DASO,MAAMA,EAAU,WAIVC,EAAU,WAYVC,EAAgB,WAIhBC,EAAU,WAaVC,EAAW,UAWXC,EAAS,WAMTC,EAA+C,CACxDC,UAAS,WAGTC,MAAK,UAGLC,OAAM,WAGNC,SAAQ,UAIRC,eAAc,WAKLC,EAAkB,WAWlBC,EAAW,WAwCXC,EAAY,WAcZC,EAAa,WAiBbC,EAAoB,UAapBC,EAAgB,UAShBC,EAAa,UAIbC,EAAkB"}
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
.t1nab4kr{padding:var(--fds-spacing-64) 0;}:where(body.fds-breakpoint-lg-max) .t1nab4kr{padding:var(--fds-spacing-32) 0;}:where(body.fds-breakpoint-lg-max) .t1nab4kr [data-id="container"]{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;gap:var(--fds-spacing-32);}
|
|
5
5
|
.l1t4stq{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;margin-right:var(--fds-spacing-64);}:where(body.fds-breakpoint-lg-max) .l1t4stq{width:100%;margin-right:0;}
|
|
6
6
|
.l14ev7f9{max-height:4rem;max-width:100%;object-fit:contain;}
|
|
7
|
-
.
|
|
8
|
-
.
|
|
9
|
-
.
|
|
10
|
-
.
|
|
7
|
+
.b1rsy8ww{width:4rem;}
|
|
8
|
+
.csv4pll{width:10rem;}
|
|
9
|
+
.l1m4savg{width:4rem;}
|
|
10
|
+
.m6zlk1a{width:10rem;max-height:2rem;}
|
|
11
11
|
.sdqdit1{width:10rem;}
|
|
12
12
|
.l1guit5j{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;gap:var(--fds-spacing-32);-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;max-width:calc(32% + var(--fds-spacing-32));}:where(body.fds-breakpoint-lg-max) .l1guit5j{max-width:100%;}
|
|
13
13
|
.l1dnmj9w{-webkit-flex:1 1 50%;-ms-flex:1 1 50%;flex:1 1 50%;list-style-type:none;}.l1dnmj9w:nth-of-type(2){-ms-grid-column:7;-ms-grid-column-span:4;grid-column:7/span 4;}.l1dnmj9w li:not(:last-child){margin-bottom:var(--fds-spacing-8);}.l1dnmj9w li a{display:inline-block;}:where(body.fds-breakpoint-lg-max) .l1dnmj9w{-ms-grid-column:1;-ms-grid-column-span:6;grid-column:1/span 6;}:where(body.fds-breakpoint-lg-max) .l1dnmj9w:nth-of-type(2){-ms-grid-column:7;-ms-grid-column-span:6;grid-column:7/span 6;}:where(body.fds-breakpoint-md-max) .l1dnmj9w{-ms-grid-column:1;-ms-grid-column-span:4;grid-column:1/span 4;}:where(body.fds-breakpoint-md-max) .l1dnmj9w:nth-of-type(2){-ms-grid-column:5;-ms-grid-column-span:4;grid-column:5/span 4;}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { FullscreenImageCarouselProps, FullscreenImageCarouselRef } from "./types";
|
|
2
|
-
export declare const Component: ({ items, initialActiveItemIndex, hideThumbnail, hideNavigation, hideCounter, hideMagnifier, onDelete, onClose, insets, show, ...otherProps }: FullscreenImageCarouselProps, ref: React.Ref<FullscreenImageCarouselRef>) => import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export declare const Component: ({ items, initialActiveItemIndex, hideThumbnail, hideNavigation, hideCounter, hideMagnifier, customActions, onDelete, onClose, insets, topBarRef, show, ...otherProps }: FullscreenImageCarouselProps, ref: React.Ref<FullscreenImageCarouselRef>) => import("react/jsx-runtime").JSX.Element;
|
|
3
3
|
/**
|
|
4
4
|
* A fullscreen modal carousel for browsing images and custom media items.
|
|
5
5
|
*
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{__rest as e}from"../_virtual/_tslib.js";import{jsx as i,jsxs as t,Fragment as l}from"react/jsx-runtime";import{ChevronLeftIcon as r,ChevronRightIcon as o,MagnifierPlusIcon as a,MagnifierMinusIcon as n,CrossIcon as s}from"@lifesg/react-icons";import{BinIcon as d}from"@lifesg/react-icons/bin";import{clearAnnouncer as c,announce as m}from"@react-aria/live-announcer";import u from"clsx";import{forwardRef as h,useState as v,useRef as p,useMemo as f,useCallback as g,useImperativeHandle as b,useEffect as N}from"react";import{TransformWrapper as
|
|
1
|
+
import{__rest as e}from"../_virtual/_tslib.js";import{jsx as i,jsxs as t,Fragment as l}from"react/jsx-runtime";import{ChevronLeftIcon as r,ChevronRightIcon as o,MagnifierPlusIcon as a,MagnifierMinusIcon as n,CrossIcon as s}from"@lifesg/react-icons";import{BinIcon as d}from"@lifesg/react-icons/bin";import{clearAnnouncer as c,announce as m}from"@react-aria/live-announcer";import u from"clsx";import{forwardRef as h,useState as v,useRef as p,useMemo as f,useCallback as g,useImperativeHandle as b,useEffect as N,cloneElement as j}from"react";import{TransformWrapper as k,TransformComponent as x}from"react-zoom-pan-pinch";import{ModalV2 as y}from"../modal-v2/modal-v2.js";import{ClickableIcon as C}from"../shared/clickable-icon/clickable-icon.js";import{useStateCallback as w}from"../shared/hooks/use-state-callback.js";import{ImagePlaceholder as I}from"../shared/image-placeholder/image-placeholder.js";import"../theme/theme-provider/index.js";import{formatUnitValue as T}from"../theme/utils/css-variable.js";import"../theme/theme-provider/context.js";import"../theme/tokens/border.js";import"../theme/tokens/colour.js";import"../theme/tokens/font.js";import"../theme/tokens/media-query.js";import{useApplyStyle as $}from"../theme/utils/use-apply-styles.js";import"../theme/utils/use-media-query.js";import{Typography as B}from"../typography/index.js";import"../util/calendar-helper.js";import"../external/dayjs/dayjs.min.js";import{mergeRefs as A}from"../util/merge-refs.js";import"../util/simple-id-generator.js";import"../util/string-helper.js";import{useEventListener as L}from"../util/use-event-listener.js";import{tokens as S,carouselModalContent as D,imageGalleryContainer as M,imageGalleryWrapper as R,imageGallerySwipe as z,iconButton as X,arrowButton as Z,arrowButtonLeft as O,arrowButtonRight as W,boxChip as q,chip as E,imageGallerySlides as P,imageGallerySlide as V,focusableImageRegion as _,slidePlaceholderImage as F,slideImage as H,thumbnailContainer as G,thumbnailWrapper as J,thumbnailItemContainer as K,thumbnailItem as Q,thumbnailImage as U,topActionButtons as Y,iconButtonError as ee,fileInfoFileName as ie,fileInfoFileSize as te,fileInfoTextWrapper as le,fileInfoTextWrapperCentered as re}from"./fullscreen-image-carousel.styles.js";import{StatefulImage as oe}from"./stateful-image.js";const ae=e=>!!e&&"custom"===e.type,ne=(h,ne)=>{var se,de,{items:ce,initialActiveItemIndex:me,hideThumbnail:ue=!1,hideNavigation:he=!1,hideCounter:ve=!1,hideMagnifier:pe=!1,customActions:fe,onDelete:ge,onClose:be,insets:Ne,topBarRef:je,show:ke}=h,xe=e(h,["items","initialActiveItemIndex","hideThumbnail","hideNavigation","hideCounter","hideMagnifier","customActions","onDelete","onClose","insets","topBarRef","show"]);const[ye,Ce]=w(null!=me?me:0),[we,Ie]=v({}),[Te,$e]=v(1),[Be,Ae]=v(),[Le,Se]=v(),De=p(null),Me=p([]),Re=p([]),ze=p(null),[Xe,Ze]=v(null),Oe=f((()=>({current:Xe})),[Xe]),We=f((()=>A(Ze,je)),[je]),qe=p(null),Ee=p(null),Pe=p(null),Ve=Be&&Le?Be-Le:0,_e=ce[ye],Fe=null!==(de=null!==(se=null==_e?void 0:_e.customActions)&&void 0!==se?se:fe)&&void 0!==de?de:[],He=ce.some((e=>{var i;return ae(e)&&!!(null===(i=e.itemLabel)||void 0===i?void 0:i.trim())})),Ge=He?"item":"image",Je=f((()=>ce.some((e=>{var i,t;return(null===(i=e.fileName)||void 0===i?void 0:i.trim())||(null===(t=e.fileSize)||void 0===t?void 0:t.trim())}))),[ce]);$(Oe,{[S.topActionButtons.insetTop]:T(null==Ne?void 0:Ne.top,"px"),[S.topActionButtons.insetLeft]:T(null==Ne?void 0:Ne.left,"px"),[S.topActionButtons.insetRight]:T(null==Ne?void 0:Ne.right,"px")}),$(qe,{[S.arrowButton.insetLeft]:T(null==Ne?void 0:Ne.left,"px")}),$(Ee,{[S.arrowButton.insetRight]:T(null==Ne?void 0:Ne.right,"px")}),$(Pe,{[S.thumbnailContainer.insetBottom]:T(null==Ne?void 0:Ne.bottom,"px")});const Ke=g((e=>{var i,t;const l=ce[e],r=He?"Item":"Image",o=ae(l)?(null===(i=l.itemLabel)||void 0===i?void 0:i.trim())||"":(null===(t=l.alt)||void 0===t?void 0:t.trim())||"",a=`${r} ${e+1} of ${ce.length}.`;return o?`${o}. ${a}`:a}),[ce,He]);b(ne,(()=>({currentItemIndex:ye,setCurrentItem:ri,goToPrevItem:ti,goToNextItem:li}))),L("keydown",(function(e){"ArrowRight"===e.key?li():"ArrowLeft"===e.key?ti():"Escape"===e.key&&(null==be||be())}),"document"),N((()=>{var e;ke&&(null===(e=ze.current)||void 0===e||e.focus())}),[ke]),N((()=>{0!==ce.length?ye>ce.length-1&&Ce(ce.length-1):Ce(0)}),[ye,ce.length,Ce]),N((()=>{var e,i;null===(i=null===(e=Me.current)||void 0===e?void 0:e[ye])||void 0===i||i.scrollIntoView({behavior:"smooth",inline:"center"}),$e(1)}),[ye]);const Qe=e=>{$e(e.state.scale)},Ue=()=>{_e&&ge&&ge(_e,ye)};const Ye=()=>{var e,i,t,l;if(1===Te){const t=ii();null===(i=null===(e=Re.current)||void 0===e?void 0:e[ye])||void 0===i||i.centerView(t),$e(null!=t?t:1)}else $e(1),null===(l=null===(t=Re.current)||void 0===t?void 0:t[ye])||void 0===l||l.resetTransform()},ei=({src:e,height:i,width:t})=>{Ie((l=>Object.assign(Object.assign({},l),{[e]:{height:i,width:t}})))},ii=()=>{if(!_e||ae(_e))return;const e=we[_e.src];if(De.current&&e){const{clientHeight:i,clientWidth:t}=De.current,{width:l,height:r}=e,o=r/l<i/t;return l<t&&r<i?o?t/l:i/r:o?i/(r/(l/t)):t/(l/(r/i))}},ti=()=>{var e,i;null===(i=null===(e=Re.current)||void 0===e?void 0:e[ye])||void 0===i||i.resetTransform(),Ce((e=>0===e?ce.length-1:e-1),(e=>{c("polite"),m(Ke(e),"polite")}))},li=()=>{var e,i;null===(i=null===(e=Re.current)||void 0===e?void 0:e[ye])||void 0===i||i.resetTransform(),Ce((e=>e===ce.length-1?0:e+1),(e=>{c("polite"),m(Ke(e),"polite")}))},ri=e=>{var i,t;null===(t=null===(i=Re.current)||void 0===i?void 0:i[ye])||void 0===t||t.resetTransform(),Ce(e)},oi=()=>{const{fileName:e,fileSize:l}=null!=_e?_e:{},r=null==e?void 0:e.trim(),o=null==l?void 0:l.trim();return t("div",{className:u(le,!o&&re),"aria-live":"polite","aria-atomic":"true","data-testid":"file-info-bar",children:[r&&i(B.BodyBL,{className:ie,weight:"semibold","data-testid":"file-info-name",children:r}),o&&i(B.BodyMD,{className:te,"data-testid":"file-info-size",children:o})]})};return i(y,Object.assign({},xe,{"data-testid":"image-carousel-modal","aria-label":He?"Carousel":"Image carousel",show:ke,disableInitialFocus:!0,children:t("div",{className:D,children:[t("div",{className:M,children:[t("div",{className:R,children:[i("div",{className:z,ref:De,onTouchStart:e=>{Te<=1&&Ae(e.touches[0].clientX)},onTouchMove:e=>{!Be||Te>1||Se(e.touches[0].clientX)},onTouchEnd:()=>{De.current&&(Math.abs(Ve)>De.current.offsetWidth/3&&(Ve>0?li():ti()),Ae(void 0),Se(void 0))},children:i("div",{className:P,style:{transform:`translateX(calc(${100*-ye}% - ${Ve}px))`},children:ce.map(((e,t)=>{const l=t===ye,r=Math.abs(t-ye)<=1||0===ye&&t===ce.length-1||ye===ce.length-1&&0===t;return i("div",{className:V,"data-testid":"slide-item",children:i("div",{className:_,ref:l?ze:null,tabIndex:l?0:-1,children:ae(e)?r?e.renderContent():i(I,{className:F}):i(k,{ref:e=>Re.current[t]=e,panning:{disabled:Te<=1},initialScale:1,onZoom:Qe,onZoomStop:Qe,onWheel:Qe,children:i(x,{children:i(oe,{className:H,src:e.src,alt:Ke(t),placeholder:i(I,{className:F}),fit:"scale-down",retrieveImageDimension:!0,setDimension:ei})})})})},t)}))})}),!he&&t(l,{children:[i(C,{className:u(X,Z,O),ref:qe,"aria-label":`Previous ${Ge}`,"data-testid":"prev-btn",onClick:ti,children:i(r,{"aria-hidden":!0})}),i(C,{className:u(X,Z,W),ref:Ee,"aria-label":`Next ${Ge}`,"data-testid":"forward-btn",onClick:li,children:i(o,{"aria-hidden":!0})})]}),!ve&&i("div",{className:q,"aria-hidden":"true",children:i(B.BodyXS,{className:E,weight:"semibold","data-testid":"carousel-counter",children:`${ye+1}/${ce.length}`})})]}),!ue&&i("div",{className:G,ref:Pe,"aria-hidden":"true","data-testid":"thumbnail-container",children:i("div",{className:J,children:ce.map(((e,t)=>{var l;const r=ae(e)?e.thumbnailSrc:null!==(l=e.thumbnailSrc)&&void 0!==l?l:e.src;return i("div",{className:K,children:i("div",{className:Q,"data-active":t===ye,"data-testid":"thumbnail-item",onClick:()=>ri(t),ref:e=>Me.current[t]=e,children:r?i(oe,{className:U,src:r,alt:`Thumbnail ${t+1}`,fit:"cover"}):i(I,{className:F})})},t)}))})})]}),(()=>{var e;return t("div",{className:Y,ref:We,"data-has-file-info":Je,children:[Je&&oi(),Fe.map(((e,t)=>i(C,{className:X,"aria-label":e.ariaLabel,"data-testid":e["data-testid"],onClick:()=>(e=>{_e&&e.onClick(_e,ye)})(e),children:j(e.icon,{"aria-hidden":!0})},t))),!pe&&!ae(_e)&&i(C,{className:X,"aria-label":1===Te?"Zoom in":"Zoom out",onClick:Ye,children:i(1===Te?a:n,{"aria-hidden":!0})}),ge&&i(C,{className:u(X,ee),"aria-label":`Delete ${ae(_e)&&(null===(e=_e.itemLabel)||void 0===e?void 0:e.trim())||"image"}`,"data-testid":"delete-btn",onClick:Ue,children:i(d,{"aria-hidden":!0})}),i(C,{className:X,"aria-label":He?"Close carousel":"Close image carousel",onClick:be,children:i(s,{"aria-hidden":!0})})]})})()]})}))},se=h(ne);export{ne as Component,se as FullscreenImageCarousel};
|
|
2
2
|
//# sourceMappingURL=fullscreen-image-carousel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fullscreen-image-carousel.js","sources":["../../src/fullscreen-image-carousel/fullscreen-image-carousel.tsx"],"sourcesContent":["import {\n ChevronLeftIcon,\n ChevronRightIcon,\n CrossIcon,\n MagnifierMinusIcon,\n MagnifierPlusIcon,\n} from \"@lifesg/react-icons\";\nimport { BinIcon } from \"@lifesg/react-icons/bin\";\nimport { announce, clearAnnouncer } from \"@react-aria/live-announcer\";\nimport clsx from \"clsx\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type {\n ReactZoomPanPinchContentRef,\n ReactZoomPanPinchRef,\n} from \"react-zoom-pan-pinch\";\nimport { TransformComponent, TransformWrapper } from \"react-zoom-pan-pinch\";\n\nimport { ModalV2 } from \"../modal-v2\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport { useStateCallback } from \"../shared/hooks\";\nimport { ImagePlaceholder } from \"../shared/image-placeholder\";\nimport { formatUnitValue, useApplyStyle } from \"../theme\";\nimport { Typography } from \"../typography\";\nimport { useEventListener } from \"../util\";\nimport * as styles from \"./fullscreen-image-carousel.styles\";\nimport { StatefulImage } from \"./stateful-image\";\nimport type {\n FullscreenImageCarouselCustomItemProps,\n FullscreenImageCarouselItemProps,\n FullscreenImageCarouselProps,\n FullscreenImageCarouselRef,\n ImageDimension,\n} from \"./types\";\n\nconst isCustomItem = (\n item: FullscreenImageCarouselItemProps | undefined\n): item is FullscreenImageCarouselCustomItemProps =>\n !!item && item.type === \"custom\";\n\nexport const Component = (\n {\n items,\n initialActiveItemIndex,\n hideThumbnail = false,\n hideNavigation = false,\n hideCounter = false,\n hideMagnifier = false,\n onDelete,\n onClose,\n insets,\n show,\n ...otherProps\n }: FullscreenImageCarouselProps,\n ref: React.Ref<FullscreenImageCarouselRef>\n) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const [currentSlide, setCurrentSlide] = useStateCallback(\n initialActiveItemIndex ?? 0\n );\n const [imagesDimension, setImageDimension] = useState<\n Record<string, ImageDimension>\n >({});\n const [zoom, setZoom] = useState(1);\n const [startX, setStartX] = useState<number | undefined>();\n const [endX, setEndX] = useState<number | undefined>();\n const containerRef = useRef<HTMLDivElement>(null);\n const thumbnailRefs = useRef<(HTMLDivElement | null)[]>([]);\n const zoomRefs = useRef<(ReactZoomPanPinchContentRef | null)[]>([]);\n const imageRef = useRef<HTMLDivElement>(null);\n const topActionButtonsRef = useRef<HTMLDivElement>(null);\n const prevArrowButtonRef = useRef<HTMLButtonElement>(null);\n const nextArrowButtonRef = useRef<HTMLButtonElement>(null);\n const thumbnailContainerRef = useRef<HTMLDivElement>(null);\n const diff = startX && endX ? startX - endX : 0;\n const currentItem = items[currentSlide];\n const hasAnyItemLabel = items.some(\n (item) => isCustomItem(item) && !!item.itemLabel?.trim()\n );\n const carouselItemNoun = hasAnyItemLabel ? \"item\" : \"image\";\n const hasFileInfo = useMemo(\n () =>\n items.some(\n (item) => item.fileName?.trim() || item.fileSize?.trim()\n ),\n [items]\n );\n\n useApplyStyle(topActionButtonsRef, {\n [styles.tokens.topActionButtons.insetTop]: formatUnitValue(\n insets?.top,\n \"px\"\n ),\n [styles.tokens.topActionButtons.insetLeft]: formatUnitValue(\n insets?.left,\n \"px\"\n ),\n [styles.tokens.topActionButtons.insetRight]: formatUnitValue(\n insets?.right,\n \"px\"\n ),\n });\n\n useApplyStyle(prevArrowButtonRef, {\n [styles.tokens.arrowButton.insetLeft]: formatUnitValue(\n insets?.left,\n \"px\"\n ),\n });\n\n useApplyStyle(nextArrowButtonRef, {\n [styles.tokens.arrowButton.insetRight]: formatUnitValue(\n insets?.right,\n \"px\"\n ),\n });\n\n useApplyStyle(thumbnailContainerRef, {\n [styles.tokens.thumbnailContainer.insetBottom]: formatUnitValue(\n insets?.bottom,\n \"px\"\n ),\n });\n\n const getItemAriaLabel = useCallback(\n (index: number) => {\n const item = items[index];\n const itemTypeLabel = hasAnyItemLabel ? \"Item\" : \"Image\";\n const prefix = isCustomItem(item)\n ? item.itemLabel?.trim() || \"\"\n : item.alt?.trim() || \"\";\n const positionLabel = `${itemTypeLabel} ${index + 1} of ${\n items.length\n }.`;\n\n return prefix ? `${prefix}. ${positionLabel}` : positionLabel;\n },\n [items, hasAnyItemLabel]\n );\n\n useImperativeHandle<FullscreenImageCarouselRef, FullscreenImageCarouselRef>(\n ref,\n () => ({\n currentItemIndex: currentSlide,\n setCurrentItem: goToSlide,\n goToPrevItem: goToPrevSlide,\n goToNextItem: goToNextSlide,\n })\n );\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEventListener(\"keydown\", handleKeyDown, \"document\");\n\n useEffect(() => {\n if (show) {\n imageRef.current?.focus();\n }\n }, [show]);\n\n useEffect(() => {\n if (items.length === 0) {\n setCurrentSlide(0);\n return;\n }\n\n if (currentSlide > items.length - 1) {\n setCurrentSlide(items.length - 1);\n }\n }, [currentSlide, items.length, setCurrentSlide]);\n\n useEffect(() => {\n thumbnailRefs.current?.[currentSlide]?.scrollIntoView({\n behavior: \"smooth\",\n inline: \"center\",\n });\n setZoom(1);\n }, [currentSlide]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleTouchStart = (e: React.TouchEvent) => {\n if (zoom <= 1) setStartX(e.touches[0].clientX);\n };\n\n const handleTouchMove = (e: React.TouchEvent) => {\n if (!startX || zoom > 1) return;\n setEndX(e.touches[0].clientX);\n };\n\n const handleTouchEnd = () => {\n if (!containerRef.current) return;\n if (Math.abs(diff) > containerRef.current.offsetWidth / 3) {\n if (diff > 0) {\n goToNextSlide();\n } else {\n goToPrevSlide();\n }\n }\n setStartX(undefined);\n setEndX(undefined);\n };\n\n const handleZoom = (e: ReactZoomPanPinchRef) => {\n setZoom(e.state.scale);\n };\n\n const handleDelete = () => {\n if (currentItem && onDelete) {\n onDelete(currentItem, currentSlide);\n }\n };\n\n function handleKeyDown(e: KeyboardEvent) {\n if (e.key === \"ArrowRight\") {\n goToNextSlide();\n } else if (e.key === \"ArrowLeft\") {\n goToPrevSlide();\n } else if (e.key === \"Escape\") {\n onClose?.();\n }\n }\n\n const handleMagnifier = () => {\n if (zoom === 1) {\n const zoomRatio = getZoomRatio();\n zoomRefs.current?.[currentSlide]?.centerView(zoomRatio);\n setZoom(zoomRatio ?? 1);\n } else {\n setZoom(1);\n zoomRefs.current?.[currentSlide]?.resetTransform();\n }\n };\n\n const setDimension = ({\n src,\n height,\n width,\n }: {\n src: string;\n height: number;\n width: number;\n }) => {\n setImageDimension((oldState) => {\n return { ...oldState, [src]: { height, width } };\n });\n };\n\n const getZoomRatio = () => {\n if (!currentItem || isCustomItem(currentItem)) {\n return;\n }\n\n const imageDimension = imagesDimension[currentItem.src];\n\n if (containerRef.current && !!imageDimension) {\n const { clientHeight, clientWidth } = containerRef.current;\n const { width, height } = imageDimension;\n const isSmallImg = width < clientWidth && height < clientHeight;\n\n const isImgLandscapeRelativeToDevice =\n height / width < clientHeight / clientWidth;\n\n if (isSmallImg) {\n return isImgLandscapeRelativeToDevice\n ? clientWidth / width\n : clientHeight / height;\n }\n\n return isImgLandscapeRelativeToDevice\n ? clientHeight / (height / (width / clientWidth))\n : clientWidth / (width / (height / clientHeight));\n }\n };\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const goToPrevSlide = () => {\n zoomRefs.current?.[currentSlide]?.resetTransform();\n setCurrentSlide(\n (prev) => (prev === 0 ? items.length - 1 : prev - 1),\n (slide) => {\n clearAnnouncer(\"polite\");\n announce(getItemAriaLabel(slide), \"polite\");\n }\n );\n };\n\n const goToNextSlide = () => {\n zoomRefs.current?.[currentSlide]?.resetTransform();\n setCurrentSlide(\n (prev) => (prev === items.length - 1 ? 0 : prev + 1),\n (slide) => {\n clearAnnouncer(\"polite\");\n announce(getItemAriaLabel(slide), \"polite\");\n }\n );\n };\n\n const goToSlide = (index: number) => {\n zoomRefs.current?.[currentSlide]?.resetTransform();\n setCurrentSlide(index);\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderSlides = () => {\n return (\n <div\n className={styles.imageGallerySlides}\n style={{\n transform: `translateX(calc(${\n -currentSlide * 100\n }% - ${diff}px))`,\n }}\n >\n {items.map((item, index) => {\n const isActive = index === currentSlide;\n const isActiveOrAdjacent =\n Math.abs(index - currentSlide) <= 1 ||\n (currentSlide === 0 && index === items.length - 1) ||\n (currentSlide === items.length - 1 && index === 0);\n\n return (\n <div\n className={styles.imageGallerySlide}\n key={index}\n data-testid=\"slide-item\"\n >\n <div\n className={styles.focusableImageRegion}\n ref={isActive ? imageRef : null}\n tabIndex={isActive ? 0 : -1}\n >\n {isCustomItem(item) ? (\n isActiveOrAdjacent ? (\n item.renderContent()\n ) : (\n <ImagePlaceholder\n className={\n styles.slidePlaceholderImage\n }\n />\n )\n ) : (\n <TransformWrapper\n ref={(el) =>\n (zoomRefs.current[index] = el)\n }\n panning={{\n disabled: zoom <= 1,\n }}\n initialScale={1}\n onZoom={handleZoom}\n onZoomStop={handleZoom}\n onWheel={handleZoom}\n >\n <TransformComponent>\n <StatefulImage\n className={styles.slideImage}\n src={item.src}\n alt={getItemAriaLabel(index)}\n placeholder={\n <ImagePlaceholder\n className={\n styles.slidePlaceholderImage\n }\n />\n }\n fit=\"scale-down\"\n retrieveImageDimension\n setDimension={setDimension}\n />\n </TransformComponent>\n </TransformWrapper>\n )}\n </div>\n </div>\n );\n })}\n </div>\n );\n };\n\n const renderFileInfo = () => {\n const { fileName, fileSize } = currentItem ?? {};\n const trimmedName = fileName?.trim();\n const trimmedSize = fileSize?.trim();\n\n return (\n <div\n className={clsx(\n styles.fileInfoTextWrapper,\n !trimmedSize && styles.fileInfoTextWrapperCentered\n )}\n aria-live=\"polite\"\n aria-atomic=\"true\"\n data-testid=\"file-info-bar\"\n >\n {trimmedName && (\n <Typography.BodyBL\n className={styles.fileInfoFileName}\n weight=\"semibold\"\n data-testid=\"file-info-name\"\n >\n {trimmedName}\n </Typography.BodyBL>\n )}\n {trimmedSize && (\n <Typography.BodyMD\n className={styles.fileInfoFileSize}\n data-testid=\"file-info-size\"\n >\n {trimmedSize}\n </Typography.BodyMD>\n )}\n </div>\n );\n };\n\n const renderThumbnails = () => {\n return (\n <div\n className={styles.thumbnailContainer}\n ref={thumbnailContainerRef}\n aria-hidden=\"true\"\n data-testid=\"thumbnail-container\"\n >\n <div className={styles.thumbnailWrapper}>\n {items.map((item, index) => {\n const src = isCustomItem(item)\n ? item.thumbnailSrc\n : item.thumbnailSrc ?? item.src;\n return (\n <div\n className={styles.thumbnailItemContainer}\n key={index}\n >\n <div\n className={styles.thumbnailItem}\n data-active={index === currentSlide}\n data-testid=\"thumbnail-item\"\n onClick={() => goToSlide(index)}\n ref={(el) =>\n (thumbnailRefs.current[index] = el)\n }\n >\n {src ? (\n <StatefulImage\n className={styles.thumbnailImage}\n src={src}\n alt={`Thumbnail ${index + 1}`}\n fit=\"cover\"\n />\n ) : (\n <ImagePlaceholder\n className={\n styles.slidePlaceholderImage\n }\n />\n )}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n };\n\n return (\n <ModalV2\n {...otherProps}\n data-testid=\"image-carousel-modal\"\n aria-label={hasAnyItemLabel ? \"Carousel\" : \"Image carousel\"}\n show={show}\n disableInitialFocus\n >\n <div className={styles.carouselModalContent}>\n <div className={styles.imageGalleryContainer}>\n <div className={styles.imageGalleryWrapper}>\n <div\n className={styles.imageGallerySwipe}\n ref={containerRef}\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleTouchEnd}\n >\n {renderSlides()}\n </div>\n\n {!hideNavigation && (\n <>\n <ClickableIcon\n className={clsx(\n styles.iconButton,\n styles.arrowButton,\n styles.arrowButtonLeft\n )}\n ref={prevArrowButtonRef}\n aria-label={`Previous ${carouselItemNoun}`}\n data-testid=\"prev-btn\"\n onClick={goToPrevSlide}\n >\n <ChevronLeftIcon aria-hidden />\n </ClickableIcon>\n <ClickableIcon\n className={clsx(\n styles.iconButton,\n styles.arrowButton,\n styles.arrowButtonRight\n )}\n ref={nextArrowButtonRef}\n aria-label={`Next ${carouselItemNoun}`}\n data-testid=\"forward-btn\"\n onClick={goToNextSlide}\n >\n <ChevronRightIcon aria-hidden />\n </ClickableIcon>\n </>\n )}\n\n {!hideCounter && (\n <div className={styles.boxChip} aria-hidden=\"true\">\n <Typography.BodyXS\n className={styles.chip}\n weight=\"semibold\"\n data-testid=\"carousel-counter\"\n >{`${currentSlide + 1}/${\n items.length\n }`}</Typography.BodyXS>\n </div>\n )}\n </div>\n\n {!hideThumbnail && renderThumbnails()}\n </div>\n <div\n className={styles.topActionButtons}\n ref={topActionButtonsRef}\n data-has-file-info={hasFileInfo}\n >\n {hasFileInfo && renderFileInfo()}\n {!hideMagnifier && !isCustomItem(currentItem) && (\n <ClickableIcon\n className={styles.iconButton}\n aria-label={zoom === 1 ? \"Zoom in\" : \"Zoom out\"}\n onClick={handleMagnifier}\n >\n {zoom === 1 ? (\n <MagnifierPlusIcon aria-hidden />\n ) : (\n <MagnifierMinusIcon aria-hidden />\n )}\n </ClickableIcon>\n )}\n\n {onDelete && (\n <ClickableIcon\n className={clsx(\n styles.iconButton,\n styles.iconButtonError\n )}\n aria-label={`Delete ${\n (isCustomItem(currentItem) &&\n currentItem.itemLabel?.trim()) ||\n \"image\"\n }`}\n data-testid=\"delete-btn\"\n onClick={handleDelete}\n >\n <BinIcon aria-hidden />\n </ClickableIcon>\n )}\n\n <ClickableIcon\n className={styles.iconButton}\n aria-label={\n hasAnyItemLabel\n ? \"Close carousel\"\n : \"Close image carousel\"\n }\n onClick={onClose}\n >\n <CrossIcon aria-hidden />\n </ClickableIcon>\n </div>\n </div>\n </ModalV2>\n );\n};\n\n// @catalog\n/**\n * A fullscreen modal carousel for browsing images and custom media items.\n *\n * Use to present a collection of images or custom content in an overlay with\n * navigation controls, zoom support, and an optional thumbnail strip.\n * The top info bar is rendered only when at least one item provides some file metadata.\n * @keywords carousel, gallery, image, lightbox, media, overlay\n */\nexport const FullscreenImageCarousel = forwardRef<\n FullscreenImageCarouselRef,\n FullscreenImageCarouselProps\n>(Component);\n"],"names":["isCustomItem","item","type","Component","_a","ref","items","initialActiveItemIndex","hideThumbnail","hideNavigation","hideCounter","hideMagnifier","onDelete","onClose","insets","show","otherProps","__rest","currentSlide","setCurrentSlide","useStateCallback","imagesDimension","setImageDimension","useState","zoom","setZoom","startX","setStartX","endX","setEndX","containerRef","useRef","thumbnailRefs","zoomRefs","imageRef","topActionButtonsRef","prevArrowButtonRef","nextArrowButtonRef","thumbnailContainerRef","diff","currentItem","hasAnyItemLabel","some","itemLabel","trim","carouselItemNoun","hasFileInfo","useMemo","fileName","fileSize","_b","useApplyStyle","styles.tokens","topActionButtons","insetTop","formatUnitValue","top","insetLeft","left","insetRight","right","arrowButton","thumbnailContainer","insetBottom","bottom","getItemAriaLabel","useCallback","index","itemTypeLabel","prefix","alt","positionLabel","length","useImperativeHandle","currentItemIndex","setCurrentItem","goToSlide","goToPrevItem","goToPrevSlide","goToNextItem","goToNextSlide","useEventListener","e","key","useEffect","current","focus","scrollIntoView","behavior","inline","handleZoom","state","scale","setDimension","src","height","width","oldState","Object","assign","getZoomRatio","imageDimension","clientHeight","clientWidth","isImgLandscapeRelativeToDevice","resetTransform","prev","slide","clearAnnouncer","announce","_jsx","ModalV2","disableInitialFocus","_jsxs","className","styles.carouselModalContent","children","styles.imageGalleryContainer","styles.imageGalleryWrapper","styles.imageGallerySwipe","onTouchStart","touches","clientX","onTouchMove","onTouchEnd","Math","abs","offsetWidth","undefined","styles.imageGallerySlides","style","transform","map","isActive","isActiveOrAdjacent","styles.imageGallerySlide","styles.focusableImageRegion","tabIndex","renderContent","ImagePlaceholder","styles.slidePlaceholderImage","TransformWrapper","el","panning","disabled","initialScale","onZoom","onZoomStop","onWheel","TransformComponent","StatefulImage","styles.slideImage","placeholder","fit","retrieveImageDimension","_Fragment","ClickableIcon","clsx","styles.iconButton","styles.arrowButton","styles.arrowButtonLeft","onClick","ChevronLeftIcon","styles.arrowButtonRight","ChevronRightIcon","styles.boxChip","Typography","BodyXS","styles.chip","weight","styles.thumbnailContainer","styles.thumbnailWrapper","thumbnailSrc","styles.thumbnailItemContainer","styles.thumbnailItem","styles.thumbnailImage","styles.topActionButtons","trimmedName","trimmedSize","styles.fileInfoTextWrapper","styles.fileInfoTextWrapperCentered","BodyBL","styles.fileInfoFileName","BodyMD","styles.fileInfoFileSize","renderFileInfo","zoomRatio","centerView","_d","_c","MagnifierPlusIcon","MagnifierMinusIcon","styles.iconButtonError","BinIcon","CrossIcon","FullscreenImageCarousel","forwardRef"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fullscreen-image-carousel.js","sources":["../../src/fullscreen-image-carousel/fullscreen-image-carousel.tsx"],"sourcesContent":["import {\n ChevronLeftIcon,\n ChevronRightIcon,\n CrossIcon,\n MagnifierMinusIcon,\n MagnifierPlusIcon,\n} from \"@lifesg/react-icons\";\nimport { BinIcon } from \"@lifesg/react-icons/bin\";\nimport { announce, clearAnnouncer } from \"@react-aria/live-announcer\";\nimport clsx from \"clsx\";\nimport {\n cloneElement,\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type {\n ReactZoomPanPinchContentRef,\n ReactZoomPanPinchRef,\n} from \"react-zoom-pan-pinch\";\nimport { TransformComponent, TransformWrapper } from \"react-zoom-pan-pinch\";\n\nimport { ModalV2 } from \"../modal-v2\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport { useStateCallback } from \"../shared/hooks\";\nimport { ImagePlaceholder } from \"../shared/image-placeholder\";\nimport { formatUnitValue, useApplyStyle } from \"../theme\";\nimport { Typography } from \"../typography\";\nimport { mergeRefs, useEventListener } from \"../util\";\nimport * as styles from \"./fullscreen-image-carousel.styles\";\nimport { StatefulImage } from \"./stateful-image\";\nimport type {\n FullscreenImageCarouselCustomAction,\n FullscreenImageCarouselCustomItemProps,\n FullscreenImageCarouselItemProps,\n FullscreenImageCarouselProps,\n FullscreenImageCarouselRef,\n ImageDimension,\n} from \"./types\";\n\nconst isCustomItem = (\n item: FullscreenImageCarouselItemProps | undefined\n): item is FullscreenImageCarouselCustomItemProps =>\n !!item && item.type === \"custom\";\n\nexport const Component = (\n {\n items,\n initialActiveItemIndex,\n hideThumbnail = false,\n hideNavigation = false,\n hideCounter = false,\n hideMagnifier = false,\n customActions,\n onDelete,\n onClose,\n insets,\n topBarRef,\n show,\n ...otherProps\n }: FullscreenImageCarouselProps,\n ref: React.Ref<FullscreenImageCarouselRef>\n) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const [currentSlide, setCurrentSlide] = useStateCallback(\n initialActiveItemIndex ?? 0\n );\n const [imagesDimension, setImageDimension] = useState<\n Record<string, ImageDimension>\n >({});\n const [zoom, setZoom] = useState(1);\n const [startX, setStartX] = useState<number | undefined>();\n const [endX, setEndX] = useState<number | undefined>();\n const containerRef = useRef<HTMLDivElement>(null);\n const thumbnailRefs = useRef<(HTMLDivElement | null)[]>([]);\n const zoomRefs = useRef<(ReactZoomPanPinchContentRef | null)[]>([]);\n const imageRef = useRef<HTMLDivElement>(null);\n /*\n * The top bar's element is held in state rather than a ref so that its mount\n * causes a render. Overlay keeps its portal target in state and mounts these\n * children, so the layout effect below would otherwise run while a ref was\n * still null and never write the inset custom properties.\n */\n const [topActionButtons, setTopActionButtons] =\n useState<HTMLDivElement | null>(null);\n const topActionButtonsRef = useMemo(\n () => ({ current: topActionButtons }),\n [topActionButtons]\n );\n const mergedTopBarRef = useMemo(\n () => mergeRefs(setTopActionButtons, topBarRef),\n [topBarRef]\n );\n const prevArrowButtonRef = useRef<HTMLButtonElement>(null);\n const nextArrowButtonRef = useRef<HTMLButtonElement>(null);\n const thumbnailContainerRef = useRef<HTMLDivElement>(null);\n const diff = startX && endX ? startX - endX : 0;\n const currentItem = items[currentSlide];\n const resolvedCustomActions =\n currentItem?.customActions ?? customActions ?? [];\n const hasAnyItemLabel = items.some(\n (item) => isCustomItem(item) && !!item.itemLabel?.trim()\n );\n const carouselItemNoun = hasAnyItemLabel ? \"item\" : \"image\";\n const hasFileInfo = useMemo(\n () =>\n items.some(\n (item) => item.fileName?.trim() || item.fileSize?.trim()\n ),\n [items]\n );\n\n useApplyStyle(topActionButtonsRef, {\n [styles.tokens.topActionButtons.insetTop]: formatUnitValue(\n insets?.top,\n \"px\"\n ),\n [styles.tokens.topActionButtons.insetLeft]: formatUnitValue(\n insets?.left,\n \"px\"\n ),\n [styles.tokens.topActionButtons.insetRight]: formatUnitValue(\n insets?.right,\n \"px\"\n ),\n });\n\n useApplyStyle(prevArrowButtonRef, {\n [styles.tokens.arrowButton.insetLeft]: formatUnitValue(\n insets?.left,\n \"px\"\n ),\n });\n\n useApplyStyle(nextArrowButtonRef, {\n [styles.tokens.arrowButton.insetRight]: formatUnitValue(\n insets?.right,\n \"px\"\n ),\n });\n\n useApplyStyle(thumbnailContainerRef, {\n [styles.tokens.thumbnailContainer.insetBottom]: formatUnitValue(\n insets?.bottom,\n \"px\"\n ),\n });\n\n const getItemAriaLabel = useCallback(\n (index: number) => {\n const item = items[index];\n const itemTypeLabel = hasAnyItemLabel ? \"Item\" : \"Image\";\n const prefix = isCustomItem(item)\n ? item.itemLabel?.trim() || \"\"\n : item.alt?.trim() || \"\";\n const positionLabel = `${itemTypeLabel} ${index + 1} of ${\n items.length\n }.`;\n\n return prefix ? `${prefix}. ${positionLabel}` : positionLabel;\n },\n [items, hasAnyItemLabel]\n );\n\n useImperativeHandle<FullscreenImageCarouselRef, FullscreenImageCarouselRef>(\n ref,\n () => ({\n currentItemIndex: currentSlide,\n setCurrentItem: goToSlide,\n goToPrevItem: goToPrevSlide,\n goToNextItem: goToNextSlide,\n })\n );\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEventListener(\"keydown\", handleKeyDown, \"document\");\n\n useEffect(() => {\n if (show) {\n imageRef.current?.focus();\n }\n }, [show]);\n\n useEffect(() => {\n if (items.length === 0) {\n setCurrentSlide(0);\n return;\n }\n\n if (currentSlide > items.length - 1) {\n setCurrentSlide(items.length - 1);\n }\n }, [currentSlide, items.length, setCurrentSlide]);\n\n useEffect(() => {\n thumbnailRefs.current?.[currentSlide]?.scrollIntoView({\n behavior: \"smooth\",\n inline: \"center\",\n });\n setZoom(1);\n }, [currentSlide]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleTouchStart = (e: React.TouchEvent) => {\n if (zoom <= 1) setStartX(e.touches[0].clientX);\n };\n\n const handleTouchMove = (e: React.TouchEvent) => {\n if (!startX || zoom > 1) return;\n setEndX(e.touches[0].clientX);\n };\n\n const handleTouchEnd = () => {\n if (!containerRef.current) return;\n if (Math.abs(diff) > containerRef.current.offsetWidth / 3) {\n if (diff > 0) {\n goToNextSlide();\n } else {\n goToPrevSlide();\n }\n }\n setStartX(undefined);\n setEndX(undefined);\n };\n\n const handleZoom = (e: ReactZoomPanPinchRef) => {\n setZoom(e.state.scale);\n };\n\n const handleDelete = () => {\n if (currentItem && onDelete) {\n onDelete(currentItem, currentSlide);\n }\n };\n\n const handleCustomAction = (\n action: FullscreenImageCarouselCustomAction\n ) => {\n if (currentItem) {\n action.onClick(currentItem, currentSlide);\n }\n };\n\n function handleKeyDown(e: KeyboardEvent) {\n if (e.key === \"ArrowRight\") {\n goToNextSlide();\n } else if (e.key === \"ArrowLeft\") {\n goToPrevSlide();\n } else if (e.key === \"Escape\") {\n onClose?.();\n }\n }\n\n const handleMagnifier = () => {\n if (zoom === 1) {\n const zoomRatio = getZoomRatio();\n zoomRefs.current?.[currentSlide]?.centerView(zoomRatio);\n setZoom(zoomRatio ?? 1);\n } else {\n setZoom(1);\n zoomRefs.current?.[currentSlide]?.resetTransform();\n }\n };\n\n const setDimension = ({\n src,\n height,\n width,\n }: {\n src: string;\n height: number;\n width: number;\n }) => {\n setImageDimension((oldState) => {\n return { ...oldState, [src]: { height, width } };\n });\n };\n\n const getZoomRatio = () => {\n if (!currentItem || isCustomItem(currentItem)) {\n return;\n }\n\n const imageDimension = imagesDimension[currentItem.src];\n\n if (containerRef.current && !!imageDimension) {\n const { clientHeight, clientWidth } = containerRef.current;\n const { width, height } = imageDimension;\n const isSmallImg = width < clientWidth && height < clientHeight;\n\n const isImgLandscapeRelativeToDevice =\n height / width < clientHeight / clientWidth;\n\n if (isSmallImg) {\n return isImgLandscapeRelativeToDevice\n ? clientWidth / width\n : clientHeight / height;\n }\n\n return isImgLandscapeRelativeToDevice\n ? clientHeight / (height / (width / clientWidth))\n : clientWidth / (width / (height / clientHeight));\n }\n };\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const goToPrevSlide = () => {\n zoomRefs.current?.[currentSlide]?.resetTransform();\n setCurrentSlide(\n (prev) => (prev === 0 ? items.length - 1 : prev - 1),\n (slide) => {\n clearAnnouncer(\"polite\");\n announce(getItemAriaLabel(slide), \"polite\");\n }\n );\n };\n\n const goToNextSlide = () => {\n zoomRefs.current?.[currentSlide]?.resetTransform();\n setCurrentSlide(\n (prev) => (prev === items.length - 1 ? 0 : prev + 1),\n (slide) => {\n clearAnnouncer(\"polite\");\n announce(getItemAriaLabel(slide), \"polite\");\n }\n );\n };\n\n const goToSlide = (index: number) => {\n zoomRefs.current?.[currentSlide]?.resetTransform();\n setCurrentSlide(index);\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderSlides = () => {\n return (\n <div\n className={styles.imageGallerySlides}\n style={{\n transform: `translateX(calc(${\n -currentSlide * 100\n }% - ${diff}px))`,\n }}\n >\n {items.map((item, index) => {\n const isActive = index === currentSlide;\n const isActiveOrAdjacent =\n Math.abs(index - currentSlide) <= 1 ||\n (currentSlide === 0 && index === items.length - 1) ||\n (currentSlide === items.length - 1 && index === 0);\n\n return (\n <div\n className={styles.imageGallerySlide}\n key={index}\n data-testid=\"slide-item\"\n >\n <div\n className={styles.focusableImageRegion}\n ref={isActive ? imageRef : null}\n tabIndex={isActive ? 0 : -1}\n >\n {isCustomItem(item) ? (\n isActiveOrAdjacent ? (\n item.renderContent()\n ) : (\n <ImagePlaceholder\n className={\n styles.slidePlaceholderImage\n }\n />\n )\n ) : (\n <TransformWrapper\n ref={(el) =>\n (zoomRefs.current[index] = el)\n }\n panning={{\n disabled: zoom <= 1,\n }}\n initialScale={1}\n onZoom={handleZoom}\n onZoomStop={handleZoom}\n onWheel={handleZoom}\n >\n <TransformComponent>\n <StatefulImage\n className={styles.slideImage}\n src={item.src}\n alt={getItemAriaLabel(index)}\n placeholder={\n <ImagePlaceholder\n className={\n styles.slidePlaceholderImage\n }\n />\n }\n fit=\"scale-down\"\n retrieveImageDimension\n setDimension={setDimension}\n />\n </TransformComponent>\n </TransformWrapper>\n )}\n </div>\n </div>\n );\n })}\n </div>\n );\n };\n\n const renderFileInfo = () => {\n const { fileName, fileSize } = currentItem ?? {};\n const trimmedName = fileName?.trim();\n const trimmedSize = fileSize?.trim();\n\n return (\n <div\n className={clsx(\n styles.fileInfoTextWrapper,\n !trimmedSize && styles.fileInfoTextWrapperCentered\n )}\n aria-live=\"polite\"\n aria-atomic=\"true\"\n data-testid=\"file-info-bar\"\n >\n {trimmedName && (\n <Typography.BodyBL\n className={styles.fileInfoFileName}\n weight=\"semibold\"\n data-testid=\"file-info-name\"\n >\n {trimmedName}\n </Typography.BodyBL>\n )}\n {trimmedSize && (\n <Typography.BodyMD\n className={styles.fileInfoFileSize}\n data-testid=\"file-info-size\"\n >\n {trimmedSize}\n </Typography.BodyMD>\n )}\n </div>\n );\n };\n\n const renderThumbnails = () => {\n return (\n <div\n className={styles.thumbnailContainer}\n ref={thumbnailContainerRef}\n aria-hidden=\"true\"\n data-testid=\"thumbnail-container\"\n >\n <div className={styles.thumbnailWrapper}>\n {items.map((item, index) => {\n const src = isCustomItem(item)\n ? item.thumbnailSrc\n : item.thumbnailSrc ?? item.src;\n return (\n <div\n className={styles.thumbnailItemContainer}\n key={index}\n >\n <div\n className={styles.thumbnailItem}\n data-active={index === currentSlide}\n data-testid=\"thumbnail-item\"\n onClick={() => goToSlide(index)}\n ref={(el) =>\n (thumbnailRefs.current[index] = el)\n }\n >\n {src ? (\n <StatefulImage\n className={styles.thumbnailImage}\n src={src}\n alt={`Thumbnail ${index + 1}`}\n fit=\"cover\"\n />\n ) : (\n <ImagePlaceholder\n className={\n styles.slidePlaceholderImage\n }\n />\n )}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n };\n\n const renderTopActions = () => {\n return (\n <div\n className={styles.topActionButtons}\n ref={mergedTopBarRef}\n data-has-file-info={hasFileInfo}\n >\n {hasFileInfo && renderFileInfo()}\n\n {resolvedCustomActions.map((action, index) => (\n <ClickableIcon\n key={index}\n className={styles.iconButton}\n aria-label={action.ariaLabel}\n data-testid={action[\"data-testid\"]}\n onClick={() => handleCustomAction(action)}\n >\n {cloneElement(action.icon, { \"aria-hidden\": true })}\n </ClickableIcon>\n ))}\n\n {!hideMagnifier && !isCustomItem(currentItem) && (\n <ClickableIcon\n className={styles.iconButton}\n aria-label={zoom === 1 ? \"Zoom in\" : \"Zoom out\"}\n onClick={handleMagnifier}\n >\n {zoom === 1 ? (\n <MagnifierPlusIcon aria-hidden />\n ) : (\n <MagnifierMinusIcon aria-hidden />\n )}\n </ClickableIcon>\n )}\n\n {onDelete && (\n <ClickableIcon\n className={clsx(\n styles.iconButton,\n styles.iconButtonError\n )}\n aria-label={`Delete ${\n (isCustomItem(currentItem) &&\n currentItem.itemLabel?.trim()) ||\n \"image\"\n }`}\n data-testid=\"delete-btn\"\n onClick={handleDelete}\n >\n <BinIcon aria-hidden />\n </ClickableIcon>\n )}\n\n <ClickableIcon\n className={styles.iconButton}\n aria-label={\n hasAnyItemLabel\n ? \"Close carousel\"\n : \"Close image carousel\"\n }\n onClick={onClose}\n >\n <CrossIcon aria-hidden />\n </ClickableIcon>\n </div>\n );\n };\n\n return (\n <ModalV2\n {...otherProps}\n data-testid=\"image-carousel-modal\"\n aria-label={hasAnyItemLabel ? \"Carousel\" : \"Image carousel\"}\n show={show}\n disableInitialFocus\n >\n <div className={styles.carouselModalContent}>\n <div className={styles.imageGalleryContainer}>\n <div className={styles.imageGalleryWrapper}>\n <div\n className={styles.imageGallerySwipe}\n ref={containerRef}\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleTouchEnd}\n >\n {renderSlides()}\n </div>\n\n {!hideNavigation && (\n <>\n <ClickableIcon\n className={clsx(\n styles.iconButton,\n styles.arrowButton,\n styles.arrowButtonLeft\n )}\n ref={prevArrowButtonRef}\n aria-label={`Previous ${carouselItemNoun}`}\n data-testid=\"prev-btn\"\n onClick={goToPrevSlide}\n >\n <ChevronLeftIcon aria-hidden />\n </ClickableIcon>\n <ClickableIcon\n className={clsx(\n styles.iconButton,\n styles.arrowButton,\n styles.arrowButtonRight\n )}\n ref={nextArrowButtonRef}\n aria-label={`Next ${carouselItemNoun}`}\n data-testid=\"forward-btn\"\n onClick={goToNextSlide}\n >\n <ChevronRightIcon aria-hidden />\n </ClickableIcon>\n </>\n )}\n\n {!hideCounter && (\n <div className={styles.boxChip} aria-hidden=\"true\">\n <Typography.BodyXS\n className={styles.chip}\n weight=\"semibold\"\n data-testid=\"carousel-counter\"\n >{`${currentSlide + 1}/${\n items.length\n }`}</Typography.BodyXS>\n </div>\n )}\n </div>\n\n {!hideThumbnail && renderThumbnails()}\n </div>\n {renderTopActions()}\n </div>\n </ModalV2>\n );\n};\n\n// @catalog\n/**\n * A fullscreen modal carousel for browsing images and custom media items.\n *\n * Use to present a collection of images or custom content in an overlay with\n * navigation controls, zoom support, and an optional thumbnail strip.\n * The top info bar is rendered only when at least one item provides some file metadata.\n * @keywords carousel, gallery, image, lightbox, media, overlay\n */\nexport const FullscreenImageCarousel = forwardRef<\n FullscreenImageCarouselRef,\n FullscreenImageCarouselProps\n>(Component);\n"],"names":["isCustomItem","item","type","Component","_a","ref","items","initialActiveItemIndex","hideThumbnail","hideNavigation","hideCounter","hideMagnifier","customActions","onDelete","onClose","insets","topBarRef","show","otherProps","__rest","currentSlide","setCurrentSlide","useStateCallback","imagesDimension","setImageDimension","useState","zoom","setZoom","startX","setStartX","endX","setEndX","containerRef","useRef","thumbnailRefs","zoomRefs","imageRef","topActionButtons","setTopActionButtons","topActionButtonsRef","useMemo","current","mergedTopBarRef","mergeRefs","prevArrowButtonRef","nextArrowButtonRef","thumbnailContainerRef","diff","currentItem","resolvedCustomActions","_c","_b","hasAnyItemLabel","some","itemLabel","trim","carouselItemNoun","hasFileInfo","fileName","fileSize","useApplyStyle","styles.tokens","insetTop","formatUnitValue","top","insetLeft","left","insetRight","right","arrowButton","thumbnailContainer","insetBottom","bottom","getItemAriaLabel","useCallback","index","itemTypeLabel","prefix","alt","positionLabel","length","useImperativeHandle","currentItemIndex","setCurrentItem","goToSlide","goToPrevItem","goToPrevSlide","goToNextItem","goToNextSlide","useEventListener","e","key","useEffect","focus","scrollIntoView","behavior","inline","handleZoom","state","scale","handleDelete","handleMagnifier","zoomRatio","getZoomRatio","centerView","_d","resetTransform","setDimension","src","height","width","oldState","Object","assign","imageDimension","clientHeight","clientWidth","isImgLandscapeRelativeToDevice","prev","slide","clearAnnouncer","announce","renderFileInfo","trimmedName","trimmedSize","_jsxs","className","clsx","styles.fileInfoTextWrapper","styles.fileInfoTextWrapperCentered","children","_jsx","Typography","BodyBL","styles.fileInfoFileName","weight","BodyMD","styles.fileInfoFileSize","ModalV2","disableInitialFocus","styles.carouselModalContent","styles.imageGalleryContainer","styles.imageGalleryWrapper","styles.imageGallerySwipe","onTouchStart","touches","clientX","onTouchMove","onTouchEnd","Math","abs","offsetWidth","undefined","styles.imageGallerySlides","style","transform","map","isActive","isActiveOrAdjacent","styles.imageGallerySlide","styles.focusableImageRegion","tabIndex","renderContent","ImagePlaceholder","styles.slidePlaceholderImage","TransformWrapper","el","panning","disabled","initialScale","onZoom","onZoomStop","onWheel","TransformComponent","StatefulImage","styles.slideImage","placeholder","fit","retrieveImageDimension","_Fragment","ClickableIcon","styles.iconButton","styles.arrowButton","styles.arrowButtonLeft","onClick","ChevronLeftIcon","styles.arrowButtonRight","ChevronRightIcon","styles.boxChip","BodyXS","styles.chip","styles.thumbnailContainer","styles.thumbnailWrapper","thumbnailSrc","styles.thumbnailItemContainer","styles.thumbnailItem","styles.thumbnailImage","styles.topActionButtons","action","ariaLabel","handleCustomAction","cloneElement","icon","MagnifierPlusIcon","MagnifierMinusIcon","styles.iconButtonError","BinIcon","CrossIcon","renderTopActions","FullscreenImageCarousel","forwardRef"],"mappings":"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"}
|
|
@@ -17,6 +17,25 @@ export interface FullscreenImageCarouselRef {
|
|
|
17
17
|
/** Navigates to the next item, wrapping from the last item to the first. */
|
|
18
18
|
goToNextItem: () => void;
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Custom button to be rendered in the carousel's top bar.
|
|
22
|
+
*/
|
|
23
|
+
export interface FullscreenImageCarouselCustomAction {
|
|
24
|
+
/** Icon element rendered inside the button. */
|
|
25
|
+
icon: JSX.Element;
|
|
26
|
+
/**
|
|
27
|
+
* Accessible name for the button.
|
|
28
|
+
*/
|
|
29
|
+
ariaLabel: string;
|
|
30
|
+
/**
|
|
31
|
+
* Called when the action is activated.
|
|
32
|
+
*
|
|
33
|
+
* @param item The item that was active when the action fired.
|
|
34
|
+
* @param index Zero-based index of that item in the `items` array.
|
|
35
|
+
*/
|
|
36
|
+
onClick: (item: FullscreenImageCarouselItemProps, index: number) => void;
|
|
37
|
+
"data-testid"?: string | undefined;
|
|
38
|
+
}
|
|
20
39
|
/**
|
|
21
40
|
* Props for the `FullscreenImageCarousel`component.
|
|
22
41
|
*/
|
|
@@ -54,6 +73,13 @@ export interface FullscreenImageCarouselProps extends Pick<ModalV2Props, "show"
|
|
|
54
73
|
* @default false
|
|
55
74
|
*/
|
|
56
75
|
hideMagnifier?: boolean | undefined;
|
|
76
|
+
/**
|
|
77
|
+
* Additional icon buttons rendered in the top bar, positioned before the
|
|
78
|
+
* default buttons. Applies to every item.
|
|
79
|
+
*
|
|
80
|
+
* An item's own `customActions` replaces this list for that item.
|
|
81
|
+
*/
|
|
82
|
+
customActions?: FullscreenImageCarouselCustomAction[] | undefined;
|
|
57
83
|
/**
|
|
58
84
|
* Called when the delete button is activated for the current item.
|
|
59
85
|
*
|
|
@@ -68,6 +94,10 @@ export interface FullscreenImageCarouselProps extends Pick<ModalV2Props, "show"
|
|
|
68
94
|
* of the viewport and avoid overlap with device UI elements.
|
|
69
95
|
*/
|
|
70
96
|
insets?: Insets | undefined;
|
|
97
|
+
/**
|
|
98
|
+
* Ref to the top bar element, which holds the file info and the action buttons.
|
|
99
|
+
*/
|
|
100
|
+
topBarRef?: React.Ref<HTMLDivElement> | undefined;
|
|
71
101
|
}
|
|
72
102
|
interface FullscreenImageCarouselBaseItemProps {
|
|
73
103
|
/**
|
|
@@ -79,6 +109,13 @@ interface FullscreenImageCarouselBaseItemProps {
|
|
|
79
109
|
* info bar (e.g. "2.4 MB").
|
|
80
110
|
*/
|
|
81
111
|
fileSize?: string | undefined;
|
|
112
|
+
/**
|
|
113
|
+
* Replaces the component-level `customActions` while this item is active.
|
|
114
|
+
*
|
|
115
|
+
* Leave `undefined` to inherit the component-level list. Pass `[]` to
|
|
116
|
+
* render no custom actions for this item.
|
|
117
|
+
*/
|
|
118
|
+
customActions?: FullscreenImageCarouselCustomAction[] | undefined;
|
|
82
119
|
}
|
|
83
120
|
/**
|
|
84
121
|
* A standard image item rendered inside the carousel slide.
|
package/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{Accordion}from"./accordion/accordion.js";export{Alert}from"./alert/alert.js";export{LoadingDots}from"./animations/loading-dots/loading-dots.js";export{LoadingDotsSpinner}from"./animations/loading-dots-spinner/loading-dots-spinner.js";export{LoadingSpinner}from"./animations/loading-spinner/loading-spinner.js";export{ThemedLoadingSpinner}from"./animations/themed-loading-spinner/themed-loading-spinner.js";export{Avatar}from"./avatar/avatar.js";export{Badge}from"./badge/badge.js";export{BoxContainer}from"./box-container/box-container.js";export{Breadcrumb}from"./breadcrumb/breadcrumb.js";export{Button}from"./button/button.js";export{Calendar}from"./calendar/calendar.js";export{Card}from"./card/card.js";export{Checkbox}from"./checkbox/checkbox.js";export{CountdownTimer}from"./countdown-timer/countdown-timer.js";export{DashedBorder}from"./dashed-border/dashed-border.js";export{DataTable}from"./data-table/data-table.js";export{DateInput}from"./date-input/date-input.js";export{DateNavigator}from"./date-navigator/date-navigator.js";export{DateRangeInput}from"./date-range-input/date-range-input.js";export{Divider}from"./divider/divider.js";export{Drawer}from"./drawer/drawer.js";export{ESignature}from"./e-signature/e-signature.js";export{ErrorDisplay}from"./error-display/error-display.js";export{ErrorDisplayHelper}from"./error-display/helper.js";export{FeedbackRating}from"./feedback-rating/feedback-rating.js";export{FileDownload}from"./file-download/file-download.js";export{FileUpload}from"./file-upload/file-upload.js";export{Filter}from"./filter/filter.js";export{Footer}from"./footer/footer.js";export{Form}from"./form/index.js";export{Component,FullscreenImageCarousel}from"./fullscreen-image-carousel/fullscreen-image-carousel.js";export{HistogramSlider}from"./histogram-slider/histogram-slider.js";export{ImageButton}from"./image-button/image-button.js";export{Input}from"./input/input.js";export{InputGroup}from"./input-group/input-group.js";export{InputMultiSelect}from"./input-multi-select/input-multi-select.js";export{InputNestedMultiSelect}from"./input-nested-multi-select/input-nested-multi-select.js";export{InputNestedSelect}from"./input-nested-select/input-nested-select.js";export{InputRangeSelect}from"./input-range-select/input-range-select.js";export{InputRangeSlider}from"./input-range-slider/input-range-slider.js";export{InputSelect}from"./input-select/input-select.js";export{InputSlider}from"./input-slider/input-slider.js";export{Textarea}from"./input-textarea/textarea.js";export{LanguageSwitcher}from"./language-switcher/language-switcher.js";export{Layout}from"./layout/index.js";export{LinkList}from"./link-list/link-list.js";export{Markup}from"./markup/markup.js";export{MaskedInput}from"./masked-input/masked-input.js";export{Masthead}from"./masthead/masthead.js";export{Menu,MenuTrigger}from"./menu/menu.js";export{Modal}from"./modal/index.js";export{ModalV2}from"./modal-v2/modal-v2.js";export{Navbar}from"./navbar/navbar.js";export{NBComponent,NotificationBanner}from"./notification-banner/notification-banner.js";export{withNotificationBanner}from"./notification-banner/notification-banner-hoc.js";export{OtpInput}from"./otp-input/otp-input.js";export{Overlay}from"./overlay/overlay.js";export{Pagination}from"./pagination/pagination.js";export{PhoneNumberInput}from"./phone-number-input/phone-number-input.js";export{Pill}from"./pill/pill.js";export{Popover}from"./popover/popover.js";export{PopoverInline}from"./popover/popover-inline/popover-inline.js";export{PopoverTrigger}from"./popover/popover-trigger.js";export{PredictiveTextInput}from"./predictive-text-input/predictive-text-input.js";export{ProgressIndicator}from"./progress-indicator/progress-indicator.js";export{RadioButton}from"./radio-button/radio-button.js";export{SelectHistogram}from"./select-histogram/select-histogram.js";export{Sidenav}from"./sidenav/sidenav.js";export{SingpassButton}from"./singpass-button/singpass-button.js";export{SmartAppBanner}from"./smart-app-banner/smart-app-banner.js";export{Tab}from"./tab/tab.js";export{Table}from"./table/table.js";export{Tag}from"./tag/tag.js";export{TextList}from"./text-list/index.js";export{ThemeProvider}from"./theme/theme-provider/index.js";export{useInheritedThemeScope,useTheme}from"./theme/theme-provider/hooks.js";export{Border,BorderStyle,BorderThickness}from"./theme/tokens/border.js";export{Breakpoint}from"./theme/tokens/breakpoint.js";export{Colour,PrimitiveColours,SemanticColours}from"./theme/tokens/colour.js";export{ComponentToken}from"./theme/tokens/component.js";export{Font,FontSpec}from"./theme/tokens/font.js";export{MediaQuery}from"./theme/tokens/media-query.js";export{Motion}from"./theme/tokens/motion.js";export{Radius}from"./theme/tokens/radius.js";export{Shadow}from"./theme/tokens/shadow.js";export{Spacing}from"./theme/tokens/spacing.js";export{THEME_TYPES}from"./theme/types.js";export{formatUnitValue,parsePxOrRemValue}from"./theme/utils/css-variable.js";export{useApplyStyle}from"./theme/utils/use-apply-styles.js";export{useDesignToken}from"./theme/utils/use-design-token.js";export{useMaxWidthMediaQuery,useMediaQuery,useMinWidthMediaQuery,useResolvedBreakpointToken}from"./theme/utils/use-media-query.js";export{TimeRangePicker}from"./time-range-picker/time-range-picker.js";export{TimeSlotBar}from"./time-slot-bar/time-slot-bar.js";export{TimeSlotBarWeek}from"./time-slot-bar-week/time-slot-bar-week.js";export{TimeSlotWeekView}from"./time-slot-week-view/time-slot-week-view.js";export{Timeline}from"./timeline/timeline.js";export{Timepicker}from"./timepicker/timepicker.js";export{TimeTable}from"./timetable/timetable.js";export{Toast}from"./toast/toast.js";export{Toggle}from"./toggle/toggle.js";export{Typography}from"./typography/index.js";export{UneditableSection}from"./uneditable-section/index.js";export{UnitNumberInput}from"./unit-number/unit-number-input.js";
|
|
1
|
+
export{Accordion}from"./accordion/accordion.js";export{Alert}from"./alert/alert.js";export{LoadingDots}from"./animations/loading-dots/loading-dots.js";export{LoadingDotsSpinner}from"./animations/loading-dots-spinner/loading-dots-spinner.js";export{LoadingSpinner}from"./animations/loading-spinner/loading-spinner.js";export{ThemedLoadingSpinner}from"./animations/themed-loading-spinner/themed-loading-spinner.js";export{Avatar}from"./avatar/avatar.js";export{Badge}from"./badge/badge.js";export{BoxContainer}from"./box-container/box-container.js";export{Breadcrumb}from"./breadcrumb/breadcrumb.js";export{Button}from"./button/button.js";export{Calendar}from"./calendar/calendar.js";export{Card}from"./card/card.js";export{Checkbox}from"./checkbox/checkbox.js";export{CountdownTimer}from"./countdown-timer/countdown-timer.js";export{DashedBorder}from"./dashed-border/dashed-border.js";export{DataTable}from"./data-table/data-table.js";export{DateInput}from"./date-input/date-input.js";export{DateNavigator}from"./date-navigator/date-navigator.js";export{DateRangeInput}from"./date-range-input/date-range-input.js";export{Divider}from"./divider/divider.js";export{Drawer}from"./drawer/drawer.js";export{ESignature}from"./e-signature/e-signature.js";export{ErrorDisplay}from"./error-display/error-display.js";export{ErrorDisplayHelper}from"./error-display/helper.js";export{FeedbackRating}from"./feedback-rating/feedback-rating.js";export{FileDownload}from"./file-download/file-download.js";export{FileUpload}from"./file-upload/file-upload.js";export{Filter}from"./filter/filter.js";export{Footer}from"./footer/footer.js";export{Form}from"./form/index.js";export{Component,FullscreenImageCarousel}from"./fullscreen-image-carousel/fullscreen-image-carousel.js";export{HistogramSlider}from"./histogram-slider/histogram-slider.js";export{ImageButton}from"./image-button/image-button.js";export{Input}from"./input/input.js";export{InputGroup}from"./input-group/input-group.js";export{InputMultiSelect}from"./input-multi-select/input-multi-select.js";export{InputNestedMultiSelect}from"./input-nested-multi-select/input-nested-multi-select.js";export{InputNestedSelect}from"./input-nested-select/input-nested-select.js";export{InputRangeSelect}from"./input-range-select/input-range-select.js";export{InputRangeSlider}from"./input-range-slider/input-range-slider.js";export{InputSelect}from"./input-select/input-select.js";export{InputSlider}from"./input-slider/input-slider.js";export{Textarea}from"./input-textarea/textarea.js";export{LanguageSwitcher}from"./language-switcher/language-switcher.js";export{Layout}from"./layout/index.js";export{LinkList}from"./link-list/link-list.js";export{Markup}from"./markup/markup.js";export{MaskedInput}from"./masked-input/masked-input.js";export{Masthead}from"./masthead/masthead.js";export{Menu,MenuTrigger}from"./menu/menu.js";export{Modal}from"./modal/index.js";export{ModalV2}from"./modal-v2/modal-v2.js";export{Navbar}from"./navbar/navbar.js";export{NBComponent,NotificationBanner}from"./notification-banner/notification-banner.js";export{withNotificationBanner}from"./notification-banner/notification-banner-hoc.js";export{OtpInput}from"./otp-input/otp-input.js";export{Overlay}from"./overlay/overlay.js";export{Pagination}from"./pagination/pagination.js";export{PhoneNumberInput}from"./phone-number-input/phone-number-input.js";export{Pill}from"./pill/pill.js";export{Popover}from"./popover/popover.js";export{PopoverInline}from"./popover/popover-inline/popover-inline.js";export{PopoverTrigger}from"./popover/popover-trigger.js";export{PredictiveTextInput}from"./predictive-text-input/predictive-text-input.js";export{ProgressIndicator}from"./progress-indicator/progress-indicator.js";export{RadioButton}from"./radio-button/radio-button.js";export{SelectHistogram}from"./select-histogram/select-histogram.js";export{Sidenav}from"./sidenav/sidenav.js";export{SingpassButton}from"./singpass-button/singpass-button.js";export{SmartAppBanner}from"./smart-app-banner/smart-app-banner.js";export{Tab}from"./tab/tab.js";export{Table}from"./table/table.js";export{Tag}from"./tag/tag.js";export{TextList}from"./text-list/index.js";export{ThemeProvider}from"./theme/theme-provider/index.js";export{useInheritedThemeScope,useTheme}from"./theme/theme-provider/hooks.js";export{Border,BorderStyle,BorderThickness}from"./theme/tokens/border.js";export{Breakpoint}from"./theme/tokens/breakpoint.js";export{Colour,PrimitiveColours,SemanticColours}from"./theme/tokens/colour.js";export{ComponentToken}from"./theme/tokens/component.js";export{Font,FontSpec}from"./theme/tokens/font.js";export{MediaQuery}from"./theme/tokens/media-query.js";export{Motion}from"./theme/tokens/motion.js";export{Radius}from"./theme/tokens/radius.js";export{Shadow}from"./theme/tokens/shadow.js";export{Spacing}from"./theme/tokens/spacing.js";export{THEME_FONT_PRESETS,THEME_TYPES}from"./theme/types.js";export{formatUnitValue,parsePxOrRemValue}from"./theme/utils/css-variable.js";export{useApplyStyle}from"./theme/utils/use-apply-styles.js";export{useDesignToken}from"./theme/utils/use-design-token.js";export{useMaxWidthMediaQuery,useMediaQuery,useMinWidthMediaQuery,useResolvedBreakpointToken}from"./theme/utils/use-media-query.js";export{TimeRangePicker}from"./time-range-picker/time-range-picker.js";export{TimeSlotBar}from"./time-slot-bar/time-slot-bar.js";export{TimeSlotBarWeek}from"./time-slot-bar-week/time-slot-bar-week.js";export{TimeSlotWeekView}from"./time-slot-week-view/time-slot-week-view.js";export{Timeline}from"./timeline/timeline.js";export{Timepicker}from"./timepicker/timepicker.js";export{TimeTable}from"./timetable/timetable.js";export{Toast}from"./toast/toast.js";export{Toggle}from"./toggle/toggle.js";export{Typography}from"./typography/index.js";export{UneditableSection}from"./uneditable-section/index.js";export{UnitNumberInput}from"./unit-number/unit-number-input.js";
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/input-group/types.d.ts
CHANGED
|
@@ -55,7 +55,10 @@ export interface ListAddon<T, V> extends DropdownDisplayProps<T, V>, DropdownSea
|
|
|
55
55
|
onSelectOption?: ((option: T, extractedValue: T | V) => void) | undefined;
|
|
56
56
|
/** Indicates the async load state of the options list. */
|
|
57
57
|
optionsLoadState?: ItemsLoadStateType | undefined;
|
|
58
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Controls how long option labels are truncated when they overflow.
|
|
60
|
+
* Specify `"none"` to display option labels in full.
|
|
61
|
+
*/
|
|
59
62
|
optionTruncationType?: TruncateType | undefined;
|
|
60
63
|
/** Called when the user activates the retry action while `optionsLoadState` is `"fail"`. */
|
|
61
64
|
onRetry?: (() => void) | undefined;
|