@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
package/codemods/run-codemod.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { checkbox, confirm, input, select } from "@inquirer/prompts";
|
|
2
|
-
import {
|
|
2
|
+
import { execFileSync } from "child_process";
|
|
3
3
|
import * as fs from "fs";
|
|
4
4
|
import * as path from "path";
|
|
5
5
|
|
|
@@ -54,14 +54,23 @@ function runCodemods(selection: UserSelection): void {
|
|
|
54
54
|
|
|
55
55
|
selectedCodemods.forEach((codemod) => {
|
|
56
56
|
const codemodPath = path.join(codemodsDir, codemod, "index.ts");
|
|
57
|
-
let command = `npx --yes jscodeshift --parser=tsx -t ${codemodPath} ${targetPath}`;
|
|
58
|
-
|
|
59
57
|
console.log(
|
|
60
58
|
`Running codemod: ${codemod} on target path: ${targetPath}`
|
|
61
59
|
);
|
|
62
60
|
|
|
63
61
|
try {
|
|
64
|
-
|
|
62
|
+
execFileSync(
|
|
63
|
+
"npx",
|
|
64
|
+
[
|
|
65
|
+
"--yes",
|
|
66
|
+
"jscodeshift",
|
|
67
|
+
"--parser=tsx",
|
|
68
|
+
"-t",
|
|
69
|
+
codemodPath,
|
|
70
|
+
targetPath,
|
|
71
|
+
],
|
|
72
|
+
{ stdio: "inherit" }
|
|
73
|
+
);
|
|
65
74
|
console.log(
|
|
66
75
|
`Codemod ${codemod} executed successfully on ${targetPath}`
|
|
67
76
|
);
|
package/drawer/drawer.d.ts
CHANGED
|
@@ -7,4 +7,4 @@ import type { DrawerProps } from "./types";
|
|
|
7
7
|
* while it is open and returns to the triggering element on close.
|
|
8
8
|
* @keywords overlay, panel, side panel, tray
|
|
9
9
|
*/
|
|
10
|
-
export declare const Drawer: ({ children, heading, show, onClose, onOverlayClick, className, ...otherProps }: DrawerProps) => import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export declare const Drawer: ({ children, heading, show, onClose, onOverlayClick, customCallToAction, className, ...otherProps }: DrawerProps) => import("react/jsx-runtime").JSX.Element;
|
package/drawer/drawer.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{__rest as e}from"../_virtual/_tslib.js";import{jsx as r,jsxs as
|
|
1
|
+
import{__rest as e}from"../_virtual/_tslib.js";import{jsx as r,jsxs as t}from"react/jsx-runtime";import{useFloating as o,useDismiss as i,useInteractions as s,useTransitionStatus as a,FloatingFocusManager as l}from"@floating-ui/react";import{CrossIcon as n}from"@lifesg/react-icons/cross";import m from"clsx";import{useState as c,useRef as d,useEffect as p}from"react";import{useResizeDetector as h}from"../external/react-resize-detector/build/index.esm.js";import{Overlay as u}from"../overlay/overlay.js";import{ClickableIcon as f}from"../shared/clickable-icon/clickable-icon.js";import"../theme/theme-provider/index.js";import{parsePxOrRemValue as j}from"../theme/utils/css-variable.js";import"../theme/theme-provider/context.js";import"../theme/tokens/border.js";import{Breakpoint as v}from"../theme/tokens/breakpoint.js";import"../theme/tokens/colour.js";import"../theme/tokens/font.js";import"../theme/tokens/media-query.js";import"../util/calendar-helper.js";import"../external/dayjs/dayjs.min.js";import{useId as g}from"../util/simple-id-generator.js";import"../util/string-helper.js";import"@react-aria/live-announcer";import{useResolvedBreakpointToken as y}from"../theme/utils/use-media-query.js";import{Typography as b}from"../typography/index.js";import{container as k,heading as x,callToAction as C,callToActionStacked as N,header as w,headerStacked as O,content as T,closeButton as F}from"./drawer.styles.js";const H=H=>{var{children:M,heading:q,show:z,onClose:A,onOverlayClick:P,customCallToAction:R,className:_}=H,D=e(H,["children","heading","show","onClose","onOverlayClick","customCallToAction","className"]);const[E,I]=c(z),[K,Y]=c(),B=g(),G=d(null),{width:J,ref:L}=h({refreshMode:"throttle",refreshRate:300,onResize:()=>{const e=G.current;e&&Y(e.offsetTop+e.offsetHeight/2)}}),Q=j(y(v["sm-max"])),S=void 0!==J&&J<=Q,{context:U,refs:V}=o({open:z,onOpenChange:e=>{!e&&A&&A()}}),W=i(U,{escapeKey:!0,outsidePress:!1}),{getFloatingProps:X}=s([W]),{isMounted:Z,status:$}=a(U,{duration:800});p((()=>{if(!z){const e=setTimeout((()=>I(!1)),800);return()=>clearTimeout(e)}I(!0)}),[z]);return r(u,{show:E,enableOverlayClick:!0,onOverlayClick:P,children:Z?r(l,{context:U,initialFocus:-1,returnFocus:!0,children:t("div",Object.assign({ref:V.setFloating,"data-status":$,"data-testid":"drawer","aria-modal":!0,role:"dialog","aria-labelledby":B,onTransitionEnd:e=>{var r;"visibility"===e.propertyName&&z&&(null===(r=G.current)||void 0===r||r.focus())},className:m(k,_)},X(),D,{children:[t("div",{ref:L,className:m(w,S&&O),children:[r(b.HeadingMD,{as:"h2",className:x,id:B,ref:G,tabIndex:-1,weight:"bold",children:q}),R?r("div",{className:m(C,S&&N),children:R}):null]}),r("div",{className:T,children:M}),r(f,{"aria-label":"Close drawer",onClick:A,focusHighlight:!1,className:F,style:void 0!==K?{top:K,transform:"translateY(-50%)"}:void 0,children:r(n,{"aria-hidden":!0})})]}))}):void 0})};export{H as Drawer};
|
|
2
2
|
//# sourceMappingURL=drawer.js.map
|
package/drawer/drawer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawer.js","sources":["../../src/drawer/drawer.tsx"],"sourcesContent":["import {\n FloatingFocusManager,\n useDismiss,\n useFloating,\n useInteractions,\n useTransitionStatus,\n} from \"@floating-ui/react\";\nimport { CrossIcon } from \"@lifesg/react-icons/cross\";\nimport clsx from \"clsx\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { Overlay } from \"../overlay\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport { Typography } from \"../typography\";\nimport { useId } from \"../util\";\nimport * as styles from \"./drawer.styles\";\nimport type { DrawerProps } from \"./types\";\n\n// @catalog\n/**\n * A slide-in panel that overlays the page content.\n *\n * Use `Drawer` to surface supplementary content or navigation options without\n * navigating away from the current page. Focus is trapped inside the dialog\n * while it is open and returns to the triggering element on close.\n * @keywords overlay, panel, side panel, tray\n */\nexport const Drawer = ({\n children,\n heading,\n show,\n onClose,\n onOverlayClick,\n className,\n ...otherProps\n}: DrawerProps) => {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const [showOverlay, setShowOverlay] = useState(show);\n const id = useId();\n const initialFocusRef = useRef<HTMLHeadingElement>(null);\n\n // =========================================================================\n // FLOATING UI CONFIG\n // =========================================================================\n const { context, refs } = useFloating({\n open: show,\n onOpenChange: (open) => {\n if (!open && onClose) {\n onClose();\n }\n },\n });\n\n const dismiss = useDismiss(context, {\n escapeKey: true,\n outsidePress: false, // defer to Overlay click\n });\n\n const { getFloatingProps } = useInteractions([dismiss]);\n\n const { isMounted, status } = useTransitionStatus(context, {\n duration: 800,\n });\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n if (!show) {\n const timer = setTimeout(() => setShowOverlay(false), 800);\n return () => clearTimeout(timer);\n } else {\n setShowOverlay(true);\n }\n }, [show]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleDialogVisibility = (e: React.TransitionEvent) => {\n if (e.propertyName === \"visibility\" && show) {\n // focus the first element so that the screenreader enters the dialog\n initialFocusRef.current?.focus();\n }\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n return (\n <Overlay\n show={showOverlay}\n enableOverlayClick\n onOverlayClick={onOverlayClick}\n >\n {isMounted ? (\n <FloatingFocusManager\n context={context}\n initialFocus={-1}\n returnFocus={true}\n >\n <div\n ref={refs.setFloating}\n data-status={status}\n data-testid=\"drawer\"\n aria-modal\n role=\"dialog\"\n aria-labelledby={id}\n onTransitionEnd={handleDialogVisibility}\n className={clsx(styles.container, className)}\n {...getFloatingProps()}\n {...otherProps}\n >\n <div className={styles.header}>\n <Typography.HeadingMD\n as=\"h2\"\n className={styles.heading}\n id={id}\n ref={initialFocusRef}\n tabIndex={-1}\n weight=\"bold\"\n >\n {heading}\n </Typography.HeadingMD>\n </div>\n <div className={styles.content}>{children}</div>\n <ClickableIcon\n aria-label=\"Close drawer\"\n onClick={onClose}\n focusHighlight={false}\n className={styles.closeButton}\n >\n <CrossIcon aria-hidden />\n </ClickableIcon>\n </div>\n </FloatingFocusManager>\n ) : undefined}\n </Overlay>\n );\n};\n"],"names":["Drawer","_a","children","heading","show","onClose","onOverlayClick","className","otherProps","__rest","showOverlay","setShowOverlay","useState","id","useId","initialFocusRef","useRef","context","refs","useFloating","open","onOpenChange","dismiss","useDismiss","escapeKey","outsidePress","getFloatingProps","useInteractions","isMounted","status","useTransitionStatus","duration","useEffect","timer","setTimeout","clearTimeout","_jsx","Overlay","enableOverlayClick","FloatingFocusManager","initialFocus","returnFocus","_jsxs","ref","setFloating","role","onTransitionEnd","e","propertyName","current","focus","clsx","styles.container","styles.header","Typography","HeadingMD","as","styles.heading","tabIndex","weight","styles.content","ClickableIcon","onClick","focusHighlight","styles.closeButton","CrossIcon","undefined"],"mappings":"00BA2BO,MAAMA,EAAUC,IAAA,IAAAC,SACnBA,EAAQC,QACRA,EAAOC,KACPA,EAAIC,QACJA,EAAOC,eACPA,EAAcC,UACdA,GAASN,EACNO,EAAUC,EAAAR,EAPM,sEAYnB,MAAOS,EAAaC,GAAkBC,EAASR,GACzCS,EAAKC,IACLC,EAAkBC,EAA2B,OAK7CC,QAAEA,EAAOC,KAAEA,GAASC,EAAY,CAClCC,KAAMhB,EACNiB,aAAeD,KACNA,GAAQf,GACTA,GACJ,IAIFiB,EAAUC,EAAWN,EAAS,CAChCO,WAAW,EACXC,cAAc,KAGZC,iBAAEA,GAAqBC,EAAgB,CAACL,KAExCM,UAAEA,EAASC,OAAEA,GAAWC,EAAoBb,EAAS,CACvDc,SAAU,MAMdC,GAAU,KACN,IAAK5B,EAAM,CACP,MAAM6B,EAAQC,YAAW,IAAMvB,GAAe,IAAQ,KACtD,MAAO,IAAMwB,aAAaF,EAC9B,CACItB,GAAe,EACnB,GACD,CAACP,IAeJ,OACIgC,EAACC,EAAO,CACJjC,KAAMM,EACN4B,oBAAkB,EAClBhC,eAAgBA,EAAcJ,SAE7B0B,EACGQ,EAACG,EAAoB,CACjBtB,QAASA,EACTuB,cAAc,EACdC,aAAa,EAAIvC,SAEjBwC,uBACIC,IAAKzB,EAAK0B,YAAW,cACRf,EAAM,cACP,yBAEZgB,KAAK,SAAQ,kBACIhC,EACjBiC,gBA7BYC,UACL,eAAnBA,EAAEC,cAAiC5C,IAEZ,QAAvBH,EAAAc,EAAgBkC,eAAO,IAAAhD,GAAAA,EAAEiD,QAC7B,EA0BgB3C,UAAW4C,EAAKC,EAAkB7C,IAC9BmB,IACAlB,EAAU,CAAAN,SAAA,CAEdkC,EAAA,MAAA,CAAK7B,UAAW8C,EAAanD,SACzBkC,EAACkB,EAAWC,UAAS,CACjBC,GAAG,KACHjD,UAAWkD,EACX5C,GAAIA,EACJ8B,IAAK5B,EACL2C,UAAU,EACVC,OAAO,gBAENxD,MAGTiC,SAAK7B,UAAWqD,EAAc1D,SAAGA,IACjCkC,EAACyB,EAAa,CAAA,aACC,eACXC,QAASzD,EACT0D,gBAAgB,EAChBxD,UAAWyD,EAAkB9D,SAE7BkC,EAAC6B,EAAS,CAAA,eAAA,iBAItBC,GACE"}
|
|
1
|
+
{"version":3,"file":"drawer.js","sources":["../../src/drawer/drawer.tsx"],"sourcesContent":["import {\n FloatingFocusManager,\n useDismiss,\n useFloating,\n useInteractions,\n useTransitionStatus,\n} from \"@floating-ui/react\";\nimport { CrossIcon } from \"@lifesg/react-icons/cross\";\nimport clsx from \"clsx\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\n\nimport { Overlay } from \"../overlay\";\nimport { ClickableIcon } from \"../shared/clickable-icon\";\nimport {\n Breakpoint,\n parsePxOrRemValue,\n useResolvedBreakpointToken,\n} from \"../theme\";\nimport { Typography } from \"../typography\";\nimport { useId } from \"../util\";\nimport * as styles from \"./drawer.styles\";\nimport type { DrawerProps } from \"./types\";\n\n// @catalog\n/**\n * A slide-in panel that overlays the page content.\n *\n * Use `Drawer` to surface supplementary content or navigation options without\n * navigating away from the current page. Focus is trapped inside the dialog\n * while it is open and returns to the triggering element on close.\n * @keywords overlay, panel, side panel, tray\n */\nexport const Drawer = ({\n children,\n heading,\n show,\n onClose,\n onOverlayClick,\n customCallToAction,\n className,\n ...otherProps\n}: DrawerProps) => {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const [showOverlay, setShowOverlay] = useState(show);\n // vertical centre of the heading, used to align the (last-in-DOM,\n // absolutely positioned) close button with it\n const [closeButtonTop, setCloseButtonTop] = useState<number>();\n const id = useId();\n const initialFocusRef = useRef<HTMLHeadingElement>(null);\n // Observe the header (whose size tracks the drawer's actual width, which\n // consumers may override) to drive layout in one pass: the width decides\n // call-to-action stacking, and each resize re-centres the close button on\n // the heading. offsetTop/offsetHeight are relative to the drawer (the\n // positioned ancestor), so they share the close button's coordinate space.\n const { width: headerWidth, ref: headerRef } =\n useResizeDetector<HTMLDivElement>({\n refreshMode: \"throttle\",\n refreshRate: 300,\n onResize: () => {\n const headingEl = initialFocusRef.current;\n if (headingEl) {\n setCloseButtonTop(\n headingEl.offsetTop + headingEl.offsetHeight / 2\n );\n }\n },\n });\n // stack the call-to-action below the heading once the drawer is too narrow\n // to fit both on one line\n const stackWidth = parsePxOrRemValue(\n useResolvedBreakpointToken(Breakpoint[\"sm-max\"])\n );\n const stackCallToAction =\n headerWidth !== undefined && headerWidth <= stackWidth;\n\n // =========================================================================\n // FLOATING UI CONFIG\n // =========================================================================\n const { context, refs } = useFloating({\n open: show,\n onOpenChange: (open) => {\n if (!open && onClose) {\n onClose();\n }\n },\n });\n\n const dismiss = useDismiss(context, {\n escapeKey: true,\n outsidePress: false, // defer to Overlay click\n });\n\n const { getFloatingProps } = useInteractions([dismiss]);\n\n const { isMounted, status } = useTransitionStatus(context, {\n duration: 800,\n });\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n if (!show) {\n const timer = setTimeout(() => setShowOverlay(false), 800);\n return () => clearTimeout(timer);\n } else {\n setShowOverlay(true);\n }\n }, [show]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleDialogVisibility = (e: React.TransitionEvent) => {\n if (e.propertyName === \"visibility\" && show) {\n // focus the first element so that the screenreader enters the dialog\n initialFocusRef.current?.focus();\n }\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n return (\n <Overlay\n show={showOverlay}\n enableOverlayClick\n onOverlayClick={onOverlayClick}\n >\n {isMounted ? (\n <FloatingFocusManager\n context={context}\n initialFocus={-1}\n returnFocus={true}\n >\n <div\n ref={refs.setFloating}\n data-status={status}\n data-testid=\"drawer\"\n aria-modal\n role=\"dialog\"\n aria-labelledby={id}\n onTransitionEnd={handleDialogVisibility}\n className={clsx(styles.container, className)}\n {...getFloatingProps()}\n {...otherProps}\n >\n <div\n ref={headerRef}\n className={clsx(\n styles.header,\n stackCallToAction && styles.headerStacked\n )}\n >\n <Typography.HeadingMD\n as=\"h2\"\n className={styles.heading}\n id={id}\n ref={initialFocusRef}\n tabIndex={-1}\n weight=\"bold\"\n >\n {heading}\n </Typography.HeadingMD>\n {customCallToAction ? (\n <div\n className={clsx(\n styles.callToAction,\n stackCallToAction &&\n styles.callToActionStacked\n )}\n >\n {customCallToAction}\n </div>\n ) : null}\n </div>\n <div className={styles.content}>{children}</div>\n {/* Rendered last so assistive tech reaches the heading\n and content before the close button; centred against\n the header via its measured height. */}\n <ClickableIcon\n aria-label=\"Close drawer\"\n onClick={onClose}\n focusHighlight={false}\n className={styles.closeButton}\n style={\n closeButtonTop !== undefined\n ? {\n top: closeButtonTop,\n transform: \"translateY(-50%)\",\n }\n : undefined\n }\n >\n <CrossIcon aria-hidden />\n </ClickableIcon>\n </div>\n </FloatingFocusManager>\n ) : undefined}\n </Overlay>\n );\n};\n"],"names":["Drawer","_a","children","heading","show","onClose","onOverlayClick","customCallToAction","className","otherProps","__rest","showOverlay","setShowOverlay","useState","closeButtonTop","setCloseButtonTop","id","useId","initialFocusRef","useRef","width","headerWidth","ref","headerRef","useResizeDetector","refreshMode","refreshRate","onResize","headingEl","current","offsetTop","offsetHeight","stackWidth","parsePxOrRemValue","useResolvedBreakpointToken","Breakpoint","stackCallToAction","undefined","context","refs","useFloating","open","onOpenChange","dismiss","useDismiss","escapeKey","outsidePress","getFloatingProps","useInteractions","isMounted","status","useTransitionStatus","duration","useEffect","timer","setTimeout","clearTimeout","_jsx","Overlay","enableOverlayClick","FloatingFocusManager","initialFocus","returnFocus","_jsxs","Object","assign","setFloating","role","onTransitionEnd","e","propertyName","focus","clsx","styles.container","styles.header","styles.headerStacked","Typography","HeadingMD","as","styles.heading","tabIndex","weight","styles.callToAction","styles.callToActionStacked","styles.content","ClickableIcon","onClick","focusHighlight","styles.closeButton","style","top","transform","CrossIcon"],"mappings":"64CAiCO,MAAMA,EAAUC,IAAA,IAAAC,SACnBA,UACAC,EAAOC,KACPA,EAAIC,QACJA,EAAOC,eACPA,EAAcC,mBACdA,EAAkBC,UAClBA,GAASP,EACNQ,EAAUC,EAAAT,EARM,2FAanB,MAAOU,EAAaC,GAAkBC,EAAST,IAGxCU,EAAgBC,GAAqBF,IACtCG,EAAKC,IACLC,EAAkBC,EAA2B,OAM3CC,MAAOC,EAAaC,IAAKC,GAC7BC,EAAkC,CAC9BC,YAAa,WACbC,YAAa,IACbC,SAAU,KACN,MAAMC,EAAYV,EAAgBW,QAC9BD,GACAb,EACIa,EAAUE,UAAYF,EAAUG,aAAe,EAEvD,IAKNC,EAAaC,EACfC,EAA2BC,EAAW,YAEpCC,OACcC,IAAhBhB,GAA6BA,GAAeW,GAK1CM,QAAEA,EAAOC,KAAEA,GAASC,EAAY,CAClCC,KAAMrC,EACNsC,aAAeD,KACNA,GAAQpC,GACTA,GACJ,IAIFsC,EAAUC,EAAWN,EAAS,CAChCO,WAAW,EACXC,cAAc,KAGZC,iBAAEA,GAAqBC,EAAgB,CAACL,KAExCM,UAAEA,EAASC,OAAEA,GAAWC,EAAoBb,EAAS,CACvDc,SAAU,MAMdC,GAAU,KACN,IAAKjD,EAAM,CACP,MAAMkD,EAAQC,YAAW,IAAM3C,GAAe,IAAQ,KACtD,MAAO,IAAM4C,aAAaF,EAC9B,CACI1C,GAAe,EACnB,GACD,CAACR,IAeJ,OACIqD,EAACC,EAAO,CACJtD,KAAMO,EACNgD,oBAAkB,EAClBrD,eAAgBA,WAEf2C,EACGQ,EAACG,EAAoB,CACjBtB,QAASA,EACTuB,gBACAC,aAAa,EAAI5D,SAEjB6D,EAAA,MAAAC,OAAAC,OAAA,CACI3C,IAAKiB,EAAK2B,YAAW,cACRhB,EAAM,cACP,SAAQ,cAAA,EAEpBiB,KAAK,2BACYnD,EACjBoD,gBA7BYC,UACL,eAAnBA,EAAEC,cAAiClE,IAEZ,QAAvBH,EAAAiB,EAAgBW,eAAO,IAAA5B,GAAAA,EAAEsE,QAC7B,EA0BgB/D,UAAWgE,EAAKC,EAAkBjE,IAC9BuC,IACAtC,EAAU,CAAAP,SAAA,CAEd6D,EAAA,MAAA,CACIzC,IAAKC,EACLf,UAAWgE,EACPE,EACAtC,GAAqBuC,GACxBzE,SAAA,CAEDuD,EAACmB,EAAWC,UAAS,CACjBC,GAAG,KACHtE,UAAWuE,EACX/D,GAAIA,EACJM,IAAKJ,EACL8D,UAAU,EACVC,OAAO,OAAM/E,SAEZC,IAEJI,EACGkD,EAAA,MAAA,CACIjD,UAAWgE,EACPU,EACA9C,GACI+C,GACPjF,SAEAK,IAEL,QAERkD,SAAKjD,UAAW4E,EAAclF,SAAGA,IAIjCuD,EAAC4B,EAAa,CAAA,aACC,eACXC,QAASjF,EACTkF,gBAAgB,EAChB/E,UAAWgF,EACXC,WACuBpD,IAAnBvB,EACM,CACI4E,IAAK5E,EACL6E,UAAW,yBAEftD,EAASnC,SAGnBuD,EAACmC,mCAIbvD,GACE"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export declare const container: import("@linaria/core").LinariaClassName;
|
|
2
2
|
export declare const header: import("@linaria/core").LinariaClassName;
|
|
3
|
+
export declare const headerStacked: import("@linaria/core").LinariaClassName;
|
|
4
|
+
export declare const callToAction: import("@linaria/core").LinariaClassName;
|
|
5
|
+
export declare const callToActionStacked: import("@linaria/core").LinariaClassName;
|
|
3
6
|
export declare const closeButton: import("@linaria/core").LinariaClassName;
|
|
4
7
|
export declare const heading: import("@linaria/core").LinariaClassName;
|
|
5
8
|
export declare const content: import("@linaria/core").LinariaClassName;
|
package/drawer/drawer.styles.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"./drawer.
|
|
1
|
+
import"./drawer.styles_a4bwe0.css";const c="c1agands",r="h1kc1wos",s="h1njxz6r",a="ccrz6mg",e="c2k10hw",o="cu0iil5",t="hdpobta",w="csm06gm";export{a as callToAction,e as callToActionStacked,o as closeButton,c as container,w as content,r as header,s as headerStacked,t as heading};
|
|
2
2
|
//# sourceMappingURL=drawer.styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawer.styles.js","sources":["../../src/drawer/drawer.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport {\n Border,\n Colour,\n Font,\n MediaQuery,\n Motion,\n Radius,\n Shadow,\n Spacing,\n} from \"../theme\";\n\nexport const container = css`\n position: fixed;\n top: 0;\n\n display: flex;\n flex-direction: column;\n\n height: 100%;\n width: 40%;\n overflow: hidden;\n\n background-color: ${Colour[\"bg\"]};\n box-shadow: ${Shadow[\"lg-subtle\"]};\n border-top-left-radius: ${Radius[\"md\"]};\n border-bottom-left-radius: ${Radius[\"md\"]};\n\n transition-property: right, visibility;\n\n &[data-status=\"initial\"] {\n right: -100%;\n visibility: hidden;\n }\n\n &[data-status=\"open\"] {\n transition-duration: ${Motion[\"duration-800\"]};\n transition-timing-function: ${Motion[\"ease-entrance\"]};\n right: 0;\n visibility: visible;\n }\n\n &[data-status=\"close\"] {\n transition-duration: ${Motion[\"duration-800\"]};\n transition-timing-function: ${Motion[\"ease-exit\"]};\n right: -100%;\n visibility: hidden;\n }\n\n ${MediaQuery.MaxWidth.xl} {\n width: 50%;\n min-width: 700px;\n }\n\n ${MediaQuery.MaxWidth.lg} {\n width: 100%;\n min-width: unset;\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n }\n`;\n\nexport const header = css`\n top: 0;\n display: flex;\n align-items: center;\n gap: ${Spacing[\"spacing-16\"]};\n padding: ${Spacing[\"spacing-32\"]} ${Spacing[\"spacing-16\"]}\n ${Spacing[\"spacing-16\"]}\n calc(${Font.Spec[\"heading-lh-md\"]} + ${Spacing[\"spacing-32\"]});\n background-color: ${Colour[\"bg\"]};\n border-bottom: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n gap: ${Spacing[\"spacing-8\"]};\n padding: ${Spacing[\"spacing-32\"]} ${Spacing[\"spacing-20\"]}\n ${Spacing[\"spacing-16\"]}\n calc(${Font.Spec[\"heading-lh-md\"]} + ${Spacing[\"spacing-24\"]});\n }\n`;\n\nexport const closeButton = css`\n color: ${Colour[\"icon\"]};\n padding: 0;\n position: absolute;\n top: ${Spacing[\"spacing-32\"]};\n left: ${Spacing[\"spacing-16\"]};\n &:active,\n &:focus {\n color: ${Colour[\"icon-hover\"]};\n }\n\n svg {\n height: ${Font.Spec[\"heading-lh-md\"]};\n width: ${Font.Spec[\"heading-lh-md\"]};\n }\n`;\n\nexport const heading = css`\n text-overflow: ellipsis;\n overflow: hidden;\n white-space: nowrap;\n`;\n\nexport const content = css`\n flex: 1;\n overflow-y: auto;\n`;\n"],"names":["container","header","closeButton","heading","content"],"mappings":"yDAaO,MAAMA,EAAS,WAkDTC,EAAM,
|
|
1
|
+
{"version":3,"file":"drawer.styles.js","sources":["../../src/drawer/drawer.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport {\n Border,\n Colour,\n Font,\n MediaQuery,\n Motion,\n Radius,\n Shadow,\n Spacing,\n} from \"../theme\";\n\nexport const container = css`\n position: fixed;\n top: 0;\n\n display: flex;\n flex-direction: column;\n\n height: 100%;\n width: 40%;\n overflow: hidden;\n\n background-color: ${Colour[\"bg\"]};\n box-shadow: ${Shadow[\"lg-subtle\"]};\n border-top-left-radius: ${Radius[\"md\"]};\n border-bottom-left-radius: ${Radius[\"md\"]};\n\n transition-property: right, visibility;\n\n &[data-status=\"initial\"] {\n right: -100%;\n visibility: hidden;\n }\n\n &[data-status=\"open\"] {\n transition-duration: ${Motion[\"duration-800\"]};\n transition-timing-function: ${Motion[\"ease-entrance\"]};\n right: 0;\n visibility: visible;\n }\n\n &[data-status=\"close\"] {\n transition-duration: ${Motion[\"duration-800\"]};\n transition-timing-function: ${Motion[\"ease-exit\"]};\n right: -100%;\n visibility: hidden;\n }\n\n ${MediaQuery.MaxWidth.xl} {\n width: 50%;\n min-width: 700px;\n }\n\n ${MediaQuery.MaxWidth.lg} {\n width: 100%;\n min-width: unset;\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n }\n`;\n\nexport const header = css`\n top: 0;\n display: flex;\n align-items: center;\n gap: ${Spacing[\"spacing-16\"]};\n padding: ${Spacing[\"spacing-32\"]} ${Spacing[\"spacing-16\"]}\n ${Spacing[\"spacing-16\"]}\n calc(${Font.Spec[\"heading-lh-md\"]} + ${Spacing[\"spacing-32\"]});\n background-color: ${Colour[\"bg\"]};\n border-bottom: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n gap: ${Spacing[\"spacing-8\"]};\n padding: ${Spacing[\"spacing-32\"]} ${Spacing[\"spacing-20\"]}\n ${Spacing[\"spacing-16\"]}\n calc(${Font.Spec[\"heading-lh-md\"]} + ${Spacing[\"spacing-24\"]});\n }\n`;\n\n// Stack the call-to-action below the heading when the drawer is too narrow\n// to fit both on one line.\nexport const headerStacked = css`\n flex-direction: column;\n align-items: stretch;\n gap: ${Spacing[\"spacing-16\"]};\n`;\n\nexport const callToAction = css`\n display: flex;\n margin-left: auto;\n`;\n\n// When stacked, flush left so the buttons line up with the heading (the\n// header's left padding already clears the close icon).\nexport const callToActionStacked = css`\n margin-left: 0;\n`;\n\nexport const closeButton = css`\n color: ${Colour[\"icon\"]};\n padding: 0;\n position: absolute;\n top: ${Spacing[\"spacing-32\"]};\n left: ${Spacing[\"spacing-16\"]};\n &:active,\n &:focus {\n color: ${Colour[\"icon-hover\"]};\n }\n\n svg {\n height: ${Font.Spec[\"heading-lh-md\"]};\n width: ${Font.Spec[\"heading-lh-md\"]};\n }\n`;\n\nexport const heading = css`\n text-overflow: ellipsis;\n overflow: hidden;\n white-space: nowrap;\n`;\n\nexport const content = css`\n flex: 1;\n overflow-y: auto;\n`;\n"],"names":["container","header","headerStacked","callToAction","callToActionStacked","closeButton","heading","content"],"mappings":"yDAaO,MAAMA,EAAS,WAkDTC,EAAM,WAqBNC,EAAa,WAMbC,EAAY,UAOZC,EAAmB,UAInBC,EAAW,UAiBXC,EAAO,UAMPC,EAAO"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
@layer fds{.c1agands{position:fixed;top:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;height:100%;width:40%;overflow:hidden;background-color:var(--fds-colour-bg);box-shadow:var(--fds-shadow-lg-subtle);border-top-left-radius:var(--fds-radius-md);border-bottom-left-radius:var(--fds-radius-md);transition-property:right,visibility;}.c1agands[data-status="initial"]{right:-100%;visibility:hidden;}.c1agands[data-status="open"]{transition-duration:var(--fds-motion-duration-800);transition-timing-function:var(--fds-motion-timing-ease-entrance);right:0;visibility:visible;}.c1agands[data-status="close"]{transition-duration:var(--fds-motion-duration-800);transition-timing-function:var(--fds-motion-timing-ease-exit);right:-100%;visibility:hidden;}:where(body.fds-breakpoint-xl-max) .c1agands{width:50%;min-width:700px;}:where(body.fds-breakpoint-lg-max) .c1agands{width:100%;min-width:unset;border-top-left-radius:0;border-bottom-left-radius:0;}
|
|
2
2
|
.h1kc1wos{top:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;gap:var(--fds-spacing-16);padding:var(--fds-spacing-32) var(--fds-spacing-16) var(--fds-spacing-16) calc(var(--fds-font-heading-lh-md) + var(--fds-spacing-32));background-color:var(--fds-colour-bg);border-bottom:var(--fds-border-width-010) var(--fds-border-style-solid) var(--fds-colour-border);}:where(body.fds-breakpoint-lg-max) .h1kc1wos{gap:var(--fds-spacing-8);padding:var(--fds-spacing-32) var(--fds-spacing-20) var(--fds-spacing-16) calc(var(--fds-font-heading-lh-md) + var(--fds-spacing-24));}
|
|
3
|
-
.
|
|
4
|
-
.
|
|
5
|
-
.c2k10hw{-
|
|
3
|
+
.h1njxz6r{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-align-items:stretch;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;gap:var(--fds-spacing-16);}
|
|
4
|
+
.ccrz6mg{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-left:auto;}
|
|
5
|
+
.c2k10hw{margin-left:0;}
|
|
6
|
+
.cu0iil5{color:var(--fds-colour-icon);padding:0;position:absolute;top:var(--fds-spacing-32);left:var(--fds-spacing-16);}.cu0iil5:active,.cu0iil5:focus{color:var(--fds-colour-icon-hover);}.cu0iil5 svg{height:var(--fds-font-heading-lh-md);width:var(--fds-font-heading-lh-md);}
|
|
7
|
+
.hdpobta{text-overflow:ellipsis;overflow:hidden;white-space:nowrap;}
|
|
8
|
+
.csm06gm{-webkit-flex:1;-ms-flex:1;flex:1;overflow-y:auto;}}
|
package/drawer/types.d.ts
CHANGED
|
@@ -23,4 +23,11 @@ export interface DrawerProps {
|
|
|
23
23
|
onClose?: (() => void) | undefined;
|
|
24
24
|
/** Called when the user clicks the background overlay. */
|
|
25
25
|
onOverlayClick?: (() => void) | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Optional element rendered in the header, e.g. a link or button.
|
|
28
|
+
*
|
|
29
|
+
* Sits beside the title on wider drawers, and wraps onto its own line
|
|
30
|
+
* below the title once the drawer is narrow.
|
|
31
|
+
*/
|
|
32
|
+
customCallToAction?: React.ReactNode | undefined;
|
|
26
33
|
}
|
|
@@ -6,4 +6,4 @@ import type { FileDownloadProps } from "./types";
|
|
|
6
6
|
* Each file item renders as a card with file metadata and a download trigger.
|
|
7
7
|
* @keywords attachment, document, download, file
|
|
8
8
|
*/
|
|
9
|
-
export declare const FileDownload: ({ id, fileItems, title, description, onDownload, "data-testid": testId, className, styleType, }: FileDownloadProps) => import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export declare const FileDownload: ({ id, fileItems, title, description, onDownload, onClick, "data-testid": testId, className, styleType, }: FileDownloadProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{__awaiter as e}from"../_virtual/_tslib.js";import{jsxs as r,jsx as t}from"react/jsx-runtime";import i from"clsx";import{DashedBorder as o}from"../dashed-border/dashed-border.js";import{Markup as s}from"../markup/markup.js";import"../theme/theme-provider/index.js";import"react";import"../theme/theme-provider/context.js";import{Border as m}from"../theme/tokens/border.js";import{Colour as d}from"../theme/tokens/colour.js";import"../theme/tokens/font.js";import"../theme/tokens/media-query.js";import{Radius as l}from"../theme/tokens/radius.js";import"../util/calendar-helper.js";import"../external/dayjs/dayjs.min.js";import"../util/simple-id-generator.js";import"../util/string-helper.js";import"@react-aria/live-announcer";import"../theme/utils/use-media-query.js";import{textContainer as a,listWrapper as n,container as p,containerBordered as c,title as h,titleContainer as f,description as u,descriptionContainer as j}from"./file-download.styles.js";import{FileListCard as b}from"./file-list-card/file-list-card.js";const y=({id:y,fileItems:
|
|
1
|
+
import{__awaiter as e}from"../_virtual/_tslib.js";import{jsxs as r,jsx as t}from"react/jsx-runtime";import i from"clsx";import{DashedBorder as o}from"../dashed-border/dashed-border.js";import{Markup as s}from"../markup/markup.js";import"../theme/theme-provider/index.js";import"react";import"../theme/theme-provider/context.js";import{Border as m}from"../theme/tokens/border.js";import{Colour as d}from"../theme/tokens/colour.js";import"../theme/tokens/font.js";import"../theme/tokens/media-query.js";import{Radius as l}from"../theme/tokens/radius.js";import"../util/calendar-helper.js";import"../external/dayjs/dayjs.min.js";import"../util/simple-id-generator.js";import"../util/string-helper.js";import"@react-aria/live-announcer";import"../theme/utils/use-media-query.js";import{textContainer as a,listWrapper as n,container as p,containerBordered as c,title as h,titleContainer as f,description as u,descriptionContainer as j}from"./file-download.styles.js";import{FileListCard as b}from"./file-list-card/file-list-card.js";const y=({id:y,fileItems:k,title:x,description:v,onDownload:N,onClick:g,"data-testid":w,className:T,styleType:q="bordered"})=>{const z=r=>e(void 0,void 0,void 0,(function*(){N&&(yield N(r))})),C="bordered"===q;return r(o,{id:y?`${y}-file-download`:"file-download",className:i(p,C&&c,T),"data-testid":w,enabled:C,thickness:m["width-040"],radius:l.sm,colour:d.border,children:[(x||v)&&r("div",{className:a,children:[x?"string"==typeof x?t("p",{className:h,children:x}):t(s,{className:f,baseTextSize:"heading-xs",children:x}):null,v?"string"==typeof v?t("p",{className:u,children:v}):t(s,{className:j,baseTextSize:"body-md",children:v}):null]}),t("ul",{className:n,children:k&&k.length>0&&k.map((e=>t(b,{fileItem:e,onDownload:z,onClick:g},e.id)))})]})};export{y as FileDownload};
|
|
2
2
|
//# sourceMappingURL=file-download.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-download.js","sources":["../../src/file-download/file-download.tsx"],"sourcesContent":["import clsx from \"clsx\";\n\nimport { DashedBorder } from \"../dashed-border\";\nimport { Markup } from \"../markup\";\nimport { Border, Colour, Radius } from \"../theme\";\nimport * as styles from \"./file-download.styles\";\nimport { FileListCard } from \"./file-list-card\";\nimport type { FileDownloadProps, FileItemDownloadProps } from \"./types\";\n\n// @catalog\n/**\n * Displays a list of downloadable files, optionally grouped under a title and description.\n *\n * Use `FileDownload` to present one or more files that users can download individually.\n * Each file item renders as a card with file metadata and a download trigger.\n * @keywords attachment, document, download, file\n */\nexport const FileDownload = ({\n id,\n fileItems,\n title,\n description,\n onDownload,\n \"data-testid\": testId,\n className,\n styleType = \"bordered\",\n}: FileDownloadProps) => {\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleDownloadItem = async (item: FileItemDownloadProps) => {\n if (onDownload) {\n await onDownload(item);\n }\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderTitle = () => {\n if (!title) {\n return null;\n }\n\n if (typeof title === \"string\") {\n return <p className={styles.title}>{title}</p>;\n }\n\n return (\n <Markup className={styles.titleContainer} baseTextSize=\"heading-xs\">\n {title}\n </Markup>\n );\n };\n\n const renderDescription = () => {\n if (!description) {\n return null;\n }\n\n if (typeof description === \"string\") {\n return <p className={styles.description}>{description}</p>;\n }\n\n return (\n <Markup\n className={styles.descriptionContainer}\n baseTextSize=\"body-md\"\n >\n {description}\n </Markup>\n );\n };\n\n const isBordered = styleType === \"bordered\";\n\n return (\n <DashedBorder\n id={id ? `${id}-file-download` : \"file-download\"}\n className={clsx(\n styles.container,\n isBordered && styles.containerBordered,\n className\n )}\n data-testid={testId}\n enabled={isBordered}\n thickness={Border[\"width-040\"]}\n radius={Radius[\"sm\"]}\n colour={Colour[\"border\"]}\n >\n {(title || description) && (\n <div className={styles.textContainer}>\n {renderTitle()}\n {renderDescription()}\n </div>\n )}\n <ul className={styles.listWrapper}>\n {fileItems &&\n fileItems.length > 0 &&\n fileItems.map((item) => (\n <FileListCard\n key={item.id}\n fileItem={item}\n onDownload={handleDownloadItem}\n />\n ))}\n </ul>\n </DashedBorder>\n );\n};\n"],"names":["FileDownload","id","fileItems","title","description","onDownload","testId","className","styleType","handleDownloadItem","item","__awaiter","isBordered","_jsxs","DashedBorder","clsx","styles.container","styles.containerBordered","enabled","thickness","Border","radius","Radius","colour","Colour","children","styles.textContainer","_jsx","styles.title","Markup","styles.titleContainer","baseTextSize","styles.description","styles.descriptionContainer","styles.listWrapper","length","map","FileListCard","fileItem"],"mappings":"ogCAiBO,MAAMA,EAAe,EACxBC,KACAC,YAASC,MACTA,EAAKC,YACLA,EACAC,
|
|
1
|
+
{"version":3,"file":"file-download.js","sources":["../../src/file-download/file-download.tsx"],"sourcesContent":["import clsx from \"clsx\";\n\nimport { DashedBorder } from \"../dashed-border\";\nimport { Markup } from \"../markup\";\nimport { Border, Colour, Radius } from \"../theme\";\nimport * as styles from \"./file-download.styles\";\nimport { FileListCard } from \"./file-list-card\";\nimport type { FileDownloadProps, FileItemDownloadProps } from \"./types\";\n\n// @catalog\n/**\n * Displays a list of downloadable files, optionally grouped under a title and description.\n *\n * Use `FileDownload` to present one or more files that users can download individually.\n * Each file item renders as a card with file metadata and a download trigger.\n * @keywords attachment, document, download, file\n */\nexport const FileDownload = ({\n id,\n fileItems,\n title,\n description,\n onDownload,\n onClick,\n \"data-testid\": testId,\n className,\n styleType = \"bordered\",\n}: FileDownloadProps) => {\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleDownloadItem = async (item: FileItemDownloadProps) => {\n if (onDownload) {\n await onDownload(item);\n }\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderTitle = () => {\n if (!title) {\n return null;\n }\n\n if (typeof title === \"string\") {\n return <p className={styles.title}>{title}</p>;\n }\n\n return (\n <Markup className={styles.titleContainer} baseTextSize=\"heading-xs\">\n {title}\n </Markup>\n );\n };\n\n const renderDescription = () => {\n if (!description) {\n return null;\n }\n\n if (typeof description === \"string\") {\n return <p className={styles.description}>{description}</p>;\n }\n\n return (\n <Markup\n className={styles.descriptionContainer}\n baseTextSize=\"body-md\"\n >\n {description}\n </Markup>\n );\n };\n\n const isBordered = styleType === \"bordered\";\n\n return (\n <DashedBorder\n id={id ? `${id}-file-download` : \"file-download\"}\n className={clsx(\n styles.container,\n isBordered && styles.containerBordered,\n className\n )}\n data-testid={testId}\n enabled={isBordered}\n thickness={Border[\"width-040\"]}\n radius={Radius[\"sm\"]}\n colour={Colour[\"border\"]}\n >\n {(title || description) && (\n <div className={styles.textContainer}>\n {renderTitle()}\n {renderDescription()}\n </div>\n )}\n <ul className={styles.listWrapper}>\n {fileItems &&\n fileItems.length > 0 &&\n fileItems.map((item) => (\n <FileListCard\n key={item.id}\n fileItem={item}\n onDownload={handleDownloadItem}\n onClick={onClick}\n />\n ))}\n </ul>\n </DashedBorder>\n );\n};\n"],"names":["FileDownload","id","fileItems","title","description","onDownload","onClick","testId","className","styleType","handleDownloadItem","item","__awaiter","isBordered","_jsxs","DashedBorder","clsx","styles.container","styles.containerBordered","enabled","thickness","Border","radius","Radius","colour","Colour","children","styles.textContainer","_jsx","styles.title","Markup","styles.titleContainer","baseTextSize","styles.description","styles.descriptionContainer","styles.listWrapper","length","map","FileListCard","fileItem"],"mappings":"ogCAiBO,MAAMA,EAAe,EACxBC,KACAC,YAASC,MACTA,EAAKC,YACLA,EACAC,aACAC,UACA,cAAeC,EACfC,YACAC,YAAY,eAKZ,MAAMC,EAA4BC,GAA+BC,OAAA,OAAA,OAAA,GAAA,YACzDP,UACMA,EAAWM,GAEzB,IAwCME,EAA2B,aAAdJ,EAEnB,OACIK,EAACC,GACGd,GAAIA,EAAK,GAAGA,kBAAqB,gBACjCO,UAAWQ,EACPC,EACAJ,GAAcK,EACdV,GACH,cACYD,EACbY,QAASN,EACTO,UAAWC,EAAO,aAClBC,OAAQC,EAAW,GACnBC,OAAQC,EAAe,OAACC,SAAA,EAEtBvB,GAASC,IACPU,SAAKN,UAAWmB,YAnDnBxB,EAIgB,iBAAVA,EACAyB,EAAA,IAAA,CAAGpB,UAAWqB,EAAYH,SAAGvB,IAIpCyB,EAACE,EAAM,CAACtB,UAAWuB,EAAuBC,aAAa,sBAClD7B,IATE,KAeNC,EAIsB,iBAAhBA,EACAwB,EAAA,IAAA,CAAGpB,UAAWyB,EAAkBP,SAAGtB,IAI1CwB,EAACE,EAAM,CACHtB,UAAW0B,EACXF,aAAa,mBAEZ5B,IAZE,QAuCPwB,QAAIpB,UAAW2B,WACVjC,GACGA,EAAUkC,OAAS,GACnBlC,EAAUmC,KAAK1B,GACXiB,EAACU,EAAY,CAETC,SAAU5B,EACVN,WAAYK,EACZJ,QAASA,GAHJK,EAAKV,UAOf"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { FileListItemProps } from "./types";
|
|
2
|
-
export declare const FileListCard: import("react").MemoExoticComponent<({ fileItem, onDownload }: FileListItemProps) => import("react/jsx-runtime").JSX.Element>;
|
|
2
|
+
export declare const FileListCard: import("react").MemoExoticComponent<({ fileItem, onDownload, onClick }: FileListItemProps) => import("react/jsx-runtime").JSX.Element>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{__awaiter as e}from"../../_virtual/_tslib.js";import{jsx as
|
|
1
|
+
import{__awaiter as e}from"../../_virtual/_tslib.js";import{jsx as t,jsxs as i,Fragment as r}from"react/jsx-runtime";import{DownloadIcon as a}from"@lifesg/react-icons";import{ExclamationCircleFillIcon as l}from"@lifesg/react-icons/exclamation-circle-fill";import o from"clsx";import{memo as s,useState as n,useRef as m,useEffect as c}from"react";import{Button as d}from"../../button/button.js";import{FileUploadHelper as p}from"../../file-upload/helper.js";import{VisuallyHidden as h}from"../../shared/accessibility/index.js";import{ImageWithFallback as u}from"../../shared/image-with-fallback/image-with-fallback.js";import"../../theme/theme-provider/index.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"../../util/calendar-helper.js";import"../../external/dayjs/dayjs.min.js";import"../../util/simple-id-generator.js";import{StringHelper as f}from"../../util/string-helper.js";import"@react-aria/live-announcer";import{useMaxWidthMediaQuery as y}from"../../theme/utils/use-media-query.js";import{item as b,box as j,boxError as g,extendedNameSection as v,contentSection as N,contentSectionHasThumbnail as k,cardButton as w,actionContainer as x,iconButton as C,thumbnailContainer as T,thumbnail as D,thumbnailPdf as $,nameSection as _,fileSizeSection as z,mobileErrorMessage as I,errorIcon as L,itemNameText as P,desktopErrorMessage as S}from"./file-list-card.styles.js";const q=s((({fileItem:s,onDownload:q,onClick:F})=>{const{id:R,name:U,mimeType:B,size:M,errorMessage:O,thumbnailImageDataUrl:A,truncateText:E=!0,ready:G=!0,clickLabel:H}=s,[J,K]=n(!1),[Q,V]=n(!1),W=p.formatFileSizeDisplay(M),X=p.resolveThumbnailDisplay(B,A),Y="none"!==X.type,Z=y("sm"),[ee,te]=n(),ie=m(null);c((()=>{ie.current&&te(Z?se(U):U)}),[U,Z]);const re=()=>e(void 0,void 0,void 0,(function*(){if(G&&!J){K(!0);try{V(!1),yield q(s)}catch(e){V(!0)}finally{K(!1)}}})),ae=()=>{G&&(F?F(s):re())},le=e=>{e.stopPropagation(),ae()},oe=e=>{e.stopPropagation(),re()},se=e=>{if(!E)return e;const t=ie&&ie.current?ie.current.getBoundingClientRect().width:0;return f.truncateTwoLines(e,t,16,1.5)},ne=()=>{if("none"===X.type)return null;const e="pdf-icon"===X.type;return t("div",{className:T,"data-testid":`${R}-thumbnail`,children:t(u,{className:o(D,e&&$),"data-testid":`${R}-thumbnail-image`,src:e?p.PDF_ICON_URL:X.src})})},me=()=>i(r,{children:[t("div",{className:_,children:i(r,{children:[t("div",{className:P,ref:ie,children:ee}),Q&&i("div",{className:S,children:[t(l,{className:L}),O||"Something went wrong"]})]})}),t("div",{className:z,children:W||"-"}),Q&&i("div",{className:I,children:[t(l,{className:L}),O||"Something went wrong"]})]});return t("li",{className:b,"data-testid":R,children:i("div",{className:o(j,Q&&g),onClick:ae,children:[i("div",{className:o(N,Y&&k),children:[ne(),Y?t("div",{className:v,children:me()}):me()]}),F?t(h,{children:t("button",{type:"button",className:w,"data-testid":`${R}-card-button`,"aria-label":null!=H?H:U,disabled:!G,onClick:le})}):null,t("div",{className:x,children:t(d,{className:C,"data-testid":`${R}-download-button`,type:"button",styleType:"light",sizeType:"small","aria-label":`download ${U}`,loading:J||!G,icon:t(a,{}),onClick:oe})})]})})}));export{q as FileListCard};
|
|
2
2
|
//# sourceMappingURL=file-list-card.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-list-card.js","sources":["../../../src/file-download/file-list-card/file-list-card.tsx"],"sourcesContent":["import { DownloadIcon } from \"@lifesg/react-icons\";\nimport { ExclamationCircleFillIcon } from \"@lifesg/react-icons/exclamation-circle-fill\";\nimport clsx from \"clsx\";\nimport { memo, useEffect, useRef, useState } from \"react\";\n\nimport { Button } from \"../../button\";\nimport { FileUploadHelper } from \"../../file-upload/helper\";\nimport { ImageWithFallback } from \"../../shared/image-with-fallback/image-with-fallback\";\nimport { useMaxWidthMediaQuery } from \"../../theme\";\nimport { StringHelper } from \"../../util\";\nimport * as styles from \"./file-list-card.styles\";\nimport type { FileListItemProps } from \"./types\";\n\nconst Component = ({ fileItem, onDownload }: FileListItemProps) => {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const {\n id,\n name,\n size,\n errorMessage,\n thumbnailImageDataUrl,\n truncateText = true,\n ready = true,\n } = fileItem;\n\n // Local variables\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [isError, setIsError] = useState<boolean>(false);\n const fileSize = FileUploadHelper.formatFileSizeDisplay(size);\n const isMobile = useMaxWidthMediaQuery(\"sm\");\n const [displayText, setDisplayText] = useState<string>();\n const containerRef = useRef<HTMLDivElement>(null);\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n if (!containerRef.current) return;\n if (isMobile) {\n setDisplayText(getTruncatedText(name));\n } else {\n setDisplayText(name);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [name, isMobile]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleDownload = async () => {\n if (!ready || isLoading) {\n return;\n }\n\n setIsLoading(true);\n try {\n setIsError(false);\n await onDownload(fileItem);\n } catch {\n setIsError(true);\n } finally {\n setIsLoading(false);\n }\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const getTruncatedText = (value: string) => {\n if (!truncateText) return value;\n\n const widthOfElement =\n containerRef && containerRef.current\n ? containerRef.current.getBoundingClientRect().width\n : 0;\n\n return StringHelper.truncateTwoLines(value, widthOfElement, 16, 1.5);\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderNameDescription = () => (\n <>\n <div className={styles.itemNameText} ref={containerRef}>\n {displayText}\n </div>\n {isError && (\n <div className={styles.desktopErrorMessage}>\n <ExclamationCircleFillIcon className={styles.errorIcon} />\n {errorMessage ? errorMessage : \"Something went wrong\"}\n </div>\n )}\n </>\n );\n\n const renderWithThumbnail = (thumbnailSrc: string) => (\n <>\n <div\n className={styles.thumbnailContainer}\n data-testid={`${id}-thumbnail`}\n >\n <ImageWithFallback\n className={styles.thumbnail}\n data-testid={`${id}-thumbnail-image`}\n src={thumbnailSrc}\n />\n </div>\n <div className={styles.extendedNameSection}>\n <div className={styles.nameSection}>\n {renderNameDescription()}\n </div>\n <div className={styles.fileSizeSection}>\n {fileSize ? fileSize : \"-\"}\n </div>\n {isError && (\n <div className={styles.mobileErrorMessage}>\n <ExclamationCircleFillIcon\n className={styles.errorIcon}\n />\n {errorMessage ? errorMessage : \"Something went wrong\"}\n </div>\n )}\n </div>\n </>\n );\n\n const renderDefault = () => (\n <>\n <div className={styles.nameSection}>{renderNameDescription()}</div>\n <div className={styles.fileSizeSection}>\n {fileSize ? fileSize : \"-\"}\n </div>\n {isError && (\n <div className={styles.mobileErrorMessage}>\n <ExclamationCircleFillIcon className={styles.errorIcon} />\n {errorMessage ? errorMessage : \"Something went wrong\"}\n </div>\n )}\n </>\n );\n\n const renderContents = () => {\n let content: JSX.Element;\n\n if (thumbnailImageDataUrl) {\n content = renderWithThumbnail(thumbnailImageDataUrl);\n } else {\n content = renderDefault();\n }\n\n return (\n <div\n className={clsx(\n styles.contentSection,\n !!thumbnailImageDataUrl && styles.contentSectionHasThumbnail\n )}\n >\n {content}\n </div>\n );\n };\n\n const renderActions = () => {\n return (\n <div className={styles.actionContainer}>\n <Button\n className={styles.iconButton}\n data-testid={`${id}-download-button`}\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`download ${name}`}\n loading={isLoading || !ready}\n icon={<DownloadIcon />}\n />\n </div>\n );\n };\n\n return (\n <li className={styles.item} data-testid={id}>\n <div\n className={clsx(styles.box, isError && styles.boxError)}\n onClick={handleDownload}\n >\n {renderContents()}\n {renderActions()}\n </div>\n </li>\n );\n};\n\nexport const FileListCard = memo(Component);\n"],"names":["FileListCard","memo","fileItem","onDownload","id","name","size","errorMessage","thumbnailImageDataUrl","truncateText","ready","isLoading","setIsLoading","useState","isError","setIsError","fileSize","FileUploadHelper","formatFileSizeDisplay","isMobile","useMaxWidthMediaQuery","displayText","setDisplayText","containerRef","useRef","useEffect","current","getTruncatedText","value","widthOfElement","getBoundingClientRect","width","StringHelper","truncateTwoLines","renderNameDescription","_jsxs","_Fragment","children","_jsx","className","styles.itemNameText","ref","styles.desktopErrorMessage","ExclamationCircleFillIcon","styles.errorIcon","styles.item","clsx","styles.box","styles.boxError","onClick","__awaiter","_a","content","styles.thumbnailContainer","ImageWithFallback","styles.thumbnail","src","styles.extendedNameSection","styles.nameSection","styles.fileSizeSection","styles.mobileErrorMessage","styles.contentSection","styles.contentSectionHasThumbnail","renderContents","styles.actionContainer","Button","styles.iconButton","type","styleType","sizeType","loading","icon","DownloadIcon"],"mappings":"q5CAaA,MAsLaA,EAAeC,GAtLV,EAAGC,WAAUC,iBAI3B,MAAMC,GACFA,EAAEC,KACFA,EAAIC,KACJA,EAAIC,aACJA,EAAYC,sBACZA,EAAqBC,aACrBA,GAAe,EAAIC,MACnBA,GAAQ,GACRR,GAGGS,EAAWC,GAAgBC,GAAkB,IAC7CC,EAASC,GAAcF,GAAkB,GAC1CG,EAAWC,EAAiBC,sBAAsBZ,GAClDa,EAAWC,EAAsB,OAChCC,EAAaC,GAAkBT,IAChCU,EAAeC,EAAuB,MAK5CC,GAAU,KACDF,EAAaG,SAEdJ,EADAH,EACeQ,EAAiBtB,GAEjBA,EACnB,GAED,CAACA,EAAMc,IAKV,MAmBMQ,EAAoBC,IACtB,IAAKnB,EAAc,OAAOmB,EAE1B,MAAMC,EACFN,GAAgBA,EAAaG,QACvBH,EAAaG,QAAQI,wBAAwBC,MAC7C,EAEV,OAAOC,EAAaC,iBAAiBL,EAAOC,EAAgB,GAAI,IAAI,EAMlEK,EAAwB,IAC1BC,EAAAC,EAAA,CAAAC,SAAA,CACIC,EAAA,MAAA,CAAKC,UAAWC,EAAqBC,IAAKlB,EAAYc,SACjDhB,IAEJP,GACGqB,EAAA,MAAA,CAAKI,UAAWG,EAA0BL,SAAA,CACtCC,EAACK,EAAyB,CAACJ,UAAWK,IACrCrC,GAA8B,6BA0F/C,OACI+B,EAAA,KAAA,CAAIC,UAAWM,EAAW,cAAezC,EAAEiC,SACvCF,SACII,UAAWO,EAAKC,EAAYjC,GAAWkC,GACvCC,QAvIW,IAAWC,OAAA,OAAA,OAAA,GAAA,YAC9B,GAAKxC,IAASC,EAAd,CAIAC,GAAa,GACb,IACIG,GAAW,SACLZ,EAAWD,EACrB,CAAE,MAAAiD,GACEpC,GAAW,EACf,SACIH,GAAa,EACjB,CAVA,CAWJ,IAyHmCyB,SAAA,CA1CZ,MACnB,IAAIe,EAQJ,OALIA,EAjDJjB,EAAAC,EAgDI5B,EAhDJ,CAAA6B,SAAA,CACIC,EAAA,MAAA,CACIC,UAAWc,EAAyB,cACvB,GAAGjD,uBAEhBkC,EAACgB,EAAiB,CACdf,UAAWgB,EAAgB,cACd,GAAGnD,oBAChBoD,IAyCsBhD,MAtC9B2B,EAAA,MAAA,CAAKI,UAAWkB,EAA0BpB,SAAA,CACtCC,EAAA,MAAA,CAAKC,UAAWmB,EAAkBrB,SAC7BH,MAELI,EAAA,MAAA,CAAKC,UAAWoB,EAAsBtB,SACjCrB,GAAsB,MAE1BF,GACGqB,EAAA,MAAA,CAAKI,UAAWqB,EAAyBvB,SAAA,CACrCC,EAACK,EAAyB,CACtBJ,UAAWK,IAEdrC,GAA8B,+BAQ/C,CAAA8B,SAAA,CACIC,EAAA,MAAA,CAAKC,UAAWmB,WAAqBxB,MACrCI,EAAA,MAAA,CAAKC,UAAWoB,EAAsBtB,SACjCrB,GAAsB,MAE1BF,GACGqB,EAAA,MAAA,CAAKI,UAAWqB,EAAyBvB,SAAA,CACrCC,EAACK,EAAyB,CAACJ,UAAWK,IACrCrC,GAA8B,6BAgBvC+B,SACIC,UAAWO,EACPe,IACErD,GAAyBsD,GAC9BzB,SAEAe,GACC,EA2BDW,GArBLzB,EAAA,MAAA,CAAKC,UAAWyB,EAAsB3B,SAClCC,EAAC2B,EAAM,CACH1B,UAAW2B,EAAiB,cACf,GAAG9D,oBAChB+D,KAAK,SACLC,UAAU,QACVC,SAAS,QAAO,aACJ,YAAYhE,IACxBiE,QAAS3D,IAAcD,EACvB6D,KAAMjC,EAACkC,EAAY,CAAA,WAe1B"}
|
|
1
|
+
{"version":3,"file":"file-list-card.js","sources":["../../../src/file-download/file-list-card/file-list-card.tsx"],"sourcesContent":["import { DownloadIcon } from \"@lifesg/react-icons\";\nimport { ExclamationCircleFillIcon } from \"@lifesg/react-icons/exclamation-circle-fill\";\nimport clsx from \"clsx\";\nimport { memo, useEffect, useRef, useState } from \"react\";\n\nimport { Button } from \"../../button\";\nimport { FileUploadHelper } from \"../../file-upload/helper\";\nimport { VisuallyHidden } from \"../../shared/accessibility\";\nimport { ImageWithFallback } from \"../../shared/image-with-fallback/image-with-fallback\";\nimport { useMaxWidthMediaQuery } from \"../../theme\";\nimport { StringHelper } from \"../../util\";\nimport * as styles from \"./file-list-card.styles\";\nimport type { FileListItemProps } from \"./types\";\n\nconst Component = ({ fileItem, onDownload, onClick }: FileListItemProps) => {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const {\n id,\n name,\n mimeType,\n size,\n errorMessage,\n thumbnailImageDataUrl,\n truncateText = true,\n ready = true,\n clickLabel,\n } = fileItem;\n\n // Local variables\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [isError, setIsError] = useState<boolean>(false);\n const fileSize = FileUploadHelper.formatFileSizeDisplay(size);\n const thumbnailDisplay = FileUploadHelper.resolveThumbnailDisplay(\n mimeType,\n thumbnailImageDataUrl\n );\n const hasThumbnail = thumbnailDisplay.type !== \"none\";\n const isMobile = useMaxWidthMediaQuery(\"sm\");\n const [displayText, setDisplayText] = useState<string>();\n const containerRef = useRef<HTMLDivElement>(null);\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n if (!containerRef.current) return;\n if (isMobile) {\n setDisplayText(getTruncatedText(name));\n } else {\n setDisplayText(name);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [name, isMobile]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleDownload = async () => {\n if (!ready || isLoading) {\n return;\n }\n\n setIsLoading(true);\n try {\n setIsError(false);\n await onDownload(fileItem);\n } catch {\n setIsError(true);\n } finally {\n setIsLoading(false);\n }\n };\n\n const handleCardClick = () => {\n if (!ready) {\n return;\n }\n\n if (onClick) {\n onClick(fileItem);\n return;\n }\n\n handleDownload();\n };\n\n const handleCardButtonClick = (\n event: React.MouseEvent<HTMLButtonElement>\n ) => {\n /*\n * The button sits inside the container, which handles clicks too.\n * Without this both handlers fire and the action runs twice.\n */\n event.stopPropagation();\n handleCardClick();\n };\n\n const handleDownloadButtonClick = (\n event: React.MouseEvent<HTMLButtonElement>\n ) => {\n // Same reason: the container's handler must not also run.\n event.stopPropagation();\n handleDownload();\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const getTruncatedText = (value: string) => {\n if (!truncateText) return value;\n\n const widthOfElement =\n containerRef && containerRef.current\n ? containerRef.current.getBoundingClientRect().width\n : 0;\n\n return StringHelper.truncateTwoLines(value, widthOfElement, 16, 1.5);\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderNameDescription = () => (\n <>\n <div className={styles.itemNameText} ref={containerRef}>\n {displayText}\n </div>\n {isError && (\n <div className={styles.desktopErrorMessage}>\n <ExclamationCircleFillIcon className={styles.errorIcon} />\n {errorMessage ? errorMessage : \"Something went wrong\"}\n </div>\n )}\n </>\n );\n\n const renderThumbnail = () => {\n if (thumbnailDisplay.type === \"none\") {\n return null;\n }\n\n const isPdfBadge = thumbnailDisplay.type === \"pdf-icon\";\n\n return (\n <div\n className={styles.thumbnailContainer}\n data-testid={`${id}-thumbnail`}\n >\n <ImageWithFallback\n className={clsx(\n styles.thumbnail,\n isPdfBadge && styles.thumbnailPdf\n )}\n data-testid={`${id}-thumbnail-image`}\n src={\n isPdfBadge\n ? FileUploadHelper.PDF_ICON_URL\n : thumbnailDisplay.src\n }\n />\n </div>\n );\n };\n\n const renderNameSizeError = () => (\n <>\n <div className={styles.nameSection}>{renderNameDescription()}</div>\n <div className={styles.fileSizeSection}>\n {fileSize ? fileSize : \"-\"}\n </div>\n {isError && (\n <div className={styles.mobileErrorMessage}>\n <ExclamationCircleFillIcon className={styles.errorIcon} />\n {errorMessage ? errorMessage : \"Something went wrong\"}\n </div>\n )}\n </>\n );\n\n const renderContents = () => (\n <div\n className={clsx(\n styles.contentSection,\n hasThumbnail && styles.contentSectionHasThumbnail\n )}\n >\n {renderThumbnail()}\n {hasThumbnail ? (\n <div className={styles.extendedNameSection}>\n {renderNameSizeError()}\n </div>\n ) : (\n renderNameSizeError()\n )}\n </div>\n );\n\n const renderCardButton = () => {\n if (!onClick) {\n return null;\n }\n\n return (\n <VisuallyHidden>\n <button\n type=\"button\"\n className={styles.cardButton}\n data-testid={`${id}-card-button`}\n aria-label={clickLabel ?? name}\n disabled={!ready}\n onClick={handleCardButtonClick}\n />\n </VisuallyHidden>\n );\n };\n\n const renderActions = () => {\n return (\n <div className={styles.actionContainer}>\n <Button\n className={styles.iconButton}\n data-testid={`${id}-download-button`}\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`download ${name}`}\n loading={isLoading || !ready}\n icon={<DownloadIcon />}\n onClick={handleDownloadButtonClick}\n />\n </div>\n );\n };\n\n return (\n <li className={styles.item} data-testid={id}>\n <div\n className={clsx(styles.box, isError && styles.boxError)}\n onClick={handleCardClick}\n >\n {renderContents()}\n {renderCardButton()}\n {renderActions()}\n </div>\n </li>\n );\n};\n\nexport const FileListCard = memo(Component);\n"],"names":["FileListCard","memo","fileItem","onDownload","onClick","id","name","mimeType","size","errorMessage","thumbnailImageDataUrl","truncateText","ready","clickLabel","isLoading","setIsLoading","useState","isError","setIsError","fileSize","FileUploadHelper","formatFileSizeDisplay","thumbnailDisplay","resolveThumbnailDisplay","hasThumbnail","type","isMobile","useMaxWidthMediaQuery","displayText","setDisplayText","containerRef","useRef","useEffect","current","getTruncatedText","handleDownload","__awaiter","_a","handleCardClick","handleCardButtonClick","event","stopPropagation","handleDownloadButtonClick","value","widthOfElement","getBoundingClientRect","width","StringHelper","truncateTwoLines","renderThumbnail","isPdfBadge","_jsx","className","styles.thumbnailContainer","children","ImageWithFallback","clsx","styles.thumbnail","styles.thumbnailPdf","src","PDF_ICON_URL","renderNameSizeError","_jsxs","_Fragment","styles.nameSection","styles.itemNameText","ref","styles.desktopErrorMessage","ExclamationCircleFillIcon","styles.errorIcon","styles.fileSizeSection","styles.mobileErrorMessage","styles.item","styles.box","styles.boxError","styles.contentSection","styles.contentSectionHasThumbnail","styles.extendedNameSection","VisuallyHidden","styles.cardButton","disabled","styles.actionContainer","Button","styles.iconButton","styleType","sizeType","loading","icon","DownloadIcon"],"mappings":"4/CAcA,MA4OaA,EAAeC,GA5OV,EAAGC,WAAUC,aAAYC,cAIvC,MAAMC,GACFA,EAAEC,KACFA,EAAIC,SACJA,EAAQC,KACRA,EAAIC,aACJA,EAAYC,sBACZA,EAAqBC,aACrBA,GAAe,EAAIC,MACnBA,GAAQ,EAAIC,WACZA,GACAX,GAGGY,EAAWC,GAAgBC,GAAkB,IAC7CC,EAASC,GAAcF,GAAkB,GAC1CG,EAAWC,EAAiBC,sBAAsBb,GAClDc,EAAmBF,EAAiBG,wBACtChB,EACAG,GAEEc,EAAyC,SAA1BF,EAAiBG,KAChCC,EAAWC,EAAsB,OAChCC,GAAaC,IAAkBb,IAChCc,GAAeC,EAAuB,MAK5CC,GAAU,KACDF,GAAaG,SAEdJ,GADAH,EACeQ,GAAiB5B,GAEjBA,EACnB,GAED,CAACA,EAAMoB,IAKV,MAAMS,GAAiB,IAAWC,OAAA,OAAA,OAAA,GAAA,YAC9B,GAAKxB,IAASE,EAAd,CAIAC,GAAa,GACb,IACIG,GAAW,SACLf,EAAWD,EACrB,CAAE,MAAAmC,GACEnB,GAAW,EACf,SACIH,GAAa,EACjB,CAVA,CAWJ,IAEMuB,GAAkB,KACf1B,IAIDR,EACAA,EAAQF,GAIZiC,KAAgB,EAGdI,GACFC,IAMAA,EAAMC,kBACNH,IAAiB,EAGfI,GACFF,IAGAA,EAAMC,kBACNN,IAAgB,EAMdD,GAAoBS,IACtB,IAAKhC,EAAc,OAAOgC,EAE1B,MAAMC,EACFd,IAAgBA,GAAaG,QACvBH,GAAaG,QAAQY,wBAAwBC,MAC7C,EAEV,OAAOC,EAAaC,iBAAiBL,EAAOC,EAAgB,GAAI,IAAI,EAoBlEK,GAAkB,KACpB,GAA8B,SAA1B3B,EAAiBG,KACjB,OAAO,KAGX,MAAMyB,EAAuC,aAA1B5B,EAAiBG,KAEpC,OACI0B,EAAA,MAAA,CACIC,UAAWC,EAAyB,cACvB,GAAGhD,cAAciD,SAE9BH,EAACI,EAAiB,CACdH,UAAWI,EACPC,EACAP,GAAcQ,GACjB,cACY,GAAGrD,oBAChBsD,IACIT,EACM9B,EAAiBwC,aACjBtC,EAAiBqC,OAG7B,EAIRE,GAAsB,IACxBC,EAAAC,EAAA,CAAAT,SAAA,CACIH,EAAA,MAAA,CAAKC,UAAWY,WA3CpBF,EAAAC,EAAA,CAAAT,SAAA,CACIH,EAAA,MAAA,CAAKC,UAAWa,EAAqBC,IAAKpC,GAAYwB,SACjD1B,KAEJX,GACG6C,EAAA,MAAA,CAAKV,UAAWe,EAA0Bb,SAAA,CACtCH,EAACiB,EAAyB,CAAChB,UAAWiB,IACrC5D,GAA8B,+BAqCvC0C,EAAA,MAAA,CAAKC,UAAWkB,EAAsBhB,SACjCnC,GAAsB,MAE1BF,GACG6C,EAAA,MAAA,CAAKV,UAAWmB,EAAyBjB,SAAA,CACrCH,EAACiB,EAAyB,CAAChB,UAAWiB,IACrC5D,GAA8B,6BA6D/C,OACI0C,EAAA,KAAA,CAAIC,UAAWoB,EAAW,cAAenE,EAAEiD,SACvCQ,EAAA,MAAA,CACIV,UAAWI,EAAKiB,EAAYxD,GAAWyD,GACvCtE,QAASkC,GAAegB,SAAA,CA1DhCQ,EAAA,MAAA,CACIV,UAAWI,EACPmB,EACAnD,GAAgBoD,GACnBtB,SAAA,CAEAL,KACAzB,EACG2B,EAAA,MAAA,CAAKC,UAAWyB,EAA0BvB,SACrCO,OAGLA,QAMHzD,EAKD+C,EAAC2B,EAAc,CAAAxB,SACXH,EAAA,SAAA,CACI1B,KAAK,SACL2B,UAAW2B,EAAiB,cACf,GAAG1E,gBAAgB,aACpBQ,QAAAA,EAAcP,EAC1B0E,UAAWpE,EACXR,QAASmC,OAXV,KAmBPY,EAAA,MAAA,CAAKC,UAAW6B,EAAsB3B,SAClCH,EAAC+B,EAAM,CACH9B,UAAW+B,EAAiB,cACf,GAAG9E,oBAChBoB,KAAK,SACL2D,UAAU,QACVC,SAAS,QAAO,aACJ,YAAY/E,IACxBgF,QAASxE,IAAcF,EACvB2E,KAAMpC,EAACqC,EAAY,CAAA,GACnBpF,QAASsC,WAgBhB"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export declare const item: import("@linaria/core").LinariaClassName;
|
|
2
|
+
export declare const cardButton: import("@linaria/core").LinariaClassName;
|
|
2
3
|
export declare const box: import("@linaria/core").LinariaClassName;
|
|
3
4
|
export declare const boxError: import("@linaria/core").LinariaClassName;
|
|
4
5
|
export declare const contentSection: import("@linaria/core").LinariaClassName;
|
|
@@ -14,3 +15,4 @@ export declare const actionContainer: import("@linaria/core").LinariaClassName;
|
|
|
14
15
|
export declare const iconButton: import("@linaria/core").LinariaClassName;
|
|
15
16
|
export declare const thumbnailContainer: import("@linaria/core").LinariaClassName;
|
|
16
17
|
export declare const thumbnail: import("@linaria/core").LinariaClassName;
|
|
18
|
+
export declare const thumbnailPdf: import("@linaria/core").LinariaClassName;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"./file-list-card.
|
|
1
|
+
import"./file-list-card.styles_lzbqkk.css";const t="ifkrwze",i="c7grm6i",l="b1ryf4f4",e="basceiz",f="c83cih3",c="c13wqyhg",o="nthi1vt",d="ef8ofzq",r="fytzo9z",s="i4y82lx",z="ega23xt",a="d1qdniby",q="m1xq0zd",y="a18nltf5",k="impqdeo",n="t4orgj8",b="t96jkl",g="t1l7ztkl";export{y as actionContainer,l as box,e as boxError,i as cardButton,f as contentSection,c as contentSectionHasThumbnail,a as desktopErrorMessage,z as errorIcon,d as extendedNameSection,r as fileSizeSection,k as iconButton,t as item,s as itemNameText,q as mobileErrorMessage,o as nameSection,b as thumbnail,n as thumbnailContainer,g as thumbnailPdf};
|
|
2
2
|
//# sourceMappingURL=file-list-card.styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-list-card.styles.js","sources":["../../../src/file-download/file-list-card/file-list-card.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { lineClampCss } from \"../../shared/styles\";\nimport { Border, Colour, Font, MediaQuery, Radius, Spacing } from \"../../theme\";\n\n// =============================================================================\n// STYLING\n// =============================================================================\nexport const item = css`\n display: flex;\n align-items: center;\n\n width: 100%;\n border: none;\n\n &:not(:last-child) {\n margin-bottom: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const box = css`\n display: flex;\n align-items: center;\n\n width: 100%;\n padding: ${Spacing[\"spacing-16\"]} ${Spacing[\"spacing-32\"]};\n cursor: pointer;\n\n background: ${Colour[\"bg-primary-subtlest\"]};\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n border-radius: ${Radius[\"sm\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n padding: ${Spacing[\"spacing-16\"]};\n }\n\n &:hover {\n background: ${Colour[\"bg-hover\"]};\n }\n`;\n\nexport const boxError = css`\n background: ${Colour[\"bg-error\"]};\n border-color: ${Colour[\"border-error\"]};\n\n &:hover {\n background: ${Colour[\"bg-error\"]};\n }\n`;\n\nexport const contentSection = css`\n display: flex;\n flex: 1;\n align-items: center;\n\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n }\n`;\n\nexport const contentSectionHasThumbnail = css`\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: row;\n align-items: center;\n }\n`;\n\nexport const nameSection = css`\n display: flex;\n flex: 1;\n flex-direction: column;\n\n width: 100%;\n\n overflow-wrap: break-word;\n word-break: break-all;\n white-space: normal;\n`;\n\nexport const extendedNameSection = css`\n display: flex;\n flex: 1;\n align-items: center;\n\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n }\n`;\n\nexport const fileSizeSection = css`\n display: flex;\n justify-content: flex-end;\n\n width: 5rem;\n margin-left: ${Spacing[\"spacing-8\"]};\n\n ${Font[\"body-md-regular\"]}\n color: ${Colour[\"text\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n justify-content: flex-start;\n\n width: 100%;\n margin-left: 0;\n margin-top: ${Spacing[\"spacing-8\"]};\n\n ${lineClampCss(2)}\n }\n`;\n\nexport const itemNameText = css`\n ${Font[\"body-md-regular\"]}\n color: ${Colour[\"text\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n ${lineClampCss(2)}\n }\n`;\n\nexport const errorIcon = css`\n height: 1lh;\n width: 1em;\n flex-shrink: 0;\n color: ${Colour[\"icon-error-strong\"]};\n`;\n\nconst baseErrorMessage = `\n ${Font[\"body-sm-semibold\"]}\n color: ${Colour[\"text-error\"]};\n`;\n\nexport const desktopErrorMessage = css`\n ${baseErrorMessage}\n margin-top: ${Spacing[\"spacing-8\"]};\n display: flex;\n gap: ${Spacing[\"spacing-4\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n display: none;\n visibility: hidden;\n }\n`;\n\nexport const mobileErrorMessage = css`\n ${baseErrorMessage}\n display: none;\n visibility: hidden;\n\n ${MediaQuery.MaxWidth.lg} {\n display: flex;\n gap: ${Spacing[\"spacing-4\"]};\n visibility: visible;\n margin-top: ${Spacing[\"spacing-8\"]};\n }\n`;\n\nexport const actionContainer = css`\n display: flex;\n justify-content: flex-end;\n align-items: center;\n\n margin-left: ${Spacing[\"spacing-32\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n margin-left: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const iconButton = css`\n min-width: unset;\n\n &:not(:last-child) {\n margin-right: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const thumbnailContainer = css`\n width: auto;\n margin-right: ${Spacing[\"spacing-32\"]};\n\n display: flex;\n flex-shrink: 0;\n flex-direction: column;\n justify-content: center;\n\n ${MediaQuery.MaxWidth.lg} {\n margin-right: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const thumbnail = css`\n border-radius: ${Radius[\"sm\"]};\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n\n width: 96px;\n height: 96px;\n aspect-ratio: 1;\n object-fit: cover;\n\n ${MediaQuery.MaxWidth.lg} {\n width: 64px;\n height: 64px;\n }\n`;\n"],"names":["item","box","boxError","contentSection","contentSectionHasThumbnail","nameSection","extendedNameSection","fileSizeSection","itemNameText","errorIcon","desktopErrorMessage","mobileErrorMessage","actionContainer","iconButton","thumbnailContainer","thumbnail"],"mappings":"
|
|
1
|
+
{"version":3,"file":"file-list-card.styles.js","sources":["../../../src/file-download/file-list-card/file-list-card.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { lineClampCss } from \"../../shared/styles\";\nimport { Border, Colour, Font, MediaQuery, Radius, Spacing } from \"../../theme\";\n\n// =============================================================================\n// STYLING\n// =============================================================================\nexport const item = css`\n display: flex;\n align-items: center;\n\n width: 100%;\n border: none;\n\n &:not(:last-child) {\n margin-bottom: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const cardButton = css`\n appearance: none;\n padding: 0;\n background: none;\n border: none;\n`;\n\nexport const box = css`\n position: relative;\n display: flex;\n align-items: center;\n\n width: 100%;\n padding: ${Spacing[\"spacing-16\"]} ${Spacing[\"spacing-32\"]};\n cursor: pointer;\n\n background: ${Colour[\"bg-primary-subtlest\"]};\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n border-radius: ${Radius[\"sm\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n padding: ${Spacing[\"spacing-16\"]};\n }\n\n &:hover {\n background: ${Colour[\"bg-hover\"]};\n }\n\n @supports selector(:has(*)) {\n &:has(.${cardButton}:focus-visible) {\n outline: 2px solid ${Colour[\"focus-ring\"]};\n outline-offset: -2px;\n }\n }\n`;\n\nexport const boxError = css`\n background: ${Colour[\"bg-error\"]};\n border-color: ${Colour[\"border-error\"]};\n\n &:hover {\n background: ${Colour[\"bg-error\"]};\n }\n\n @supports selector(:has(*)) {\n &:has(.${cardButton}:focus-visible) {\n outline-color: ${Colour[\"border-error-focus\"]};\n }\n }\n`;\n\nexport const contentSection = css`\n display: flex;\n flex: 1;\n align-items: center;\n\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n }\n`;\n\nexport const contentSectionHasThumbnail = css`\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: row;\n align-items: center;\n }\n`;\n\nexport const nameSection = css`\n display: flex;\n flex: 1;\n flex-direction: column;\n\n width: 100%;\n\n overflow-wrap: break-word;\n word-break: break-all;\n white-space: normal;\n`;\n\nexport const extendedNameSection = css`\n display: flex;\n flex: 1;\n align-items: center;\n\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n }\n`;\n\nexport const fileSizeSection = css`\n display: flex;\n justify-content: flex-end;\n\n width: 5rem;\n margin-left: ${Spacing[\"spacing-8\"]};\n\n ${Font[\"body-md-regular\"]}\n color: ${Colour[\"text\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n justify-content: flex-start;\n\n width: 100%;\n margin-left: 0;\n margin-top: ${Spacing[\"spacing-8\"]};\n\n ${lineClampCss(2)}\n }\n`;\n\nexport const itemNameText = css`\n ${Font[\"body-md-regular\"]}\n color: ${Colour[\"text\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n ${lineClampCss(2)}\n }\n`;\n\nexport const errorIcon = css`\n height: 1lh;\n width: 1em;\n flex-shrink: 0;\n color: ${Colour[\"icon-error-strong\"]};\n`;\n\nconst baseErrorMessage = `\n ${Font[\"body-sm-semibold\"]}\n color: ${Colour[\"text-error\"]};\n`;\n\nexport const desktopErrorMessage = css`\n ${baseErrorMessage}\n margin-top: ${Spacing[\"spacing-8\"]};\n display: flex;\n gap: ${Spacing[\"spacing-4\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n display: none;\n visibility: hidden;\n }\n`;\n\nexport const mobileErrorMessage = css`\n ${baseErrorMessage}\n display: none;\n visibility: hidden;\n\n ${MediaQuery.MaxWidth.lg} {\n display: flex;\n gap: ${Spacing[\"spacing-4\"]};\n visibility: visible;\n margin-top: ${Spacing[\"spacing-8\"]};\n }\n`;\n\nexport const actionContainer = css`\n display: flex;\n justify-content: flex-end;\n align-items: center;\n\n margin-left: ${Spacing[\"spacing-32\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n margin-left: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const iconButton = css`\n min-width: unset;\n\n &:not(:last-child) {\n margin-right: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const thumbnailContainer = css`\n width: auto;\n margin-right: ${Spacing[\"spacing-32\"]};\n\n display: flex;\n flex-shrink: 0;\n flex-direction: column;\n justify-content: center;\n\n ${MediaQuery.MaxWidth.lg} {\n margin-right: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const thumbnail = css`\n border-radius: ${Radius[\"sm\"]};\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n\n width: 96px;\n height: 96px;\n aspect-ratio: 1;\n object-fit: cover;\n\n ${MediaQuery.MaxWidth.lg} {\n width: 64px;\n height: 64px;\n }\n`;\n\nexport const thumbnailPdf = css`\n border: none;\n`;\n"],"names":["item","cardButton","box","boxError","contentSection","contentSectionHasThumbnail","nameSection","extendedNameSection","fileSizeSection","itemNameText","errorIcon","desktopErrorMessage","mobileErrorMessage","actionContainer","iconButton","thumbnailContainer","thumbnail","thumbnailPdf"],"mappings":"uFAQO,MAAMA,EAAI,UAYJC,EAAU,UAOVC,EAAG,WA6BHC,EAAQ,UAeRC,EAAc,UAYdC,EAA0B,WAO1BC,EAAW,UAYXC,EAAmB,UAYnBC,EAAe,UAqBfC,EAAY,UASZC,EAAS,UAYTC,EAAmB,WAYnBC,EAAkB,UAalBC,EAAe,WAYfC,EAAU,UAQVC,EAAkB,UAclBC,EAAS,SAeTC,EAAY"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
@layer fds{.ifkrwze{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;width:100%;border:none;}.ifkrwze:not(:last-child){margin-bottom:var(--fds-spacing-16);}
|
|
2
|
+
.c7grm6i{-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;padding:0;background:none;border:none;}
|
|
3
|
+
.b1ryf4f4{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;width:100%;padding:var(--fds-spacing-16) var(--fds-spacing-32);cursor:pointer;background:var(--fds-colour-bg-primary-subtlest);border:var(--fds-border-width-010) var(--fds-border-style-solid) var(--fds-colour-border);border-radius:var(--fds-radius-sm);}:where(body.fds-breakpoint-lg-max) .b1ryf4f4{padding:var(--fds-spacing-16);}.b1ryf4f4:hover{background:var(--fds-colour-bg-hover);}@supports selector(:has(*)){.b1ryf4f4:has(.c7grm6i:focus-visible){outline:2px solid var(--fds-colour-focus-ring);outline-offset:-2px;}}
|
|
4
|
+
.basceiz{background:var(--fds-colour-bg-error);border-color:var(--fds-colour-border-error);}.basceiz:hover{background:var(--fds-colour-bg-error);}@supports selector(:has(*)){.basceiz:has(.c7grm6i:focus-visible){outline-color:var(--fds-colour-border-error-focus);}}
|
|
5
|
+
.c83cih3{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1;-ms-flex:1;flex:1;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}:where(body.fds-breakpoint-lg-max) .c83cih3{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;width:100%;}
|
|
6
|
+
:where(body.fds-breakpoint-lg-max) .c13wqyhg{-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}
|
|
7
|
+
.nthi1vt{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1;-ms-flex:1;flex:1;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;width:100%;overflow-wrap:break-word;word-break:break-all;white-space:normal;}
|
|
8
|
+
.ef8ofzq{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1;-ms-flex:1;flex:1;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}:where(body.fds-breakpoint-lg-max) .ef8ofzq{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;width:100%;}
|
|
9
|
+
.fytzo9z{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;width:5rem;margin-left:var(--fds-spacing-8);font-family:var(--fds-font-family-body);font-variant:var(--fds-font-variant);font-size:var(--fds-font-body-size-md);font-weight:var(--fds-font-weight-regular);line-height:var(--fds-font-body-lh-md);letter-spacing:var(--fds-font-body-ls-md);color:var(--fds-colour-text);}:where(body.fds-breakpoint-lg-max) .fytzo9z{-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start;width:100%;margin-left:0;margin-top:var(--fds-spacing-8);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;}
|
|
10
|
+
.i4y82lx{font-family:var(--fds-font-family-body);font-variant:var(--fds-font-variant);font-size:var(--fds-font-body-size-md);font-weight:var(--fds-font-weight-regular);line-height:var(--fds-font-body-lh-md);letter-spacing:var(--fds-font-body-ls-md);color:var(--fds-colour-text);}:where(body.fds-breakpoint-lg-max) .i4y82lx{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;}
|
|
11
|
+
.ega23xt{height:1lh;width:1em;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;color:var(--fds-colour-icon-error-strong);}
|
|
12
|
+
.d1qdniby{font-family:var(--fds-font-family-body);font-variant:var(--fds-font-variant);font-size:var(--fds-font-body-size-sm);font-weight:var(--fds-font-weight-semibold);line-height:var(--fds-font-body-lh-sm);letter-spacing:var(--fds-font-body-ls-sm);color:var(--fds-colour-text-error);margin-top:var(--fds-spacing-8);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;gap:var(--fds-spacing-4);}:where(body.fds-breakpoint-lg-max) .d1qdniby{display:none;visibility:hidden;}
|
|
13
|
+
.m1xq0zd{font-family:var(--fds-font-family-body);font-variant:var(--fds-font-variant);font-size:var(--fds-font-body-size-sm);font-weight:var(--fds-font-weight-semibold);line-height:var(--fds-font-body-lh-sm);letter-spacing:var(--fds-font-body-ls-sm);color:var(--fds-colour-text-error);display:none;visibility:hidden;}:where(body.fds-breakpoint-lg-max) .m1xq0zd{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;gap:var(--fds-spacing-4);visibility:visible;margin-top:var(--fds-spacing-8);}
|
|
14
|
+
.a18nltf5{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin-left:var(--fds-spacing-32);}:where(body.fds-breakpoint-lg-max) .a18nltf5{margin-left:var(--fds-spacing-16);}
|
|
15
|
+
.impqdeo{min-width:unset;}.impqdeo:not(:last-child){margin-right:var(--fds-spacing-16);}
|
|
16
|
+
.t4orgj8{width:auto;margin-right:var(--fds-spacing-32);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;}:where(body.fds-breakpoint-lg-max) .t4orgj8{margin-right:var(--fds-spacing-16);}
|
|
17
|
+
.t96jkl{border-radius:var(--fds-radius-sm);border:var(--fds-border-width-010) var(--fds-border-style-solid) var(--fds-colour-border);width:96px;height:96px;aspect-ratio:1;object-fit:cover;}:where(body.fds-breakpoint-lg-max) .t96jkl{width:64px;height:64px;}
|
|
18
|
+
.t1l7ztkl{border:none;}}
|
package/file-download/types.d.ts
CHANGED
|
@@ -30,6 +30,12 @@ export interface FileItemDownloadProps {
|
|
|
30
30
|
* @default true
|
|
31
31
|
*/
|
|
32
32
|
ready?: boolean | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Name for the card, used when `FileDownload` is given an `onClick`.
|
|
35
|
+
*
|
|
36
|
+
* @default the file name
|
|
37
|
+
*/
|
|
38
|
+
clickLabel?: string | undefined;
|
|
33
39
|
}
|
|
34
40
|
/** Visual style variant controlling whether the component renders with a dashed border. */
|
|
35
41
|
export type FileDownloadStyle = "bordered" | "no-border";
|
|
@@ -68,4 +74,11 @@ export interface FileDownloadProps {
|
|
|
68
74
|
* @returns A `Promise` that resolves when the download is complete, or `void` for synchronous handling.
|
|
69
75
|
*/
|
|
70
76
|
onDownload: (file: FileItemDownloadProps) => void | Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Called when a file card itself is activated, as opposed to its download button.
|
|
79
|
+
* When omitted, activating the card triggers `onDownload` instead.
|
|
80
|
+
*
|
|
81
|
+
* @param file The file item whose card was activated.
|
|
82
|
+
*/
|
|
83
|
+
onClick?: ((file: FileItemDownloadProps) => void) | undefined;
|
|
71
84
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsx as e,jsxs as r,Fragment as t}from"react/jsx-runtime";import{useSensors as i,useSensor as s,DndContext as o,KeyboardSensor as n,TouchSensor as l}from"../../external/@dnd-kit/core/dist/core.esm.js";import{SortableContext as
|
|
1
|
+
import{jsx as e,jsxs as r,Fragment as t}from"react/jsx-runtime";import{useSensors as i,useSensor as s,DndContext as o,KeyboardSensor as n,TouchSensor as l}from"../../external/@dnd-kit/core/dist/core.esm.js";import{SortableContext as a,verticalListSortingStrategy as d,arrayMove as c,sortableKeyboardCoordinates as p}from"../../external/@dnd-kit/sortable/dist/sortable.esm.js";import m from"clsx";import{forwardRef as f,useContext as u,useState as g,useRef as h,useImperativeHandle as b,useEffect as v}from"react";import{useResizeDetector as j}from"../../external/react-resize-detector/build/index.esm.js";import{VisuallyHidden as x}from"../../shared/accessibility/index.js";import{FileUploadContext as y}from"../context.js";import{MouseSensor as $}from"../custom-sensors.js";import{FileListItem as I}from"../file-list-item/file-list-item.js";import{FileUploadHelper as M}from"../helper.js";import{listWrapper as D,listWrapperReadOnly as S}from"./file-list.styles.js";const O=f((function({fileItems:f=[],editableFileItems:O,fileDescriptionMaxLength:w,descriptionRequired:C,descriptionLabel:L,sortable:E,disabled:F,readOnly:R,onItemUpdate:k,onItemDelete:q,onSort:B},N){const{setActiveId:z}=u(y),[A,G]=g(0),[K,T]=g(""),U=h({});b(N,(()=>({focus:()=>{var e;null===(e=H.current)||void 0===e||e.focus()}})));const{width:W=0,ref:H}=j(),J=h({}),P=i(s($,{activationConstraint:{distance:8}}),s(l,{activationConstraint:{delay:150,tolerance:5}}),s(n,{coordinateGetter:p})),Q=e=>{delete J.current[e]};v((()=>{var e;if(!f||0===f.length)return void T("");const r=Date.now(),t=[];for(const i of f){const s=U.current[i.id];if(i.errorMessage)"error"!==(null==s?void 0:s.status)&&(t.push("string"==typeof i.errorMessage?`Error uploading ${i.name}: ${i.errorMessage}`:`Error uploading ${i.name}`),U.current[i.id]={progress:null!==(e=i.progress)&&void 0!==e?e:1,timestamp:r,status:"error"});else if(void 0!==i.progress)if(i.progress>=1)"complete"!==(null==s?void 0:s.status)&&(t.push(`${i.name} upload is complete`),U.current[i.id]={progress:1,timestamp:r,status:"complete"});else if("number"==typeof i.progress&&i.progress<1){(!s||"in-progress"!==s.status)&&(t.push(`Starting upload of ${i.name}`),U.current[i.id]={progress:i.progress,timestamp:r,status:"in-progress"})}}t.length>0&&T(t.join(", "))}),[f]);const V=e=>r=>{Q(e.id);const t=Object.assign(Object.assign({},e),{description:r});k(t)},X=e=>r=>{J.current[e.id]=r},Y=e=>()=>{Q(e.id),e.description&&0!==e.description.length||q(e)},Z=e=>{G((r=>"edit"===e?r+1:Math.max(0,r-1)))},_=e=>()=>{q(e),H.current&&H.current.focus()},ee=e=>O&&M.isSupportedImageType(e.type),re=()=>f&&f.length>1&&E&&!R&&!(A>0||f.some((e=>!!e.errorMessage))),te=()=>{if(0===f.length)return"No files uploaded";const e=f.filter((e=>!(null==e?void 0:e.errorMessage)&&(1===e.progress||void 0===e.progress))).length,r=f.filter((e=>"number"==typeof e.progress&&e.progress<1)).length,t=f.filter((e=>e.errorMessage)).length;if(0===e&&0===r&&0===t)return"File list";const i=[e>0?`${e} completed files`:"",r>0?`${r} file in progress`:"",t>0?`${t} ${t>1?"files":"file"} with error`:""].filter(Boolean);return`${R?"Read-only file list":"File list"}. ${i.join(", ")}`};return e(o,{sensors:P,onDragEnd:e=>{if(B&&f){const{active:r,over:t}=e;if(t&&r.id!==t.id){const e=f.findIndex((e=>e.id===r.id)),i=f.findIndex((e=>e.id===t.id)),s=c(f,e,i);B(s)}}z(void 0)},onDragStart:e=>{const{active:r}=e;z(r.id)},children:e(a,{items:f,strategy:d,children:r(t,{children:[e(x,{"aria-live":"polite","aria-atomic":"true",children:K}),e("ul",{tabIndex:-1,className:m(D,R&&S),ref:H,"aria-label":te(),children:0===f.length?null:f.map((r=>{const t=Object.assign({},r);return void 0!==J.current[r.id]&&(t.description=J.current[r.id]),e(I,{fileItem:t,editable:ee(r),wrapperWidth:W,sortable:re(),disabled:F,readOnly:R,descriptionLabel:L,fileDescriptionMaxLength:w,descriptionRequired:C,onDelete:_(r),onSave:V(r),onCancel:Y(r),onBlur:X(r),onModeChange:Z},r.id)}))})]})})})}));export{O as FileList};
|
|
2
2
|
//# sourceMappingURL=file-list.js.map
|