@lifesg/react-design-system 4.0.0-alpha.11 → 4.0.0-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/breadcrumb/breadcrumb.js +1 -1
- package/breadcrumb/breadcrumb.js.map +1 -1
- package/breadcrumb/breadcrumb.styles.d.ts +0 -8
- package/breadcrumb/breadcrumb.styles.js +1 -1
- package/breadcrumb/breadcrumb.styles.js.map +1 -1
- package/breadcrumb/breadcrumb.styles_1blzn8n.css +7 -0
- package/breadcrumb/types.d.ts +2 -13
- package/cjs/breadcrumb/breadcrumb.js +1 -1
- package/cjs/breadcrumb/breadcrumb.js.map +1 -1
- package/cjs/breadcrumb/breadcrumb.styles.js +1 -1
- package/cjs/breadcrumb/breadcrumb.styles.js.map +1 -1
- package/cjs/breadcrumb/breadcrumb.styles_1blzn8n.css +7 -0
- package/cjs/drawer/drawer.js +1 -1
- package/cjs/drawer/drawer.js.map +1 -1
- package/cjs/drawer/drawer.styles.js +1 -1
- package/cjs/drawer/drawer.styles.js.map +1 -1
- package/{drawer/drawer.styles_94hx3y.css → cjs/drawer/drawer.styles_a4bwe0.css} +6 -3
- package/cjs/file-download/file-download.js +1 -1
- package/cjs/file-download/file-download.js.map +1 -1
- package/cjs/file-download/file-list-card/file-list-card.js +1 -1
- package/cjs/file-download/file-list-card/file-list-card.js.map +1 -1
- package/cjs/file-download/file-list-card/file-list-card.styles.js +1 -1
- package/cjs/file-download/file-list-card/file-list-card.styles.js.map +1 -1
- package/cjs/file-download/file-list-card/file-list-card.styles_lzbqkk.css +18 -0
- package/cjs/file-upload/file-list/file-list.js +1 -1
- package/cjs/file-upload/file-list/file-list.js.map +1 -1
- package/cjs/file-upload/file-list/file-list.styles.js +1 -1
- package/cjs/file-upload/file-list/file-list.styles.js.map +1 -1
- package/cjs/file-upload/file-list/file-list.styles_1xbypnh.css +2 -0
- package/cjs/file-upload/file-list-item/file-item-actions.js +2 -0
- package/cjs/file-upload/file-list-item/file-item-actions.js.map +1 -0
- package/cjs/file-upload/file-list-item/file-item-actions.styles.js +2 -0
- package/cjs/file-upload/file-list-item/file-item-actions.styles.js.map +1 -0
- package/cjs/file-upload/file-list-item/file-item-actions.styles_1quulgy.css +8 -0
- package/cjs/file-upload/file-list-item/file-item-details.js +2 -0
- package/cjs/file-upload/file-list-item/file-item-details.js.map +1 -0
- package/cjs/file-upload/file-list-item/file-item-details.styles.js +2 -0
- package/cjs/file-upload/file-list-item/file-item-details.styles.js.map +1 -0
- package/cjs/file-upload/file-list-item/file-item-details.styles_1ce9akx.css +7 -0
- package/cjs/file-upload/file-list-item/file-list-item.js +1 -1
- package/cjs/file-upload/file-list-item/file-list-item.js.map +1 -1
- package/cjs/file-upload/file-list-item/file-list-item.styles.js +1 -1
- package/cjs/file-upload/file-list-item/file-list-item.styles.js.map +1 -1
- package/cjs/file-upload/file-list-item/file-list-item.styles_x3a500.css +10 -0
- package/cjs/file-upload/file-list-item/use-truncated-name.js +2 -0
- package/cjs/file-upload/file-list-item/use-truncated-name.js.map +1 -0
- package/cjs/file-upload/helper.js +1 -1
- package/cjs/file-upload/helper.js.map +1 -1
- package/cjs/footer/footer-disclaimer-links-data.js +1 -1
- package/cjs/footer/footer-disclaimer-links-data.js.map +1 -1
- package/cjs/footer/footer.styles.js +1 -1
- package/cjs/footer/footer.styles.js.map +1 -1
- package/{footer/footer.styles_1msorhc.css → cjs/footer/footer.styles_14hnlcq.css} +4 -4
- package/cjs/fullscreen-image-carousel/fullscreen-image-carousel.js +1 -1
- package/cjs/fullscreen-image-carousel/fullscreen-image-carousel.js.map +1 -1
- package/cjs/index.js +1 -1
- package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.js +1 -1
- package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.js.map +1 -1
- package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js +1 -1
- package/cjs/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js.map +1 -1
- package/cjs/local-nav/local-nav-dropdown/{local-nav-dropdown.styles_uhd4xl.css → local-nav-dropdown.styles_kpel1m.css} +9 -6
- package/cjs/local-nav/local-nav-menu/local-nav-menu.js +1 -1
- package/cjs/local-nav/local-nav-menu/local-nav-menu.js.map +1 -1
- package/cjs/local-nav/local-nav-menu/local-nav-menu.styles.js +1 -1
- package/cjs/local-nav/local-nav-menu/local-nav-menu.styles.js.map +1 -1
- package/cjs/local-nav/local-nav-menu/local-nav-menu.styles_67fcyc.css +8 -0
- package/cjs/masthead/sgds-day.css +0 -1
- package/cjs/masthead/sgds-night.css +0 -1
- package/cjs/menu/menu-content.js +1 -1
- package/cjs/menu/menu-content.js.map +1 -1
- package/cjs/menu/menu-content.styles.js +1 -1
- package/cjs/menu/menu-content.styles.js.map +1 -1
- package/cjs/menu/menu-content.styles_1r8oxtk.css +5 -0
- package/cjs/menu/menu-item.styles.js +1 -1
- package/cjs/menu/menu-item.styles.js.map +1 -1
- package/cjs/menu/{menu-item.styles_liyed8.css → menu-item.styles_eut2j9.css} +1 -1
- package/cjs/menu/menu-link.styles.js +1 -1
- package/cjs/menu/menu-link.styles.js.map +1 -1
- package/cjs/menu/menu-link.styles_rng7n7.css +2 -0
- package/cjs/menu/menu-section.js +1 -1
- package/cjs/menu/menu-section.js.map +1 -1
- package/cjs/menu/menu-section.styles.js +1 -1
- package/cjs/menu/menu-section.styles.js.map +1 -1
- package/cjs/menu/menu-section.styles_1n0ppxl.css +5 -0
- package/cjs/navbar/navbar-items.js +1 -1
- package/cjs/navbar/navbar-items.js.map +1 -1
- package/cjs/navbar/navbar-logo-data.js +1 -1
- package/cjs/navbar/navbar-logo-data.js.map +1 -1
- package/cjs/notification-banner/notification-banner-hoc.js +1 -1
- package/cjs/notification-banner/notification-banner-hoc.js.map +1 -1
- package/cjs/pagination/pagination.js +1 -1
- package/cjs/pagination/pagination.js.map +1 -1
- package/cjs/shared/dropdown-list/dropdown-label.js +1 -1
- package/cjs/shared/dropdown-list/dropdown-label.js.map +1 -1
- package/cjs/shared/fade-wrapper/fade-wrapper.js +1 -1
- package/cjs/shared/fade-wrapper/fade-wrapper.js.map +1 -1
- package/cjs/theme/index.js +1 -1
- package/cjs/theme/tokens/colour.js +1 -1
- package/cjs/theme/tokens/colour.js.map +1 -1
- package/cjs/theme/tokens/radius.js +1 -1
- package/cjs/theme/tokens/radius.js.map +1 -1
- package/cjs/theme/types.js +1 -1
- package/cjs/theme/types.js.map +1 -1
- package/codemods/run-codemod.js +8 -2
- package/codemods/run-codemod.js.map +1 -1
- package/codemods/run-codemod.ts +13 -4
- package/drawer/drawer.d.ts +1 -1
- package/drawer/drawer.js +1 -1
- package/drawer/drawer.js.map +1 -1
- package/drawer/drawer.styles.d.ts +3 -0
- package/drawer/drawer.styles.js +1 -1
- package/drawer/drawer.styles.js.map +1 -1
- package/{cjs/drawer/drawer.styles_94hx3y.css → drawer/drawer.styles_a4bwe0.css} +6 -3
- package/drawer/types.d.ts +7 -0
- package/file-download/file-download.d.ts +1 -1
- package/file-download/file-download.js +1 -1
- package/file-download/file-download.js.map +1 -1
- package/file-download/file-list-card/file-list-card.d.ts +1 -1
- package/file-download/file-list-card/file-list-card.js +1 -1
- package/file-download/file-list-card/file-list-card.js.map +1 -1
- package/file-download/file-list-card/file-list-card.styles.d.ts +2 -0
- package/file-download/file-list-card/file-list-card.styles.js +1 -1
- package/file-download/file-list-card/file-list-card.styles.js.map +1 -1
- package/file-download/file-list-card/file-list-card.styles_lzbqkk.css +18 -0
- package/file-download/file-list-card/types.d.ts +1 -0
- package/file-download/types.d.ts +13 -0
- package/file-upload/file-list/file-list.js +1 -1
- package/file-upload/file-list/file-list.js.map +1 -1
- package/file-upload/file-list/file-list.styles.d.ts +0 -1
- package/file-upload/file-list/file-list.styles.js +1 -1
- package/file-upload/file-list/file-list.styles.js.map +1 -1
- package/file-upload/file-list/file-list.styles_1xbypnh.css +2 -0
- package/file-upload/file-list-item/file-item-actions.d.ts +30 -0
- package/file-upload/file-list-item/file-item-actions.js +2 -0
- package/file-upload/file-list-item/file-item-actions.js.map +1 -0
- package/file-upload/file-list-item/file-item-actions.styles.d.ts +6 -0
- package/file-upload/file-list-item/file-item-actions.styles.js +2 -0
- package/file-upload/file-list-item/file-item-actions.styles.js.map +1 -0
- package/file-upload/file-list-item/file-item-actions.styles_1quulgy.css +8 -0
- package/file-upload/file-list-item/file-item-details.d.ts +15 -0
- package/file-upload/file-list-item/file-item-details.js +2 -0
- package/file-upload/file-list-item/file-item-details.js.map +1 -0
- package/file-upload/file-list-item/file-item-details.styles.d.ts +7 -0
- package/file-upload/file-list-item/file-item-details.styles.js +2 -0
- package/file-upload/file-list-item/file-item-details.styles.js.map +1 -0
- package/file-upload/file-list-item/file-item-details.styles_1ce9akx.css +7 -0
- package/file-upload/file-list-item/file-list-item.d.ts +1 -7
- package/file-upload/file-list-item/file-list-item.js +1 -1
- package/file-upload/file-list-item/file-list-item.js.map +1 -1
- package/file-upload/file-list-item/file-list-item.styles.d.ts +6 -13
- package/file-upload/file-list-item/file-list-item.styles.js +1 -1
- package/file-upload/file-list-item/file-list-item.styles.js.map +1 -1
- package/file-upload/file-list-item/file-list-item.styles_x3a500.css +10 -0
- package/file-upload/file-list-item/types.d.ts +10 -3
- package/file-upload/file-list-item/use-truncated-name.d.ts +1 -0
- package/file-upload/file-list-item/use-truncated-name.js +2 -0
- package/file-upload/file-list-item/use-truncated-name.js.map +1 -0
- package/file-upload/helper.d.ts +30 -0
- package/file-upload/helper.js +1 -1
- package/file-upload/helper.js.map +1 -1
- package/footer/footer-disclaimer-links-data.js +1 -1
- package/footer/footer-disclaimer-links-data.js.map +1 -1
- package/footer/footer.styles.js +1 -1
- package/footer/footer.styles.js.map +1 -1
- package/{cjs/footer/footer.styles_1msorhc.css → footer/footer.styles_14hnlcq.css} +4 -4
- package/fullscreen-image-carousel/fullscreen-image-carousel.d.ts +1 -1
- package/fullscreen-image-carousel/fullscreen-image-carousel.js +1 -1
- package/fullscreen-image-carousel/fullscreen-image-carousel.js.map +1 -1
- package/fullscreen-image-carousel/types.d.ts +37 -0
- package/index.js +1 -1
- package/input-group/types.d.ts +4 -1
- package/input-select/types.d.ts +1 -0
- package/local-nav/local-nav-dropdown/local-nav-dropdown.js +1 -1
- package/local-nav/local-nav-dropdown/local-nav-dropdown.js.map +1 -1
- package/local-nav/local-nav-dropdown/local-nav-dropdown.styles.d.ts +3 -0
- package/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js +1 -1
- package/local-nav/local-nav-dropdown/local-nav-dropdown.styles.js.map +1 -1
- package/local-nav/local-nav-dropdown/{local-nav-dropdown.styles_uhd4xl.css → local-nav-dropdown.styles_kpel1m.css} +9 -6
- package/local-nav/local-nav-menu/local-nav-menu.js +1 -1
- package/local-nav/local-nav-menu/local-nav-menu.js.map +1 -1
- package/local-nav/local-nav-menu/local-nav-menu.styles.d.ts +3 -0
- package/local-nav/local-nav-menu/local-nav-menu.styles.js +1 -1
- package/local-nav/local-nav-menu/local-nav-menu.styles.js.map +1 -1
- package/local-nav/local-nav-menu/local-nav-menu.styles_67fcyc.css +8 -0
- package/local-nav/types.d.ts +17 -0
- package/masked-input/types.d.ts +1 -2
- package/masthead/sgds-day.css +0 -1
- package/masthead/sgds-night.css +0 -1
- package/menu/menu-content.js +1 -1
- package/menu/menu-content.js.map +1 -1
- package/menu/menu-content.styles.d.ts +1 -0
- package/menu/menu-content.styles.js +1 -1
- package/menu/menu-content.styles.js.map +1 -1
- package/menu/menu-content.styles_1r8oxtk.css +5 -0
- package/menu/menu-item.styles.js +1 -1
- package/menu/menu-item.styles.js.map +1 -1
- package/menu/{menu-item.styles_liyed8.css → menu-item.styles_eut2j9.css} +1 -1
- package/menu/menu-link.styles.js +1 -1
- package/menu/menu-link.styles.js.map +1 -1
- package/menu/menu-link.styles_rng7n7.css +2 -0
- package/menu/menu-section.d.ts +1 -1
- package/menu/menu-section.js +1 -1
- package/menu/menu-section.js.map +1 -1
- package/menu/menu-section.styles.d.ts +7 -0
- package/menu/menu-section.styles.js +1 -1
- package/menu/menu-section.styles.js.map +1 -1
- package/menu/menu-section.styles_1n0ppxl.css +5 -0
- package/menu/menu.d.ts +1 -1
- package/menu/types.d.ts +10 -2
- package/navbar/navbar-items.js +1 -1
- package/navbar/navbar-items.js.map +1 -1
- package/navbar/navbar-logo-data.js +1 -1
- package/navbar/navbar-logo-data.js.map +1 -1
- package/navbar/types.d.ts +9 -0
- package/notification-banner/notification-banner-hoc.js +1 -1
- package/notification-banner/notification-banner-hoc.js.map +1 -1
- package/package.json +2 -3
- package/pagination/pagination.js +1 -1
- package/pagination/pagination.js.map +1 -1
- package/pagination/types.d.ts +8 -1
- package/select-histogram/types.d.ts +1 -0
- package/shared/dropdown-list/dropdown-label.d.ts +2 -2
- package/shared/dropdown-list/dropdown-label.js +1 -1
- package/shared/dropdown-list/dropdown-label.js.map +1 -1
- package/shared/dropdown-list/types.d.ts +6 -2
- package/shared/fade-wrapper/fade-wrapper.js +1 -1
- package/shared/fade-wrapper/fade-wrapper.js.map +1 -1
- package/shared/fade-wrapper/types.d.ts +1 -0
- package/shared/styles/index.d.ts +5 -0
- package/theme/index.js +1 -1
- package/theme/styles/a11y-playground.css +52 -40
- package/theme/styles/bookingsg.css +52 -40
- package/theme/styles/careercompass.css +52 -40
- package/theme/styles/ccube.css +52 -40
- package/theme/styles/imda.css +52 -40
- package/theme/styles/lifesg.css +52 -40
- package/theme/styles/mylegacy.css +52 -40
- package/theme/styles/oneservice.css +52 -40
- package/theme/styles/pa.css +28 -22
- package/theme/styles/rbs.css +52 -40
- package/theme/styles/sgw-digital-lobby.css +52 -40
- package/theme/styles/smgs.css +52 -40
- package/theme/styles/spf.css +28 -27
- package/theme/styles/sportsg-orange.css +791 -0
- package/theme/styles/supportgowhere.css +52 -40
- package/theme/styles/tote-board.css +52 -40
- package/theme/styles/vica.css +52 -40
- package/theme/styles/websg.css +52 -40
- package/theme/styles/wise.css +52 -40
- package/theme/styles/wogaa.css +52 -40
- package/theme/theme-provider/preset.d.ts +2 -0
- package/theme/tokens/colour.d.ts +6 -0
- package/theme/tokens/colour.js +1 -1
- package/theme/tokens/colour.js.map +1 -1
- package/theme/tokens/radius.d.ts +3 -0
- package/theme/tokens/radius.js +1 -1
- package/theme/tokens/radius.js.map +1 -1
- package/theme/types.d.ts +9 -3
- package/theme/types.js +1 -1
- package/theme/types.js.map +1 -1
- package/breadcrumb/breadcrumb.styles_1nl4aua.css +0 -18
- package/cjs/breadcrumb/breadcrumb.styles_1nl4aua.css +0 -18
- package/cjs/file-download/file-list-card/file-list-card.styles_18j2gut.css +0 -16
- package/cjs/file-upload/file-item-edit.js +0 -2
- package/cjs/file-upload/file-item-edit.js.map +0 -1
- package/cjs/file-upload/file-item-edit.styles.js +0 -2
- package/cjs/file-upload/file-item-edit.styles.js.map +0 -1
- package/cjs/file-upload/file-item-edit.styles_19bvztn.css +0 -11
- package/cjs/file-upload/file-list/file-list.styles_1w7so98.css +0 -3
- package/cjs/file-upload/file-list-item/file-list-item.styles_kgtfke.css +0 -17
- package/cjs/local-nav/local-nav-menu/local-nav-menu.styles_pq19dh.css +0 -5
- package/cjs/menu/menu-content.styles_p7ijll.css +0 -2
- package/cjs/menu/menu-link.styles_hfxoez.css +0 -2
- package/cjs/menu/menu-section.styles_g7my4d.css +0 -3
- package/file-download/file-list-card/file-list-card.styles_18j2gut.css +0 -16
- package/file-upload/file-item-edit.d.ts +0 -14
- package/file-upload/file-item-edit.js +0 -2
- package/file-upload/file-item-edit.js.map +0 -1
- package/file-upload/file-item-edit.styles.d.ts +0 -9
- package/file-upload/file-item-edit.styles.js +0 -2
- package/file-upload/file-item-edit.styles.js.map +0 -1
- package/file-upload/file-item-edit.styles_19bvztn.css +0 -11
- package/file-upload/file-list/file-list.styles_1w7so98.css +0 -3
- package/file-upload/file-list-item/file-list-item.styles_kgtfke.css +0 -17
- package/local-nav/local-nav-menu/local-nav-menu.styles_pq19dh.css +0 -5
- package/menu/menu-content.styles_p7ijll.css +0 -2
- package/menu/menu-link.styles_hfxoez.css +0 -2
- package/menu/menu-section.styles_g7my4d.css +0 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-list.js","sources":["../../../src/file-upload/file-list/file-list.tsx"],"sourcesContent":["import type { DragEndEvent, DragStartEvent } from \"@dnd-kit/core\";\nimport {\n DndContext,\n KeyboardSensor,\n TouchSensor,\n useSensor,\n useSensors,\n} from \"@dnd-kit/core\";\nimport {\n arrayMove,\n SortableContext,\n sortableKeyboardCoordinates,\n verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport clsx from \"clsx\";\nimport type React from \"react\";\nimport {\n forwardRef,\n useContext,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\n\nimport type { FormLabelProps } from \"../../form/form-label/types\";\nimport { VisuallyHidden } from \"../../shared/accessibility\";\nimport { FileUploadContext } from \"../context\";\nimport { MouseSensor } from \"../custom-sensors\";\nimport { FileItemEdit } from \"../file-item-edit\";\nimport { FileListItem } from \"../file-list-item\";\nimport { FileUploadHelper } from \"../helper\";\nimport type { FileItemProps } from \"../types\";\nimport * as styles from \"./file-list.styles\";\n\n// =============================================================================\n// INTERFACES\n// =============================================================================\ntype RenderMode = \"edit\" | \"display\" | \"error\";\n\ntype FileItemRenderModes = Record<string, RenderMode>;\ntype FileEditedDescriptions = Record<string, string>;\n\ntype RenderItem = FileItemProps | FileItemProps[];\n\ninterface Props {\n fileItems: FileItemProps[] | undefined;\n editableFileItems: boolean;\n fileDescriptionMaxLength?: number | undefined;\n descriptionRequired?: boolean | undefined;\n descriptionLabel?: FormLabelProps | undefined;\n sortable?: boolean | undefined;\n disabled?: boolean | undefined;\n readOnly?: boolean | undefined;\n onItemUpdate: (item: FileItemProps) => void;\n onItemDelete: (item: FileItemProps) => void;\n onSort?: ((reorderedFileItems: FileItemProps[]) => void) | undefined;\n}\n\ntype AnnouncementProgress = Record<\n string,\n {\n progress: number;\n timestamp: number;\n status: \"in-progress\" | \"complete\" | \"error\";\n }\n>;\n\nexport interface FileListRef {\n focus: () => void;\n}\n\n// =============================================================================\n// COMPONENT\n// =============================================================================\n\nfunction Component(\n {\n fileItems = [],\n editableFileItems,\n fileDescriptionMaxLength,\n descriptionRequired,\n descriptionLabel,\n sortable,\n disabled,\n readOnly,\n onItemUpdate,\n onItemDelete,\n onSort,\n }: Props,\n ref: React.Ref<FileListRef>\n) {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const [renderModes, setRenderModes] = useState<FileItemRenderModes>({});\n const { setActiveId } = useContext(FileUploadContext);\n\n // Progress announcement state (for aria-live) - announces start and completion only\n const [progressAnnouncement, setProgressAnnouncement] = useState(\"\");\n const lastAnnouncedRef = useRef<AnnouncementProgress>({});\n\n useImperativeHandle(ref, () => ({\n focus: () => {\n wrapperRef.current?.focus();\n },\n }));\n const { width: wrapperWidth = 0, ref: wrapperRef } = useResizeDetector();\n\n // Keep track of edited description without re-rendering\n const descriptionsValueRef = useRef<FileEditedDescriptions>({});\n\n /**\n * As the default drag sensors interfere with click events\n * on the file items, we'll need to configure the sensor to\n * only activate the drag if the mouse moves a certain distance\n */\n const sensors = useSensors(\n useSensor(MouseSensor, {\n activationConstraint: {\n distance: 8, // mouse drag of 8px then activate the drag event\n },\n }),\n useSensor(TouchSensor, {\n activationConstraint: {\n delay: 150,\n tolerance: 5,\n },\n }),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n })\n );\n\n // =========================================================================\n // REF METHODS\n // =========================================================================\n const removeDescription = (itemId: string) => {\n delete descriptionsValueRef.current[itemId];\n };\n\n const shallowCompareRenderModes = (\n prev: FileItemRenderModes,\n next: FileItemRenderModes\n ) => {\n const prevKeys = Object.keys(prev);\n const nextKeys = Object.keys(next);\n if (prevKeys.length !== nextKeys.length) {\n return false;\n }\n for (const k of nextKeys) {\n if (prev[k] !== next[k]) {\n return false;\n }\n }\n return true;\n };\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n const nextModes = getItemsRenderMode(fileItems);\n const prevModes = renderModes;\n // We perform shallowCompare to avoid infinite re-render loop\n if (shallowCompareRenderModes(prevModes, nextModes)) {\n return;\n }\n setRenderModes(nextModes);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [fileItems, editableFileItems, readOnly]);\n\n // Progress announcements only at start and completion\n useEffect(() => {\n if (!fileItems || fileItems.length === 0) {\n setProgressAnnouncement(\"\");\n return;\n }\n const now = Date.now();\n const messages: string[] = [];\n\n for (const item of fileItems) {\n const fileStatus = lastAnnouncedRef.current[item.id];\n\n if (item.errorMessage) {\n if (fileStatus?.status !== \"error\") {\n messages.push(\n typeof item.errorMessage === \"string\"\n ? `Error uploading ${item.name}: ${item.errorMessage}`\n : `Error uploading ${item.name}`\n );\n lastAnnouncedRef.current[item.id] = {\n progress: item.progress ?? 1,\n timestamp: now,\n status: \"error\",\n };\n }\n continue;\n }\n\n if (item.progress === undefined) {\n continue;\n }\n\n if (item.progress >= 1) {\n if (fileStatus?.status !== \"complete\") {\n messages.push(`${item.name} upload is complete`);\n lastAnnouncedRef.current[item.id] = {\n progress: 1,\n timestamp: now,\n status: \"complete\",\n };\n }\n continue;\n }\n\n // In progress - only announce start, not progress updates\n if (typeof item.progress === \"number\" && item.progress < 1) {\n // Only announce when starting upload (no previous status or status was not in-progress)\n const shouldAnnounce =\n !fileStatus || fileStatus.status !== \"in-progress\";\n\n if (shouldAnnounce) {\n messages.push(`Starting upload of ${item.name}`);\n lastAnnouncedRef.current[item.id] = {\n progress: item.progress,\n timestamp: now,\n status: \"in-progress\",\n };\n }\n }\n }\n\n if (messages.length > 0) {\n // Update aria-live region once with aggregated message\n setProgressAnnouncement(messages.join(\", \"));\n }\n }, [fileItems]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleSaveEdit = (item: FileItemProps) => (description: string) => {\n updateRenderModes(item.id, \"display\");\n removeDescription(item.id);\n\n const updatedItem = { ...item, description };\n onItemUpdate(updatedItem);\n };\n\n const handleBlurEdit = (item: FileItemProps) => (value: string) => {\n descriptionsValueRef.current[item.id] = value;\n };\n\n const handleCancel = (item: FileItemProps) => () => {\n if (!item.description || item.description.length === 0) {\n // New addition\n onItemDelete(item);\n } else {\n updateRenderModes(item.id, \"display\");\n }\n removeDescription(item.id);\n };\n\n const handleInitiateEdit = (item: FileItemProps) => () => {\n updateRenderModes(item.id, \"edit\");\n };\n\n const handleDelete = (item: FileItemProps) => () => {\n onItemDelete(item);\n if (wrapperRef.current) {\n wrapperRef.current.focus();\n }\n };\n\n const handleDragEnd = (event: DragEndEvent) => {\n if (onSort && fileItems) {\n const { active, over } = event;\n\n if (over && active.id !== over.id) {\n const oldIndex = fileItems.findIndex(\n (item) => item.id === active.id\n );\n const newIndex = fileItems.findIndex(\n (item) => item.id === over.id\n );\n\n const updatedFileItems = arrayMove(\n fileItems,\n oldIndex,\n newIndex\n );\n\n onSort(updatedFileItems);\n }\n }\n\n setActiveId(undefined);\n };\n\n const handleDragStart = (event: DragStartEvent) => {\n const { active } = event;\n setActiveId(active.id as string);\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const checkEditable = (item: FileItemProps) => {\n return (\n editableFileItems &&\n FileUploadHelper.isSupportedImageType(item.type)\n );\n };\n\n const shouldRenderEditMode = (item: FileItemProps) => {\n return (\n !item.errorMessage &&\n !readOnly &&\n !(typeof item.progress === \"number\" && item.progress < 1) &&\n checkEditable(item) &&\n !item.description\n );\n };\n\n const getItemsRenderMode = (\n fileItems: FileItemProps[] | undefined\n ): FileItemRenderModes => {\n if (!fileItems || fileItems.length === 0) return {};\n\n const newRenderModes: FileItemRenderModes = {};\n\n for (const item of fileItems) {\n if (item.errorMessage) {\n newRenderModes[item.id] = \"error\";\n } else if (!renderModes[item.id]) {\n newRenderModes[item.id] = shouldRenderEditMode(item)\n ? \"edit\"\n : \"display\";\n } else {\n newRenderModes[item.id] = renderModes[item.id];\n }\n }\n\n return newRenderModes;\n };\n\n const updateRenderModes = (itemId: string, mode: RenderMode) => {\n setRenderModes((prevRenderModes) => {\n return {\n ...prevRenderModes,\n [itemId]: mode,\n };\n });\n };\n\n /**\n * Due to a UI requirement, we will render the items\n * with edit modes as a group\n */\n const getArrangedItems = (\n fileItems: FileItemProps[] | undefined,\n renderModes: FileItemRenderModes\n ) => {\n if (!fileItems || fileItems.length === 0) return [];\n\n const arrangedItems: RenderItem[] = [];\n\n for (const fileItem of fileItems) {\n if (renderModes[fileItem.id] === \"edit\") {\n const previousElement = arrangedItems[arrangedItems.length - 1];\n if (Array.isArray(previousElement)) {\n previousElement.push(fileItem);\n } else {\n arrangedItems.push([fileItem]);\n }\n } else {\n arrangedItems.push(fileItem);\n }\n }\n\n return arrangedItems;\n };\n\n const areAllItemsInDisplayViews = () => {\n return Object.values(renderModes).every((mode) => mode === \"display\");\n };\n\n const shouldEnableSort = () => {\n return (\n fileItems &&\n fileItems.length > 1 &&\n sortable &&\n areAllItemsInDisplayViews()\n );\n };\n\n /**\n * If there are no files, return \"No files uploaded\".\n * If readOnly is true, return \"Read-only file list\".\n * If there are files, return a summary of the file statuses.\n * For example, \"File list. 2 completed files, 1 file in progress, 1 file with error\".\n *\n * @returns aria label\n */\n const getWrapperAriaLabel = () => {\n if (fileItems.length === 0) {\n return \"No files uploaded\";\n }\n const completedCount = fileItems.filter(\n (item) =>\n !item?.errorMessage &&\n (item.progress === 1 || item.progress === undefined)\n ).length;\n const inProgressCount = fileItems.filter(\n (item) => typeof item.progress === \"number\" && item.progress < 1\n ).length;\n const errorCount = fileItems.filter((item) => item.errorMessage).length;\n if (completedCount === 0 && inProgressCount === 0 && errorCount === 0) {\n return `File list`;\n }\n const completedText =\n completedCount > 0 ? `${completedCount} completed files` : \"\";\n const inProgressText =\n inProgressCount > 0 ? `${inProgressCount} file in progress` : \"\";\n const errorText =\n errorCount > 0\n ? `${errorCount} ${\n errorCount > 1 ? \"files\" : \"file\"\n } with error`\n : \"\";\n const parts = [completedText, inProgressText, errorText].filter(\n Boolean\n );\n const prefix = readOnly ? \"Read-only file list\" : \"File list\";\n return `${prefix}. ${parts.join(\", \")}`;\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderItemsInEditMode = (\n fileItems: FileItemProps[],\n keyToUse: number\n ) => {\n const itemsToRender = fileItems.map((item) => {\n const updatedFileItem = { ...item };\n if (descriptionsValueRef.current[item.id] !== undefined) {\n updatedFileItem.description =\n descriptionsValueRef.current[item.id];\n }\n\n return (\n <FileItemEdit\n key={item.id}\n fileItem={updatedFileItem}\n wrapperWidth={wrapperWidth}\n fileDescriptionMaxLength={fileDescriptionMaxLength}\n descriptionRequired={descriptionRequired}\n descriptionLabel={descriptionLabel}\n onSave={handleSaveEdit(item)}\n onCancel={handleCancel(item)}\n onBlur={handleBlurEdit(item)}\n />\n );\n });\n\n return (\n <li\n key={`editable-${keyToUse}`}\n className={styles.editableItemsContainer}\n >\n <ul>{itemsToRender}</ul>\n </li>\n );\n };\n\n const renderItems = () => {\n const arrangedItems = getArrangedItems(fileItems, renderModes);\n\n if (arrangedItems.length === 0) return null;\n\n return arrangedItems.map((item, index) => {\n if (Array.isArray(item)) {\n return renderItemsInEditMode(item, index);\n } else {\n return (\n <FileListItem\n key={item.id}\n fileItem={item}\n editable={checkEditable(item)}\n wrapperWidth={wrapperWidth}\n sortable={shouldEnableSort()}\n disabled={disabled}\n readOnly={readOnly}\n descriptionLabel={descriptionLabel}\n onDelete={handleDelete(item)}\n onEditClick={handleInitiateEdit(item)}\n />\n );\n }\n });\n };\n\n /**\n * Renders the progress status of each file upload.\n * In progress: 25% complete for uploading filename.pdf\n * Complete: filename.pdf upload is complete\n * Error: Error uploading filename.pdf: error message\n *\n * @returns A visually hidden element announcing the progress status.\n */\n const renderProgressStatus = () => (\n <VisuallyHidden aria-live=\"polite\" aria-atomic=\"true\">\n {progressAnnouncement}\n </VisuallyHidden>\n );\n\n const renderItemsWithWrapper = () => {\n return (\n <>\n {renderProgressStatus()}\n <ul\n tabIndex={-1}\n className={clsx(\n styles.listWrapper,\n readOnly && styles.listWrapperReadOnly\n )}\n ref={wrapperRef}\n aria-label={getWrapperAriaLabel()}\n >\n {renderItems()}\n </ul>\n </>\n );\n };\n\n if (disabled || readOnly || !shouldEnableSort()) {\n return renderItemsWithWrapper();\n } else {\n return (\n <DndContext\n sensors={sensors}\n onDragEnd={handleDragEnd}\n onDragStart={handleDragStart}\n >\n <SortableContext\n items={fileItems}\n strategy={verticalListSortingStrategy}\n >\n {renderItemsWithWrapper()}\n </SortableContext>\n </DndContext>\n );\n }\n}\n\nexport const FileList = forwardRef<FileListRef, Props>(Component);\n"],"names":["FileList","forwardRef","fileItems","editableFileItems","fileDescriptionMaxLength","descriptionRequired","descriptionLabel","sortable","disabled","readOnly","onItemUpdate","onItemDelete","onSort","ref","renderModes","setRenderModes","useState","setActiveId","useContext","FileUploadContext","progressAnnouncement","setProgressAnnouncement","lastAnnouncedRef","useRef","useImperativeHandle","focus","_a","wrapperRef","current","width","wrapperWidth","useResizeDetector","descriptionsValueRef","sensors","useSensors","useSensor","MouseSensor","activationConstraint","distance","TouchSensor","delay","tolerance","KeyboardSensor","coordinateGetter","sortableKeyboardCoordinates","removeDescription","itemId","useEffect","nextModes","getItemsRenderMode","prev","next","prevKeys","Object","keys","nextKeys","length","k","shallowCompareRenderModes","now","Date","messages","item","fileStatus","id","errorMessage","status","push","name","progress","timestamp","undefined","join","handleSaveEdit","description","updateRenderModes","updatedItem","assign","handleBlurEdit","value","handleCancel","handleInitiateEdit","handleDelete","handleDragEnd","event","active","over","oldIndex","findIndex","newIndex","updatedFileItems","arrayMove","handleDragStart","checkEditable","FileUploadHelper","isSupportedImageType","type","shouldRenderEditMode","newRenderModes","mode","prevRenderModes","shouldEnableSort","values","every","getWrapperAriaLabel","completedCount","filter","inProgressCount","errorCount","parts","Boolean","renderItems","arrangedItems","fileItem","previousElement","Array","isArray","getArrangedItems","map","index","keyToUse","itemsToRender","updatedFileItem","_jsx","FileItemEdit","onSave","onCancel","onBlur","className","styles.editableItemsContainer","children","renderItemsInEditMode","FileListItem","editable","onDelete","onEditClick","renderItemsWithWrapper","_jsxs","_Fragment","VisuallyHidden","tabIndex","clsx","styles.listWrapper","styles.listWrapperReadOnly","DndContext","onDragEnd","onDragStart","SortableContext","items","strategy","verticalListSortingStrategy"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"file-list.js","sources":["../../../src/file-upload/file-list/file-list.tsx"],"sourcesContent":["import type { DragEndEvent, DragStartEvent } from \"@dnd-kit/core\";\nimport {\n DndContext,\n KeyboardSensor,\n TouchSensor,\n useSensor,\n useSensors,\n} from \"@dnd-kit/core\";\nimport {\n arrayMove,\n SortableContext,\n sortableKeyboardCoordinates,\n verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport clsx from \"clsx\";\nimport type React from \"react\";\nimport {\n forwardRef,\n useContext,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\n\nimport type { FormLabelProps } from \"../../form/form-label/types\";\nimport { VisuallyHidden } from \"../../shared/accessibility\";\nimport { FileUploadContext } from \"../context\";\nimport { MouseSensor } from \"../custom-sensors\";\nimport { FileListItem } from \"../file-list-item\";\nimport type { FileItemMode } from \"../file-list-item/types\";\nimport { FileUploadHelper } from \"../helper\";\nimport type { FileItemProps } from \"../types\";\nimport * as styles from \"./file-list.styles\";\n\n// =============================================================================\n// INTERFACES\n// =============================================================================\ntype FileEditedDescriptions = Record<string, string>;\n\ninterface Props {\n fileItems: FileItemProps[] | undefined;\n editableFileItems: boolean;\n fileDescriptionMaxLength?: number | undefined;\n descriptionRequired?: boolean | undefined;\n descriptionLabel?: FormLabelProps | undefined;\n sortable?: boolean | undefined;\n disabled?: boolean | undefined;\n readOnly?: boolean | undefined;\n onItemUpdate: (item: FileItemProps) => void;\n onItemDelete: (item: FileItemProps) => void;\n onSort?: ((reorderedFileItems: FileItemProps[]) => void) | undefined;\n}\n\ntype AnnouncementProgress = Record<\n string,\n {\n progress: number;\n timestamp: number;\n status: \"in-progress\" | \"complete\" | \"error\";\n }\n>;\n\nexport interface FileListRef {\n focus: () => void;\n}\n\n// =============================================================================\n// COMPONENT\n// =============================================================================\n\nfunction Component(\n {\n fileItems = [],\n editableFileItems,\n fileDescriptionMaxLength,\n descriptionRequired,\n descriptionLabel,\n sortable,\n disabled,\n readOnly,\n onItemUpdate,\n onItemDelete,\n onSort,\n }: Props,\n ref: React.Ref<FileListRef>\n) {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const { setActiveId } = useContext(FileUploadContext);\n const [editingCount, setEditingCount] = useState(0);\n\n // Progress announcement state (for aria-live) - announces start and completion only\n const [progressAnnouncement, setProgressAnnouncement] = useState(\"\");\n const lastAnnouncedRef = useRef<AnnouncementProgress>({});\n\n useImperativeHandle(ref, () => ({\n focus: () => {\n wrapperRef.current?.focus();\n },\n }));\n const { width: wrapperWidth = 0, ref: wrapperRef } = useResizeDetector();\n\n // Keep track of edited description without re-rendering\n const descriptionsValueRef = useRef<FileEditedDescriptions>({});\n\n /**\n * As the default drag sensors interfere with click events\n * on the file items, we'll need to configure the sensor to\n * only activate the drag if the mouse moves a certain distance\n */\n const sensors = useSensors(\n useSensor(MouseSensor, {\n activationConstraint: {\n distance: 8, // mouse drag of 8px then activate the drag event\n },\n }),\n useSensor(TouchSensor, {\n activationConstraint: {\n delay: 150,\n tolerance: 5,\n },\n }),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n })\n );\n\n // =========================================================================\n // REF METHODS\n // =========================================================================\n const removeDescription = (itemId: string) => {\n delete descriptionsValueRef.current[itemId];\n };\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n // Progress announcements only at start and completion\n useEffect(() => {\n if (!fileItems || fileItems.length === 0) {\n setProgressAnnouncement(\"\");\n return;\n }\n const now = Date.now();\n const messages: string[] = [];\n\n for (const item of fileItems) {\n const fileStatus = lastAnnouncedRef.current[item.id];\n\n if (item.errorMessage) {\n if (fileStatus?.status !== \"error\") {\n messages.push(\n typeof item.errorMessage === \"string\"\n ? `Error uploading ${item.name}: ${item.errorMessage}`\n : `Error uploading ${item.name}`\n );\n lastAnnouncedRef.current[item.id] = {\n progress: item.progress ?? 1,\n timestamp: now,\n status: \"error\",\n };\n }\n continue;\n }\n\n if (item.progress === undefined) {\n continue;\n }\n\n if (item.progress >= 1) {\n if (fileStatus?.status !== \"complete\") {\n messages.push(`${item.name} upload is complete`);\n lastAnnouncedRef.current[item.id] = {\n progress: 1,\n timestamp: now,\n status: \"complete\",\n };\n }\n continue;\n }\n\n // In progress - only announce start, not progress updates\n if (typeof item.progress === \"number\" && item.progress < 1) {\n // Only announce when starting upload (no previous status or status was not in-progress)\n const shouldAnnounce =\n !fileStatus || fileStatus.status !== \"in-progress\";\n\n if (shouldAnnounce) {\n messages.push(`Starting upload of ${item.name}`);\n lastAnnouncedRef.current[item.id] = {\n progress: item.progress,\n timestamp: now,\n status: \"in-progress\",\n };\n }\n }\n }\n\n if (messages.length > 0) {\n // Update aria-live region once with aggregated message\n setProgressAnnouncement(messages.join(\", \"));\n }\n }, [fileItems]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleSaveEdit = (item: FileItemProps) => (description: string) => {\n removeDescription(item.id);\n const updatedItem = { ...item, description };\n onItemUpdate(updatedItem);\n };\n\n const handleBlurEdit = (item: FileItemProps) => (value: string) => {\n descriptionsValueRef.current[item.id] = value;\n };\n\n const handleCancel = (item: FileItemProps) => () => {\n removeDescription(item.id);\n if (!item.description || item.description.length === 0) {\n onItemDelete(item);\n }\n };\n\n const handleModeChange = (mode: FileItemMode) => {\n setEditingCount((prev) =>\n mode === \"edit\" ? prev + 1 : Math.max(0, prev - 1)\n );\n };\n\n const handleDelete = (item: FileItemProps) => () => {\n onItemDelete(item);\n if (wrapperRef.current) {\n wrapperRef.current.focus();\n }\n };\n\n const handleDragEnd = (event: DragEndEvent) => {\n if (onSort && fileItems) {\n const { active, over } = event;\n\n if (over && active.id !== over.id) {\n const oldIndex = fileItems.findIndex(\n (item) => item.id === active.id\n );\n const newIndex = fileItems.findIndex(\n (item) => item.id === over.id\n );\n\n const updatedFileItems = arrayMove(\n fileItems,\n oldIndex,\n newIndex\n );\n\n onSort(updatedFileItems);\n }\n }\n\n setActiveId(undefined);\n };\n\n const handleDragStart = (event: DragStartEvent) => {\n const { active } = event;\n setActiveId(active.id as string);\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const checkEditable = (item: FileItemProps) => {\n return (\n editableFileItems &&\n FileUploadHelper.isSupportedImageType(item.type)\n );\n };\n\n const areAllItemsInDisplayViews = () => {\n if (editingCount > 0) return false;\n return !fileItems.some((item) => !!item.errorMessage);\n };\n\n const shouldEnableSort = () => {\n return (\n fileItems &&\n fileItems.length > 1 &&\n sortable &&\n !readOnly &&\n areAllItemsInDisplayViews()\n );\n };\n\n /**\n * If there are no files, return \"No files uploaded\".\n * If readOnly is true, return \"Read-only file list\".\n * If there are files, return a summary of the file statuses.\n * For example, \"File list. 2 completed files, 1 file in progress, 1 file with error\".\n *\n * @returns aria label\n */\n const getWrapperAriaLabel = () => {\n if (fileItems.length === 0) {\n return \"No files uploaded\";\n }\n const completedCount = fileItems.filter(\n (item) =>\n !item?.errorMessage &&\n (item.progress === 1 || item.progress === undefined)\n ).length;\n const inProgressCount = fileItems.filter(\n (item) => typeof item.progress === \"number\" && item.progress < 1\n ).length;\n const errorCount = fileItems.filter((item) => item.errorMessage).length;\n if (completedCount === 0 && inProgressCount === 0 && errorCount === 0) {\n return `File list`;\n }\n const completedText =\n completedCount > 0 ? `${completedCount} completed files` : \"\";\n const inProgressText =\n inProgressCount > 0 ? `${inProgressCount} file in progress` : \"\";\n const errorText =\n errorCount > 0\n ? `${errorCount} ${\n errorCount > 1 ? \"files\" : \"file\"\n } with error`\n : \"\";\n const parts = [completedText, inProgressText, errorText].filter(\n Boolean\n );\n const prefix = readOnly ? \"Read-only file list\" : \"File list\";\n return `${prefix}. ${parts.join(\", \")}`;\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderItems = () => {\n if (fileItems.length === 0) return null;\n\n return fileItems.map((item) => {\n const updatedFileItem = { ...item };\n if (descriptionsValueRef.current[item.id] !== undefined) {\n updatedFileItem.description =\n descriptionsValueRef.current[item.id];\n }\n\n return (\n <FileListItem\n key={item.id}\n fileItem={updatedFileItem}\n editable={checkEditable(item)}\n wrapperWidth={wrapperWidth}\n sortable={shouldEnableSort()}\n disabled={disabled}\n readOnly={readOnly}\n descriptionLabel={descriptionLabel}\n fileDescriptionMaxLength={fileDescriptionMaxLength}\n descriptionRequired={descriptionRequired}\n onDelete={handleDelete(item)}\n onSave={handleSaveEdit(item)}\n onCancel={handleCancel(item)}\n onBlur={handleBlurEdit(item)}\n onModeChange={handleModeChange}\n />\n );\n });\n };\n\n /**\n * Renders the progress status of each file upload.\n * In progress: 25% complete for uploading filename.pdf\n * Complete: filename.pdf upload is complete\n * Error: Error uploading filename.pdf: error message\n *\n * @returns A visually hidden element announcing the progress status.\n */\n const renderProgressStatus = () => (\n <VisuallyHidden aria-live=\"polite\" aria-atomic=\"true\">\n {progressAnnouncement}\n </VisuallyHidden>\n );\n\n const renderItemsWithWrapper = () => {\n return (\n <>\n {renderProgressStatus()}\n <ul\n tabIndex={-1}\n className={clsx(\n styles.listWrapper,\n readOnly && styles.listWrapperReadOnly\n )}\n ref={wrapperRef}\n aria-label={getWrapperAriaLabel()}\n >\n {renderItems()}\n </ul>\n </>\n );\n };\n\n return (\n <DndContext\n sensors={sensors}\n onDragEnd={handleDragEnd}\n onDragStart={handleDragStart}\n >\n <SortableContext\n items={fileItems}\n strategy={verticalListSortingStrategy}\n >\n {renderItemsWithWrapper()}\n </SortableContext>\n </DndContext>\n );\n}\n\nexport const FileList = forwardRef<FileListRef, Props>(Component);\n"],"names":["FileList","forwardRef","fileItems","editableFileItems","fileDescriptionMaxLength","descriptionRequired","descriptionLabel","sortable","disabled","readOnly","onItemUpdate","onItemDelete","onSort","ref","setActiveId","useContext","FileUploadContext","editingCount","setEditingCount","useState","progressAnnouncement","setProgressAnnouncement","lastAnnouncedRef","useRef","useImperativeHandle","focus","_a","wrapperRef","current","width","wrapperWidth","useResizeDetector","descriptionsValueRef","sensors","useSensors","useSensor","MouseSensor","activationConstraint","distance","TouchSensor","delay","tolerance","KeyboardSensor","coordinateGetter","sortableKeyboardCoordinates","removeDescription","itemId","useEffect","length","now","Date","messages","item","fileStatus","id","errorMessage","status","push","name","progress","timestamp","undefined","join","handleSaveEdit","description","updatedItem","Object","assign","handleBlurEdit","value","handleCancel","handleModeChange","mode","prev","Math","max","handleDelete","checkEditable","FileUploadHelper","isSupportedImageType","type","shouldEnableSort","some","getWrapperAriaLabel","completedCount","filter","inProgressCount","errorCount","parts","Boolean","_jsx","DndContext","onDragEnd","event","active","over","oldIndex","findIndex","newIndex","updatedFileItems","arrayMove","onDragStart","children","SortableContext","items","strategy","verticalListSortingStrategy","_jsxs","_Fragment","VisuallyHidden","tabIndex","className","clsx","styles.listWrapper","styles.listWrapperReadOnly","map","updatedFileItem","FileListItem","fileItem","editable","onDelete","onSave","onCancel","onBlur","onModeChange"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"./file-list.
|
|
1
|
+
import"./file-list.styles_1xbypnh.css";const l="l14goqmf",s="l1spcgo1";export{l as listWrapper,s as listWrapperReadOnly};
|
|
2
2
|
//# sourceMappingURL=file-list.styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-list.styles.js","sources":["../../../src/file-upload/file-list/file-list.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Spacing } from \"../../theme\";\n\nexport const listWrapper = css`\n list-style-type: none;\n margin-bottom: ${Spacing[\"spacing-32\"]};\n`;\n\nexport const listWrapperReadOnly = css`\n margin-bottom: 0;\n`;\n
|
|
1
|
+
{"version":3,"file":"file-list.styles.js","sources":["../../../src/file-upload/file-list/file-list.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Spacing } from \"../../theme\";\n\nexport const listWrapper = css`\n list-style-type: none;\n margin-bottom: ${Spacing[\"spacing-32\"]};\n`;\n\nexport const listWrapperReadOnly = css`\n margin-bottom: 0;\n`;\n"],"names":["listWrapper","listWrapperReadOnly"],"mappings":"4EAIO,MAAMA,EAAW,WAKXC,EAAmB"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
interface BaseProps {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
}
|
|
5
|
+
interface ErrorActionProps extends BaseProps {
|
|
6
|
+
mode: "error";
|
|
7
|
+
errorMessage?: string | React.ReactNode | undefined;
|
|
8
|
+
onDelete: () => void;
|
|
9
|
+
}
|
|
10
|
+
interface DisplayActionProps extends BaseProps {
|
|
11
|
+
mode: "display";
|
|
12
|
+
inline?: boolean | undefined;
|
|
13
|
+
editable?: boolean | undefined;
|
|
14
|
+
isLoading: boolean;
|
|
15
|
+
progress: number;
|
|
16
|
+
disabled: boolean;
|
|
17
|
+
onDelete: () => void;
|
|
18
|
+
onEdit?: (() => void) | undefined;
|
|
19
|
+
onKeyDown?: ((event: React.KeyboardEvent<HTMLButtonElement>) => void) | undefined;
|
|
20
|
+
}
|
|
21
|
+
interface EditActionProps extends BaseProps {
|
|
22
|
+
mode: "edit";
|
|
23
|
+
hasThumbnail: boolean;
|
|
24
|
+
disableSave: boolean;
|
|
25
|
+
onSave: () => void;
|
|
26
|
+
onCancel: () => void;
|
|
27
|
+
}
|
|
28
|
+
type FileItemActionsProps = ErrorActionProps | DisplayActionProps | EditActionProps;
|
|
29
|
+
export declare const FileItemActions: (props: FileItemActionsProps) => import("react/jsx-runtime").JSX.Element;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{jsx as e,jsxs as t,Fragment as a}from"react/jsx-runtime";import{BinIcon as i}from"@lifesg/react-icons/bin";import{PencilIcon as d}from"@lifesg/react-icons/pencil";import l from"clsx";import{Button as n}from"../../button/button.js";import{ProgressBar as o}from"../../shared/progress-bar/progress-bar.js";import{actionContainer as s,iconButton as r,actionButton as c,actionButtonsSection as b,actionButtonsSectionWithThumbnail as m,inlineActionContainer as y}from"./file-item-actions.styles.js";const p=p=>{const{mode:u,id:h,name:g}=p;if("error"===u)return e("div",{className:s,children:e(n,{"data-testid":`${h}-error-delete-button`,"data-no-dnd":"true",type:"button",styleType:"light",sizeType:"small","aria-label":`delete ${g}, error: ${p.errorMessage}`,onClick:p.onDelete,className:r,icon:e(i,{"aria-hidden":!0})})});if("edit"===u)return t("div",{className:l(b,p.hasThumbnail&&m),children:[e(n,{"data-testid":`${h}-save-button`,type:"button",sizeType:"small",disabled:p.disableSave,onClick:p.onSave,className:c,children:"Save"}),e(n,{type:"button",sizeType:"small",styleType:"secondary","data-testid":`${h}-cancel-button`,onClick:p.onCancel,className:c,children:"Cancel"})]});if(p.inline)return t("div",{className:y,children:[e(n,{"data-testid":`${h}-edit-button`,"data-no-dnd":"true",type:"button",styleType:"light",sizeType:"small","aria-label":`edit ${g}`,disabled:p.disabled,onClick:p.onEdit,onKeyDown:p.onKeyDown,icon:e(d,{"aria-hidden":!0}),className:r},"edit"),e(n,{"data-testid":`${h}-delete-button`,"data-no-dnd":"true",type:"button",styleType:"light",sizeType:"small","aria-label":`delete ${g}`,disabled:p.disabled,onClick:p.onDelete,onKeyDown:p.onKeyDown,icon:e(i,{"aria-hidden":!0}),className:r},"delete")]});let T;return T=p.isLoading?e(o,{progress:p.progress,"data-testid":`${h}-progress-bar`}):t(a,{children:[p.editable&&e(n,{"data-testid":`${h}-edit-button`,"data-no-dnd":"true",type:"button",styleType:"light",sizeType:"small","aria-label":`edit ${g}`,disabled:p.disabled,onClick:p.onEdit,onKeyDown:p.onKeyDown,icon:e(d,{"aria-hidden":!0}),className:r},"edit"),e(n,{"data-testid":`${h}-delete-button`,"data-no-dnd":"true",type:"button",styleType:"light",sizeType:"small","aria-label":`delete ${g}`,disabled:p.disabled,onClick:p.onDelete,onKeyDown:p.onKeyDown,icon:e(i,{"aria-hidden":!0}),className:r},"delete")]}),e("div",{className:s,"data-mobile-layout":p.isLoading?"loading":p.editable?"editable":void 0,children:T})};export{p as FileItemActions};
|
|
2
|
+
//# sourceMappingURL=file-item-actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-item-actions.js","sources":["../../../src/file-upload/file-list-item/file-item-actions.tsx"],"sourcesContent":["import { BinIcon } from \"@lifesg/react-icons/bin\";\nimport { PencilIcon } from \"@lifesg/react-icons/pencil\";\nimport clsx from \"clsx\";\n\nimport { Button } from \"../../button\";\nimport { ProgressBar } from \"../../shared/progress-bar\";\nimport * as styles from \"./file-item-actions.styles\";\n\n// =============================================================================\n// TYPES\n// =============================================================================\ninterface BaseProps {\n id: string;\n name: string;\n}\n\ninterface ErrorActionProps extends BaseProps {\n mode: \"error\";\n errorMessage?: string | React.ReactNode | undefined;\n onDelete: () => void;\n}\n\ninterface DisplayActionProps extends BaseProps {\n mode: \"display\";\n inline?: boolean | undefined;\n editable?: boolean | undefined;\n isLoading: boolean;\n progress: number;\n disabled: boolean;\n onDelete: () => void;\n onEdit?: (() => void) | undefined;\n onKeyDown?:\n | ((event: React.KeyboardEvent<HTMLButtonElement>) => void)\n | undefined;\n}\n\ninterface EditActionProps extends BaseProps {\n mode: \"edit\";\n hasThumbnail: boolean;\n disableSave: boolean;\n onSave: () => void;\n onCancel: () => void;\n}\n\ntype FileItemActionsProps =\n | ErrorActionProps\n | DisplayActionProps\n | EditActionProps;\n\n// =============================================================================\n// COMPONENT\n// =============================================================================\nexport const FileItemActions = (props: FileItemActionsProps) => {\n const { mode, id, name } = props;\n\n if (mode === \"error\") {\n return (\n <div className={styles.actionContainer}>\n <Button\n data-testid={`${id}-error-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}, error: ${props.errorMessage}`}\n onClick={props.onDelete}\n className={styles.iconButton}\n icon={<BinIcon aria-hidden />}\n />\n </div>\n );\n }\n\n if (mode === \"edit\") {\n return (\n <div\n className={clsx(\n styles.actionButtonsSection,\n props.hasThumbnail &&\n styles.actionButtonsSectionWithThumbnail\n )}\n >\n <Button\n data-testid={`${id}-save-button`}\n type=\"button\"\n sizeType=\"small\"\n disabled={props.disableSave}\n onClick={props.onSave}\n className={styles.actionButton}\n >\n Save\n </Button>\n <Button\n type=\"button\"\n sizeType=\"small\"\n styleType=\"secondary\"\n data-testid={`${id}-cancel-button`}\n onClick={props.onCancel}\n className={styles.actionButton}\n >\n Cancel\n </Button>\n </div>\n );\n }\n\n // Display mode\n if (props.inline) {\n return (\n <div className={styles.inlineActionContainer}>\n <Button\n key=\"edit\"\n data-testid={`${id}-edit-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`edit ${name}`}\n disabled={props.disabled}\n onClick={props.onEdit}\n onKeyDown={props.onKeyDown}\n icon={<PencilIcon aria-hidden />}\n className={styles.iconButton}\n />\n <Button\n key=\"delete\"\n data-testid={`${id}-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}`}\n disabled={props.disabled}\n onClick={props.onDelete}\n onKeyDown={props.onKeyDown}\n icon={<BinIcon aria-hidden />}\n className={styles.iconButton}\n />\n </div>\n );\n }\n\n const getActionContainerLayout = () => {\n if (props.isLoading) return \"loading\";\n if (props.editable) return \"editable\";\n return undefined;\n };\n\n let content: JSX.Element;\n\n if (props.isLoading) {\n content = (\n <ProgressBar\n progress={props.progress}\n data-testid={`${id}-progress-bar`}\n />\n );\n } else {\n content = (\n <>\n {props.editable && (\n <Button\n key=\"edit\"\n data-testid={`${id}-edit-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`edit ${name}`}\n disabled={props.disabled}\n onClick={props.onEdit}\n onKeyDown={props.onKeyDown}\n icon={<PencilIcon aria-hidden />}\n className={styles.iconButton}\n />\n )}\n <Button\n key=\"delete\"\n data-testid={`${id}-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}`}\n disabled={props.disabled}\n onClick={props.onDelete}\n onKeyDown={props.onKeyDown}\n icon={<BinIcon aria-hidden />}\n className={styles.iconButton}\n />\n </>\n );\n }\n\n return (\n <div\n className={styles.actionContainer}\n data-mobile-layout={getActionContainerLayout()}\n >\n {content}\n </div>\n );\n};\n"],"names":["FileItemActions","props","mode","id","name","_jsx","className","styles.actionContainer","children","Button","type","styleType","sizeType","errorMessage","onClick","onDelete","styles.iconButton","icon","BinIcon","_jsxs","clsx","styles.actionButtonsSection","hasThumbnail","styles.actionButtonsSectionWithThumbnail","disabled","disableSave","onSave","styles.actionButton","onCancel","inline","styles.inlineActionContainer","onEdit","onKeyDown","PencilIcon","content","isLoading","ProgressBar","progress","_Fragment","editable"],"mappings":"ofAoDO,MAAMA,EAAmBC,IAC5B,MAAMC,KAAEA,EAAIC,GAAEA,EAAEC,KAAEA,GAASH,EAE3B,GAAa,UAATC,EACA,OACIG,EAAA,MAAA,CAAKC,UAAWC,EAAsBC,SAClCH,EAACI,EAAM,CAAA,cACU,GAAGN,wBAAwB,cAC5B,OACZO,KAAK,SACLC,UAAU,QACVC,SAAS,qBACG,UAAUR,aAAgBH,EAAMY,eAC5CC,QAASb,EAAMc,SACfT,UAAWU,EACXC,KAAMZ,EAACa,EAAO,CAAA,eAAA,QAM9B,GAAa,SAAThB,EACA,OACIiB,EAAA,MAAA,CACIb,UAAWc,EACPC,EACApB,EAAMqB,cACFC,GACPf,SAAA,CAEDH,EAACI,EAAM,CAAA,cACU,GAAGN,gBAChBO,KAAK,SACLE,SAAS,QACTY,SAAUvB,EAAMwB,YAChBX,QAASb,EAAMyB,OACfpB,UAAWqB,EAAmBnB,SAAA,SAIlCH,EAACI,EAAM,CACHC,KAAK,SACLE,SAAS,QACTD,UAAU,YAAW,cACR,GAAGR,kBAChBW,QAASb,EAAM2B,SACftB,UAAWqB,EAAmBnB,SAAA,cAS9C,GAAIP,EAAM4B,OACN,OACIV,EAAA,MAAA,CAAKb,UAAWwB,EAA4BtB,SAAA,CACxCH,EAACI,EAAM,CAAA,cAEU,GAAGN,gBAAgB,cACpB,OACZO,KAAK,SACLC,UAAU,QACVC,SAAS,QAAO,aACJ,QAAQR,IACpBoB,SAAUvB,EAAMuB,SAChBV,QAASb,EAAM8B,OACfC,UAAW/B,EAAM+B,UACjBf,KAAMZ,EAAC4B,EAAU,CAAA,eAAA,IACjB3B,UAAWU,GAXP,QAaRX,EAACI,EAAM,CAAA,cAEU,GAAGN,kBAAkB,cACtB,OACZO,KAAK,SACLC,UAAU,QACVC,SAAS,QAAO,aACJ,UAAUR,IACtBoB,SAAUvB,EAAMuB,SAChBV,QAASb,EAAMc,SACfiB,UAAW/B,EAAM+B,UACjBf,KAAMZ,EAACa,EAAO,CAAA,eAAA,IACdZ,UAAWU,GAXP,aAuBpB,IAAIkB,EA8CJ,OA3CIA,EADAjC,EAAMkC,UAEF9B,EAAC+B,EAAW,CACRC,SAAUpC,EAAMoC,uBACH,GAAGlC,mBAKpBgB,EAAAmB,EAAA,CAAA9B,SAAA,CACKP,EAAMsC,UACHlC,EAACI,EAAM,CAAA,cAEU,GAAGN,gBAAgB,cACpB,OACZO,KAAK,SACLC,UAAU,QACVC,SAAS,QAAO,aACJ,QAAQR,IACpBoB,SAAUvB,EAAMuB,SAChBV,QAASb,EAAM8B,OACfC,UAAW/B,EAAM+B,UACjBf,KAAMZ,EAAC4B,EAAU,CAAA,eAAA,IACjB3B,UAAWU,GAXP,QAcZX,EAACI,EAAM,CAAA,cAEU,GAAGN,kBAAkB,cACtB,OACZO,KAAK,SACLC,UAAU,QACVC,SAAS,QAAO,aACJ,UAAUR,IACtBoB,SAAUvB,EAAMuB,SAChBV,QAASb,EAAMc,SACfiB,UAAW/B,EAAM+B,UACjBf,KAAMZ,EAACa,EAAO,CAAA,eAAA,IACdZ,UAAWU,GAXP,aAkBhBX,EAAA,MAAA,CACIC,UAAWC,EAAsB,qBArDjCN,EAAMkC,UAAkB,UACxBlC,EAAMsC,SAAiB,gBAA3B,EAqDkD/B,SAE7C0B,GACC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const actionContainer: import("@linaria/core").LinariaClassName;
|
|
2
|
+
export declare const inlineActionContainer: import("@linaria/core").LinariaClassName;
|
|
3
|
+
export declare const actionButtonsSection: import("@linaria/core").LinariaClassName;
|
|
4
|
+
export declare const actionButtonsSectionWithThumbnail: import("@linaria/core").LinariaClassName;
|
|
5
|
+
export declare const actionButton: import("@linaria/core").LinariaClassName;
|
|
6
|
+
export declare const iconButton: import("@linaria/core").LinariaClassName;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"./file-item-actions.styles_1quulgy.css";const i="a1j9d2dw",t="i1c7erb1",e="ax57y32",l="a1r3bkt9",s="a4qbgp8",a="i1m4nw9n";export{s as actionButton,e as actionButtonsSection,l as actionButtonsSectionWithThumbnail,i as actionContainer,a as iconButton,t as inlineActionContainer};
|
|
2
|
+
//# sourceMappingURL=file-item-actions.styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-item-actions.styles.js","sources":["../../../src/file-upload/file-list-item/file-item-actions.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { MediaQuery, Spacing } from \"../../theme\";\n\nexport const actionContainer = css`\n width: 6rem;\n margin-left: ${Spacing[\"spacing-32\"]};\n display: flex;\n justify-content: flex-end;\n align-items: center;\n\n ${MediaQuery.MaxWidth.md} {\n width: fit-content;\n }\n\n &[data-mobile-layout=\"loading\"] {\n ${MediaQuery.MaxWidth.md} {\n margin-left: 0;\n margin-top: ${Spacing[\"spacing-16\"]};\n width: 100%;\n }\n }\n\n &[data-mobile-layout=\"editable\"] {\n ${MediaQuery.MaxWidth.md} {\n margin-left: 0;\n margin-top: ${Spacing[\"spacing-16\"]};\n align-self: flex-end;\n }\n }\n`;\n\nexport const inlineActionContainer = css`\n width: 100%;\n margin-top: ${Spacing[\"spacing-16\"]};\n display: flex;\n justify-content: flex-end;\n align-items: center;\n`;\n\nexport const actionButtonsSection = css`\n display: flex;\n justify-content: flex-end;\n\n ${MediaQuery.MaxWidth.md} {\n flex-direction: column;\n }\n`;\n\nexport const actionButtonsSectionWithThumbnail = css`\n margin-left: calc(\n 96px + ${Spacing[\"spacing-32\"]}\n ); // thumbnail width + right margin\n\n ${MediaQuery.MaxWidth.md} {\n margin-left: 0;\n }\n`;\n\nexport const actionButton = css`\n width: 7.5rem;\n\n &:not(:last-of-type) {\n margin-right: ${Spacing[\"spacing-16\"]};\n }\n\n ${MediaQuery.MaxWidth.md} {\n width: 100%;\n\n &:not(:last-of-type) {\n margin-bottom: ${Spacing[\"spacing-16\"]};\n }\n }\n`;\n\nexport const iconButton = css`\n min-width: unset;\n\n &:not(:last-child) {\n margin-right: ${Spacing[\"spacing-8\"]};\n }\n`;\n"],"names":["actionContainer","inlineActionContainer","actionButtonsSection","actionButtonsSectionWithThumbnail","actionButton","iconButton"],"mappings":"yFAIO,MAAMA,EAAe,WA4BfC,EAAqB,WAQrBC,EAAoB,UASpBC,EAAiC,WAUjCC,EAAY,UAgBZC,EAAU"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
@layer fds{.a1j9d2dw{width:6rem;margin-left:var(--fds-spacing-32);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}:where(body.fds-breakpoint-md-max) .a1j9d2dw{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;}:where(body.fds-breakpoint-md-max) .a1j9d2dw[data-mobile-layout="loading"]{margin-left:0;margin-top:var(--fds-spacing-16);width:100%;}:where(body.fds-breakpoint-md-max) .a1j9d2dw[data-mobile-layout="editable"]{margin-left:0;margin-top:var(--fds-spacing-16);-webkit-align-self:flex-end;-ms-flex-item-align:end;align-self:flex-end;}
|
|
2
|
+
.i1c7erb1{width:100%;margin-top:var(--fds-spacing-16);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}
|
|
3
|
+
.ax57y32{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;}:where(body.fds-breakpoint-md-max) .ax57y32{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}
|
|
4
|
+
.a1r3bkt9{margin-left:calc(
|
|
5
|
+
96px + var(--fds-spacing-32)
|
|
6
|
+
);}:where(body.fds-breakpoint-md-max) .a1r3bkt9{margin-left:0;}
|
|
7
|
+
.a4qbgp8{width:7.5rem;}.a4qbgp8:not(:last-of-type){margin-right:var(--fds-spacing-16);}:where(body.fds-breakpoint-md-max) .a4qbgp8{width:100%;}:where(body.fds-breakpoint-md-max) .a4qbgp8:not(:last-of-type){margin-bottom:var(--fds-spacing-16);}
|
|
8
|
+
.i1m4nw9n{min-width:unset;}.i1m4nw9n:not(:last-child){margin-right:var(--fds-spacing-8);}}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { FormLabelProps } from "../../form/form-label/types";
|
|
2
|
+
import type { FileItemMode } from "./types";
|
|
3
|
+
interface Props {
|
|
4
|
+
mode: Exclude<FileItemMode, "edit">;
|
|
5
|
+
formattedName: string | undefined;
|
|
6
|
+
description: string | undefined;
|
|
7
|
+
fileSize: string;
|
|
8
|
+
errorMessage: string | React.ReactNode | undefined;
|
|
9
|
+
isLoading: boolean;
|
|
10
|
+
descriptionLabel?: FormLabelProps | undefined;
|
|
11
|
+
detailSectionRef: React.Ref<HTMLDivElement>;
|
|
12
|
+
children?: React.ReactNode;
|
|
13
|
+
}
|
|
14
|
+
export declare const FileItemDetails: ({ mode, formattedName, description, fileSize, errorMessage, isLoading, descriptionLabel, detailSectionRef, children, }: Props) => import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{jsxs as e,jsx as i,Fragment as r}from"react/jsx-runtime";import{ExclamationCircleFillIcon as l}from"@lifesg/react-icons/exclamation-circle-fill";import{Typography as d}from"../../typography/index.js";import{nameSection as o,descriptionFileSizeText as s,errorMessage as a,errorIcon as c,itemDescriptionLabel as n,itemDescriptionText as t}from"./file-item-details.styles.js";const m=({mode:m,formattedName:h,description:f,fileSize:p,errorMessage:y,isLoading:g,descriptionLabel:N,detailSectionRef:M,children:B})=>{var u;return e("div","error"===m?{ref:M,className:o,children:[i(d.BodyMD,{weight:f?"semibold":"regular",children:h}),i(d.BodyMD,{className:s,children:p}),y&&e(d.BodySM,{className:a,weight:"semibold",children:[i(l,{className:c,"aria-hidden":!0}),y]})]}:{ref:M,className:o,children:[i(d.BodyMD,{weight:f?"semibold":"regular",children:h}),f&&e(r,{children:[i(d.BodyMD,{className:n,children:null!==(u=null==N?void 0:N.children)&&void 0!==u?u:"Photo description"}),i(d.BodyMD,{className:t,children:f})]}),!g&&i(d.BodyMD,{className:s,children:p}),B]})};export{m as FileItemDetails};
|
|
2
|
+
//# sourceMappingURL=file-item-details.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-item-details.js","sources":["../../../src/file-upload/file-list-item/file-item-details.tsx"],"sourcesContent":["import { ExclamationCircleFillIcon } from \"@lifesg/react-icons/exclamation-circle-fill\";\n\nimport type { FormLabelProps } from \"../../form/form-label/types\";\nimport { Typography } from \"../../typography\";\nimport * as styles from \"./file-item-details.styles\";\nimport type { FileItemMode } from \"./types\";\n\ninterface Props {\n mode: Exclude<FileItemMode, \"edit\">;\n formattedName: string | undefined;\n description: string | undefined;\n fileSize: string;\n errorMessage: string | React.ReactNode | undefined;\n isLoading: boolean;\n descriptionLabel?: FormLabelProps | undefined;\n detailSectionRef: React.Ref<HTMLDivElement>;\n children?: React.ReactNode;\n}\n\nexport const FileItemDetails = ({\n mode,\n formattedName,\n description,\n fileSize,\n errorMessage,\n isLoading,\n descriptionLabel,\n detailSectionRef,\n children,\n}: Props) => {\n if (mode === \"error\") {\n return (\n <div ref={detailSectionRef} className={styles.nameSection}>\n <Typography.BodyMD\n weight={description ? \"semibold\" : \"regular\"}\n >\n {formattedName}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.descriptionFileSizeText}>\n {fileSize}\n </Typography.BodyMD>\n {errorMessage && (\n <Typography.BodySM\n className={styles.errorMessage}\n weight=\"semibold\"\n >\n <ExclamationCircleFillIcon\n className={styles.errorIcon}\n aria-hidden\n />\n {errorMessage}\n </Typography.BodySM>\n )}\n </div>\n );\n }\n\n return (\n <div ref={detailSectionRef} className={styles.nameSection}>\n <Typography.BodyMD weight={description ? \"semibold\" : \"regular\"}>\n {formattedName}\n </Typography.BodyMD>\n {description && (\n <>\n <Typography.BodyMD className={styles.itemDescriptionLabel}>\n {descriptionLabel?.children ?? \"Photo description\"}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.itemDescriptionText}>\n {description}\n </Typography.BodyMD>\n </>\n )}\n {!isLoading && (\n <Typography.BodyMD className={styles.descriptionFileSizeText}>\n {fileSize}\n </Typography.BodyMD>\n )}\n {children}\n </div>\n );\n};\n"],"names":["FileItemDetails","mode","formattedName","description","fileSize","errorMessage","isLoading","descriptionLabel","detailSectionRef","children","_jsxs","ref","className","styles.nameSection","_jsx","Typography","BodyMD","weight","styles.descriptionFileSizeText","BodySM","styles.errorMessage","ExclamationCircleFillIcon","styles.errorIcon","styles.itemDescriptionLabel","_a","styles.itemDescriptionText"],"mappings":"4XAmBO,MAAMA,EAAkB,EAC3BC,OACAC,gBACAC,cACAC,wBACAC,EACAC,YACAC,mBACAC,mBACAC,qBAEA,OAEQC,EAAA,MAFK,UAATT,EAEI,CAAKU,IAAKH,EAAkBI,UAAWC,EAAkBJ,SAAA,CACrDK,EAACC,EAAWC,OAAM,CACdC,OAAQd,EAAc,WAAa,UAASM,SAE3CP,IAELY,EAACC,EAAWC,QAAOJ,UAAWM,EAA8BT,SACvDL,IAEJC,GACGK,EAACK,EAAWI,OAAM,CACdP,UAAWQ,EACXH,OAAO,WAAUR,SAAA,CAEjBK,EAACO,EAAyB,CACtBT,UAAWU,qBAGdjB,QAQZM,IAAKH,EAAkBI,UAAWC,EAAkBJ,SAAA,CACrDK,EAACC,EAAWC,QAAOC,OAAQd,EAAc,WAAa,UAASM,SAC1DP,IAEJC,GACGO,eACII,EAACC,EAAWC,OAAM,CAACJ,UAAWW,EAA2Bd,SAC1B,QAA1Be,EAAAjB,eAAAA,EAAkBE,gBAAQ,IAAAe,EAAAA,EAAI,sBAEnCV,EAACC,EAAWC,QAAOJ,UAAWa,EAA0BhB,SACnDN,QAIXG,GACEQ,EAACC,EAAWC,OAAM,CAACJ,UAAWM,WACzBd,IAGRK,IACC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const nameSection: import("@linaria/core").LinariaClassName;
|
|
2
|
+
export declare const extendedNameSection: import("@linaria/core").LinariaClassName;
|
|
3
|
+
export declare const itemDescriptionLabel: import("@linaria/core").LinariaClassName;
|
|
4
|
+
export declare const itemDescriptionText: import("@linaria/core").LinariaClassName;
|
|
5
|
+
export declare const descriptionFileSizeText: import("@linaria/core").LinariaClassName;
|
|
6
|
+
export declare const errorIcon: import("@linaria/core").LinariaClassName;
|
|
7
|
+
export declare const errorMessage: import("@linaria/core").LinariaClassName;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"./file-item-details.styles_1ce9akx.css";const e="naum77y",i="i11dywsu",s="i745c9",t="d1cbfa1y",l="e1dtq2ug",c="e1scdqz1";export{t as descriptionFileSizeText,l as errorIcon,c as errorMessage,i as itemDescriptionLabel,s as itemDescriptionText,e as nameSection};
|
|
2
|
+
//# sourceMappingURL=file-item-details.styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-item-details.styles.js","sources":["../../../src/file-upload/file-list-item/file-item-details.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Colour, Font, MediaQuery, Spacing } from \"../../theme\";\n\nexport const nameSection = css`\n display: flex;\n flex: 1;\n flex-direction: column;\n width: 100%;\n`;\n\nexport const extendedNameSection = css`\n display: flex;\n flex: 1;\n flex-direction: column;\n align-items: flex-start;\n\n ${MediaQuery.MaxWidth.md} {\n width: 100%;\n }\n`;\n\nexport const itemDescriptionLabel = css`\n ${Font[\"form-label\"]}\n font-weight: ${Font.Spec[\"weight-semibold\"]};\n color: ${Colour[\"text-subtle\"]};\n margin-top: ${Spacing[\"spacing-16\"]};\n`;\n\nexport const itemDescriptionText = css`\n margin-top: ${Spacing[\"spacing-4\"]};\n overflow-wrap: anywhere;\n`;\n\nexport const descriptionFileSizeText = css`\n color: ${Colour[\"text-subtler\"]};\n margin-top: ${Spacing[\"spacing-16\"]};\n`;\n\nexport const errorIcon = css`\n height: 1lh;\n width: 1em;\n flex-shrink: 0;\n color: ${Colour[\"icon-error-strong\"]};\n`;\n\nexport const errorMessage = css`\n color: ${Colour[\"text-error\"]};\n margin-top: ${Spacing[\"spacing-4\"]};\n display: flex;\n gap: ${Spacing[\"spacing-4\"]};\n`;\n"],"names":["nameSection","itemDescriptionLabel","itemDescriptionText","descriptionFileSizeText","errorIcon","errorMessage"],"mappings":"yFAIO,MAAMA,EAAW,UAkBXC,EAAoB,WAOpBC,EAAmB,SAKnBC,EAAuB,WAKvBC,EAAS,WAOTC,EAAY"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
@layer fds{.naum77y{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1;-ms-flex:1;flex:1;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;width:100%;}
|
|
2
|
+
.e13zkqng{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1;-ms-flex:1;flex:1;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;}:where(body.fds-breakpoint-md-max) .e13zkqng{width:100%;}
|
|
3
|
+
.i11dywsu{font-family:var(--fds-font-family-body);font-variant:var(--fds-font-variant);font-size:var(--fds-font-form-label-size);font-weight:var(--fds-font-weight-semibold);line-height:var(--fds-font-form-label-lh);letter-spacing:var(--fds-font-form-label-ls);font-weight:var(--fds-font-weight-semibold);color:var(--fds-colour-text-subtle);margin-top:var(--fds-spacing-16);}
|
|
4
|
+
.i745c9{margin-top:var(--fds-spacing-4);overflow-wrap:anywhere;}
|
|
5
|
+
.d1cbfa1y{color:var(--fds-colour-text-subtler);margin-top:var(--fds-spacing-16);}
|
|
6
|
+
.e1dtq2ug{height:1lh;width:1em;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;color:var(--fds-colour-icon-error-strong);}
|
|
7
|
+
.e1scdqz1{color:var(--fds-colour-text-error);margin-top:var(--fds-spacing-4);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;gap:var(--fds-spacing-4);}}
|
|
@@ -1,8 +1,2 @@
|
|
|
1
|
-
import type { FormLabelProps } from "../../form/form-label/types";
|
|
2
1
|
import type { FileListItemProps } from "./types";
|
|
3
|
-
|
|
4
|
-
readOnly?: boolean | undefined;
|
|
5
|
-
descriptionLabel?: FormLabelProps | undefined;
|
|
6
|
-
}
|
|
7
|
-
export declare const FileListItem: import("react").MemoExoticComponent<({ fileItem, editable, sortable, wrapperWidth, disabled, readOnly, descriptionLabel, onDelete, onEditClick, }: Props) => import("react/jsx-runtime").JSX.Element>;
|
|
8
|
-
export {};
|
|
2
|
+
export declare const FileListItem: import("react").MemoExoticComponent<({ fileItem, wrapperWidth, editable, sortable, disabled, readOnly, descriptionLabel, fileDescriptionMaxLength, descriptionRequired, onDelete, onSave, onCancel, onBlur, onModeChange, }: FileListItemProps) => import("react/jsx-runtime").JSX.Element>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsxs as e,jsx as t
|
|
1
|
+
import{jsxs as e,jsx as t}from"react/jsx-runtime";import{useSortable as i}from"../../external/@dnd-kit/sortable/dist/sortable.esm.js";import{CSS as a}from"../../external/@dnd-kit/utilities/dist/utilities.esm.js";import{DragHandleIcon as r}from"@lifesg/react-icons/drag-handle";import{memo as l,useContext as s,useRef as d,useState as n,useMemo as o,useEffect as m}from"react";import{Form as c}from"../../form/index.js";import{Typography as p}from"../../typography/index.js";import{FileUploadContext as u}from"../context.js";import{FileUploadHelper as f}from"../helper.js";import{FileItemActions as b}from"./file-item-actions.js";import{FileItemDetails as h}from"./file-item-details.js";import{editItem as g,editContentSection as y,editDetailsSection as v,editNameSection as x,editFileNameText as j,editFileSizeText as D,item as S,dragHandleIcon as N,box as M,contentSection as L}from"./file-list-item.styles.js";import{FileListItemThumbnail as T}from"./file-list-item-thumbnail.js";import{useTruncatedName as w}from"./use-truncated-name.js";const I=l((({fileItem:l,wrapperWidth:I,editable:$,sortable:B,disabled:C,readOnly:E,descriptionLabel:O,fileDescriptionMaxLength:P,descriptionRequired:k=!0,onDelete:z,onSave:R,onCancel:U,onBlur:F,onModeChange:H})=>{const{id:K,name:_,size:q,description:W,progress:Y=1,errorMessage:A,thumbnailImageDataUrl:G,truncateText:J=!0}=l,{activeId:Q}=s(u),V=d(null),X=w(_,I,J,V),Z=()=>{if(A)return"error";return(null!=Y?Y:1)>=1&&$&&!W?"edit":"display"},[ee,te]=n(Z),{attributes:ie,listeners:ae,setNodeRef:re,transform:le,transition:se}=i({id:K,disabled:"edit"===ee}),de=d(null),[ne,oe]=n(l.description||""),me=Y<1,ce=f.formatFileSizeDisplay(q),pe=!!G||l.type===f.PDF_MIME_TYPE,ue="display"===ee&&!!W&&!!$,fe=!!B&&!E,be=C||!!Q,he=o((()=>{const e=Q?Q===K?"self":"others":"none";return{itemState:be&&"none"===e?"disabled":fe&&"self"===e?"sortable-active":fe?"sortable":void 0,dragHandleState:"self"===e?"active":be?"disabled":void 0,boxState:"self"===e?"focused":be?"disabled":A?"error":void 0}}),[Q,K,be,fe,A]),ge=k&&0===ne.trim().length,ye=d(ee);ye.current=ee;const ve=d(H);ve.current=H,m((()=>("edit"===ee&&(null==H||H("edit")),()=>{var e;"edit"===ye.current&&(null===(e=ve.current)||void 0===e||e.call(ve,"display"))})),[]),m((()=>{if(A&&"error"!==ee)"edit"===ee&&(null==H||H("display")),te("error");else if(!A&&"error"===ee){const e=Z();"edit"===e&&(null==H||H("edit")),te(e)}}),[A]),m((()=>{"edit"===ee&&oe(l.description||"")}),[ee,l.description]);const xe=()=>{te("edit"),null==H||H("edit")},je=e=>{B&&e.stopPropagation()},De=()=>{de.current&&(te("display"),null==H||H("display"),null==R||R(de.current.value.trim()))},Se=()=>{te("display"),null==H||H("display"),null==U||U()},Ne=e=>{oe(e.target.value)},Me=e=>{null==F||F(e.target.value)};if("edit"===ee)return e("li",{"data-testid":`${K}-edit-display`,className:g,children:[e("div",{className:y,children:[pe&&t(T,{thumbnailImageDataUrl:G,fileType:l.type}),e("div",{className:v,children:[e("div",{ref:V,className:x,children:[t(p.BodyMD,{className:j,weight:"semibold",children:X}),t(p.BodyMD,{className:D,children:ce})]}),t(c.Textarea,{ref:de,id:`${K}-description-textarea`,"data-testid":`${K}-textarea`,value:ne,maxLength:P,onChange:Ne,onBlur:Me,rows:3,label:null!=O?O:{children:"Photo description",subtitle:"Describe this photo to users who may not be able to see the image."}})]})]}),t(b,{mode:"edit",id:K,name:_,hasThumbnail:pe,disableSave:ge,onSave:De,onCancel:Se})]});const Le={transform:a.Translate.toString(le),transition:se},Te=Object.assign(Object.assign({style:Le},ie),ae),we=pe?t(T,{thumbnailImageDataUrl:G||"",fileType:l.type,"data-testid":`${K}-thumbnail`}):null;return e("li",Object.assign({id:K,ref:re,className:S,"data-item-state":he.itemState,"data-testid":`${K}-item`},fe?Te:{},{children:[fe&&t(r,{"data-testid":`${K}-drag-handle`,className:N,"data-drag-handle-state":he.dragHandleState}),e("div",{className:M,"data-box-state":he.boxState,"data-stack-mobile":!A&&(me||$),children:[e("div",{className:L,"data-has-thumbnail":"display"===ee&&pe,children:["display"===ee&&we,t(h,{mode:ee,formattedName:X,description:W,fileSize:ce,errorMessage:A,isLoading:me,descriptionLabel:O,detailSectionRef:V,children:!E&&ue&&t(b,{mode:"display",inline:!0,id:K,name:_,editable:!!$,isLoading:me,progress:Y,disabled:be,onDelete:z,onEdit:xe,onKeyDown:je})})]}),!E&&!ue&&t(b,"error"===ee?{mode:"error",id:K,name:_,errorMessage:A,onDelete:z}:{mode:"display",id:K,name:_,editable:!!$,isLoading:me,progress:Y,disabled:be,onDelete:z,onEdit:xe,onKeyDown:je})]})]}))}));export{I as FileListItem};
|
|
2
2
|
//# sourceMappingURL=file-list-item.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-list-item.js","sources":["../../../src/file-upload/file-list-item/file-list-item.tsx"],"sourcesContent":["import { useSortable } from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { BinIcon } from \"@lifesg/react-icons/bin\";\nimport { DragHandleIcon as DSDragHandleIcon } from \"@lifesg/react-icons/drag-handle\";\nimport { ExclamationCircleFillIcon } from \"@lifesg/react-icons/exclamation-circle-fill\";\nimport { PencilIcon } from \"@lifesg/react-icons/pencil\";\nimport {\n memo,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\n\nimport { Button } from \"../../button\";\nimport type { FormLabelProps } from \"../../form/form-label/types\";\nimport { ProgressBar } from \"../../shared/progress-bar\";\nimport { Typography } from \"../../typography\";\nimport { StringHelper } from \"../../util\";\nimport { FileUploadContext } from \"../context\";\nimport { FileUploadHelper } from \"../helper\";\nimport type { ItemFocusType } from \"./file-list-item.styles\";\nimport * as styles from \"./file-list-item.styles\";\nimport { FileListItemThumbnail } from \"./file-list-item-thumbnail\";\nimport type { FileListItemProps } from \"./types\";\n\ninterface Props extends FileListItemProps {\n readOnly?: boolean | undefined;\n descriptionLabel?: FormLabelProps | undefined;\n}\n\nconst Component = ({\n fileItem,\n editable,\n sortable,\n wrapperWidth,\n disabled,\n readOnly,\n descriptionLabel,\n onDelete,\n onEditClick,\n}: Props) => {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const {\n id,\n name,\n size,\n description,\n progress = 1,\n errorMessage,\n thumbnailImageDataUrl,\n truncateText = true,\n } = fileItem;\n const [formattedName, setFormattedName] = useState<string>();\n const { activeId } = useContext(FileUploadContext);\n\n // Sortable mechanism\n const { attributes, listeners, setNodeRef, transform, transition } =\n useSortable({ id });\n const detailSectionRef = useRef<HTMLDivElement>(null);\n const style = {\n transform: CSS.Translate.toString(transform),\n transition,\n };\n\n const sortableProps = {\n style,\n ...attributes,\n ...listeners,\n };\n\n // Local variables\n const isLoading = progress < 1;\n const fileSize = FileUploadHelper.formatFileSizeDisplay(size);\n const hasInlineActions = !!description && !!editable;\n const focusType: ItemFocusType = activeId\n ? activeId === id\n ? \"self\"\n : \"others\"\n : \"none\";\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const getTruncatedText = useCallback(\n (value: string) => {\n if (!truncateText) return value;\n\n const widthOfElement =\n detailSectionRef && detailSectionRef.current\n ? detailSectionRef.current.getBoundingClientRect().width\n : 0;\n\n return StringHelper.truncateOneLine(\n value,\n widthOfElement,\n widthOfElement / 2,\n widthOfElement / 2 / 8, // Arbitrary\n 16 // Font size\n );\n },\n [truncateText]\n );\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n setFormattedName(getTruncatedText(name));\n }, [wrapperWidth, getTruncatedText, name]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleDelete = () => {\n onDelete();\n };\n\n const handleEdit = () => {\n if (onEditClick) {\n onEditClick();\n }\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n /**\n * Circumvent issue of keydown action activating the sort mechanism\n * rather than the actual action\n */\n if (sortable) {\n event.stopPropagation();\n }\n };\n\n const shouldDisable = () => disabled || !!activeId;\n\n const shouldEnableSort = () => !!sortable && !readOnly;\n\n const getItemState = () => {\n if (shouldDisable() && focusType === \"none\") {\n return \"disabled\";\n }\n\n if (shouldEnableSort() && focusType === \"self\") {\n return \"sortable-active\";\n }\n\n if (shouldEnableSort()) {\n return \"sortable\";\n }\n\n return undefined;\n };\n\n const getDragHandleState = () => {\n if (focusType === \"self\") {\n return \"active\";\n }\n\n if (shouldDisable()) {\n return \"disabled\";\n }\n\n return undefined;\n };\n\n const getBoxState = () => {\n if (focusType === \"self\") {\n return \"focused\";\n }\n\n if (shouldDisable()) {\n return \"disabled\";\n }\n\n if (errorMessage) {\n return \"error\";\n }\n\n return undefined;\n };\n\n const getActionContainerLayout = () => {\n if (!errorMessage && isLoading) {\n return \"loading\";\n }\n\n if (!errorMessage && editable) {\n return \"editable\";\n }\n\n return undefined;\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderNameDescription = () => (\n <>\n <Typography.BodyMD weight={description ? \"semibold\" : \"regular\"}>\n {formattedName}\n </Typography.BodyMD>\n {description && (\n <>\n <Typography.BodyMD className={styles.itemDescriptionLabel}>\n {descriptionLabel?.children ?? \"Photo description\"}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.itemDescriptionText}>\n {description}\n </Typography.BodyMD>\n </>\n )}\n </>\n );\n\n const renderErrorState = () => (\n <>\n <div ref={detailSectionRef} className={styles.nameSection}>\n {renderNameDescription()}\n {errorMessage && (\n <Typography.BodySM\n className={styles.desktopErrorMessage}\n weight=\"semibold\"\n >\n <ExclamationCircleFillIcon\n className={styles.errorIcon}\n aria-hidden\n />\n {errorMessage}\n </Typography.BodySM>\n )}\n </div>\n <div\n className={styles.fileSizeSection}\n data-mobile-visibility={isLoading ? \"hidden\" : \"expand\"}\n >\n <Typography.BodyMD className={styles.fileSizeText}>\n {fileSize}\n </Typography.BodyMD>\n </div>\n {errorMessage && (\n <Typography.BodySM\n className={styles.mobileErrorMessage}\n weight=\"semibold\"\n >\n <ExclamationCircleFillIcon\n className={styles.errorIcon}\n aria-hidden\n />\n {errorMessage}\n </Typography.BodySM>\n )}\n </>\n );\n\n const renderInlineActions = () => (\n <div className={styles.inlineActionContainer}>\n <Button\n key=\"edit\"\n data-testid={`${id}-edit-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`edit ${name}`}\n disabled={shouldDisable()}\n onClick={handleEdit}\n onKeyDown={handleKeyDown}\n icon={<PencilIcon aria-hidden />}\n className={styles.iconButton}\n />\n <Button\n key=\"delete\"\n data-testid={`${id}-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}`}\n disabled={shouldDisable()}\n onClick={handleDelete}\n onKeyDown={handleKeyDown}\n icon={<BinIcon aria-hidden />}\n className={styles.iconButton}\n />\n </div>\n );\n\n const renderDescriptionContent = () => (\n <div ref={detailSectionRef} className={styles.extendedNameSection}>\n <Typography.BodyMD weight=\"semibold\">\n {formattedName}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.itemDescriptionLabel}>\n {descriptionLabel?.children ?? \"Photo description\"}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.itemDescriptionText}>\n {description}\n </Typography.BodyMD>\n <Typography.BodyMD className={styles.descriptionFileSizeText}>\n {fileSize}\n </Typography.BodyMD>\n {!readOnly && hasInlineActions && renderInlineActions()}\n </div>\n );\n\n const renderFileContent = (thumbnailImageDataUrl?: string) => {\n const shouldShowThumbnail =\n !!thumbnailImageDataUrl ||\n fileItem.type === FileUploadHelper.PDF_MIME_TYPE;\n\n const thumbnail = shouldShowThumbnail ? (\n <FileListItemThumbnail\n thumbnailImageDataUrl={thumbnailImageDataUrl || \"\"}\n fileType={fileItem.type}\n data-testid={`${id}-thumbnail`}\n />\n ) : null;\n\n if (hasInlineActions) {\n return (\n <>\n {thumbnail}\n {renderDescriptionContent()}\n </>\n );\n }\n\n return (\n <>\n {thumbnail}\n <div ref={detailSectionRef} className={styles.nameSection}>\n {renderNameDescription()}\n {!isLoading && (\n <Typography.BodyMD\n className={styles.descriptionFileSizeText}\n >\n {fileSize}\n </Typography.BodyMD>\n )}\n </div>\n </>\n );\n };\n\n const renderContents = () => {\n const shouldShowThumbnail =\n !!thumbnailImageDataUrl ||\n fileItem.type === FileUploadHelper.PDF_MIME_TYPE;\n\n const content = errorMessage\n ? renderErrorState()\n : renderFileContent(thumbnailImageDataUrl);\n\n return (\n <div\n className={styles.contentSection}\n data-has-thumbnail={shouldShowThumbnail}\n >\n {content}\n </div>\n );\n };\n\n const renderActions = () => {\n let content: JSX.Element;\n\n if (errorMessage) {\n content = (\n <Button\n data-testid={`${id}-error-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}, error: ${errorMessage}`}\n onClick={handleDelete}\n className={styles.iconButton}\n icon={<BinIcon aria-hidden />}\n />\n );\n } else if (isLoading) {\n content = (\n <ProgressBar\n progress={progress}\n data-testid={`${id}-progress-bar`}\n />\n );\n } else {\n content = (\n <>\n {editable && (\n <Button\n key=\"edit\"\n data-testid={`${id}-edit-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`edit ${name}`}\n disabled={shouldDisable()}\n onClick={handleEdit}\n onKeyDown={handleKeyDown}\n icon={<PencilIcon aria-hidden />}\n className={styles.iconButton}\n />\n )}\n <Button\n key=\"delete\"\n data-testid={`${id}-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}`}\n disabled={shouldDisable()}\n onClick={handleDelete}\n onKeyDown={handleKeyDown}\n icon={<BinIcon aria-hidden />}\n className={styles.iconButton}\n />\n </>\n );\n }\n\n return (\n <div\n className={styles.actionContainer}\n data-mobile-layout={getActionContainerLayout()}\n >\n {content}\n </div>\n );\n };\n\n return (\n <li\n id={id}\n ref={setNodeRef}\n className={styles.item}\n data-item-state={getItemState()}\n data-testid={`${id}-item`}\n {...(shouldEnableSort() ? sortableProps : {})}\n >\n {shouldEnableSort() && (\n <DSDragHandleIcon\n data-testid={`${id}-drag-handle`}\n className={styles.dragHandleIcon}\n data-drag-handle-state={getDragHandleState()}\n />\n )}\n <div\n className={styles.box}\n data-box-state={getBoxState()}\n data-stack-mobile={!errorMessage && (isLoading || editable)}\n >\n {renderContents()}\n {!readOnly && !hasInlineActions && renderActions()}\n </div>\n </li>\n );\n};\n\nexport const FileListItem = memo(Component);\n"],"names":["FileListItem","memo","fileItem","editable","sortable","wrapperWidth","disabled","readOnly","descriptionLabel","onDelete","onEditClick","id","name","size","description","progress","errorMessage","thumbnailImageDataUrl","truncateText","formattedName","setFormattedName","useState","activeId","useContext","FileUploadContext","attributes","listeners","setNodeRef","transform","transition","useSortable","detailSectionRef","useRef","style","CSS","Translate","toString","sortableProps","isLoading","fileSize","FileUploadHelper","formatFileSizeDisplay","hasInlineActions","focusType","getTruncatedText","useCallback","value","widthOfElement","current","getBoundingClientRect","width","StringHelper","truncateOneLine","useEffect","handleDelete","handleEdit","handleKeyDown","event","stopPropagation","shouldDisable","shouldEnableSort","renderNameDescription","_jsxs","_Fragment","children","_jsx","Typography","BodyMD","weight","className","styles.itemDescriptionLabel","_a","styles.itemDescriptionText","Object","assign","ref","styles.item","DSDragHandleIcon","styles.dragHandleIcon","styles.box","shouldShowThumbnail","type","PDF_MIME_TYPE","content","styles.nameSection","BodySM","styles.desktopErrorMessage","ExclamationCircleFillIcon","styles.errorIcon","styles.fileSizeSection","styles.fileSizeText","styles.mobileErrorMessage","thumbnail","FileListItemThumbnail","fileType","styles.extendedNameSection","styles.descriptionFileSizeText","styles.inlineActionContainer","Button","styleType","sizeType","onClick","onKeyDown","icon","PencilIcon","styles.iconButton","BinIcon","renderFileContent","styles.contentSection","renderContents","ProgressBar","styles.actionContainer","renderActions"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"file-list-item.js","sources":["../../../src/file-upload/file-list-item/file-list-item.tsx"],"sourcesContent":["import { useSortable } from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { DragHandleIcon as DSDragHandleIcon } from \"@lifesg/react-icons/drag-handle\";\nimport { memo, useContext, useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { Form } from \"../../form\";\nimport { Typography } from \"../../typography\";\nimport { FileUploadContext } from \"../context\";\nimport { FileUploadHelper } from \"../helper\";\nimport { FileItemActions } from \"./file-item-actions\";\nimport { FileItemDetails } from \"./file-item-details\";\nimport * as styles from \"./file-list-item.styles\";\nimport { FileListItemThumbnail } from \"./file-list-item-thumbnail\";\nimport type { FileItemMode, FileListItemProps } from \"./types\";\nimport { useTruncatedName } from \"./use-truncated-name\";\n\nconst Component = ({\n fileItem,\n wrapperWidth,\n editable,\n sortable,\n disabled,\n readOnly,\n descriptionLabel,\n fileDescriptionMaxLength,\n descriptionRequired = true,\n onDelete,\n onSave,\n onCancel,\n onBlur,\n onModeChange,\n}: FileListItemProps) => {\n const {\n id,\n name,\n size,\n description,\n progress = 1,\n errorMessage,\n thumbnailImageDataUrl,\n truncateText = true,\n } = fileItem;\n\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const { activeId } = useContext(FileUploadContext);\n const detailSectionRef = useRef<HTMLDivElement>(null);\n const formattedName = useTruncatedName(\n name,\n wrapperWidth,\n truncateText,\n detailSectionRef\n );\n\n const computeMode = (): FileItemMode => {\n if (errorMessage) return \"error\";\n\n const isUploaded = (progress ?? 1) >= 1;\n if (isUploaded && editable && !description) return \"edit\";\n\n return \"display\";\n };\n\n const [currentMode, setCurrentMode] = useState<FileItemMode>(computeMode);\n\n // Sortable mechanism\n const { attributes, listeners, setNodeRef, transform, transition } =\n useSortable({ id, disabled: currentMode === \"edit\" });\n\n // Edit mode state\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const [currentDescription, setCurrentDescription] = useState(\n fileItem.description || \"\"\n );\n\n // =========================================================================\n // DERIVED STATE\n // =========================================================================\n const isLoading = progress < 1;\n const fileSize = FileUploadHelper.formatFileSizeDisplay(size);\n const shouldShowThumbnail =\n !!thumbnailImageDataUrl ||\n fileItem.type === FileUploadHelper.PDF_MIME_TYPE;\n\n const hasInlineActions =\n currentMode === \"display\" && !!description && !!editable;\n const shouldEnableSort = !!sortable && !readOnly;\n const isDisabled = disabled || !!activeId;\n\n const visualStates = useMemo(() => {\n const focusType = activeId\n ? activeId === id\n ? \"self\"\n : \"others\"\n : \"none\";\n\n const itemState = (() => {\n if (isDisabled && focusType === \"none\") return \"disabled\";\n if (shouldEnableSort && focusType === \"self\")\n return \"sortable-active\";\n if (shouldEnableSort) return \"sortable\";\n return undefined;\n })();\n\n const dragHandleState = (() => {\n if (focusType === \"self\") return \"active\";\n if (isDisabled) return \"disabled\";\n return undefined;\n })();\n\n const boxState = (() => {\n if (focusType === \"self\") return \"focused\";\n if (isDisabled) return \"disabled\";\n if (errorMessage) return \"error\";\n return undefined;\n })();\n\n return { itemState, dragHandleState, boxState };\n }, [activeId, id, isDisabled, shouldEnableSort, errorMessage]);\n\n const disableSave =\n descriptionRequired && currentDescription.trim().length === 0;\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n const currentModeRef = useRef(currentMode);\n currentModeRef.current = currentMode;\n const onModeChangeRef = useRef(onModeChange);\n onModeChangeRef.current = onModeChange;\n\n useEffect(() => {\n if (currentMode === \"edit\") {\n onModeChange?.(\"edit\");\n }\n return () => {\n if (currentModeRef.current === \"edit\") {\n onModeChangeRef.current?.(\"display\");\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n useEffect(() => {\n if (errorMessage && currentMode !== \"error\") {\n if (currentMode === \"edit\") {\n onModeChange?.(\"display\");\n }\n setCurrentMode(\"error\");\n } else if (!errorMessage && currentMode === \"error\") {\n const nextMode = computeMode();\n if (nextMode === \"edit\") {\n onModeChange?.(\"edit\");\n }\n setCurrentMode(nextMode);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [errorMessage]);\n\n useEffect(() => {\n if (currentMode === \"edit\") {\n setCurrentDescription(fileItem.description || \"\");\n }\n }, [currentMode, fileItem.description]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleEdit = () => {\n setCurrentMode(\"edit\");\n onModeChange?.(\"edit\");\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n /**\n * Circumvent issue of keydown action activating the sort mechanism\n * rather than the actual action\n */\n if (sortable) {\n event.stopPropagation();\n }\n };\n\n const handleSave = () => {\n if (textareaRef.current) {\n setCurrentMode(\"display\");\n onModeChange?.(\"display\");\n onSave?.(textareaRef.current.value.trim());\n }\n };\n\n const handleCancel = () => {\n setCurrentMode(\"display\");\n onModeChange?.(\"display\");\n onCancel?.();\n };\n\n const handleTextareaChange = (\n event: React.ChangeEvent<HTMLTextAreaElement>\n ) => {\n setCurrentDescription(event.target.value);\n };\n\n const handleTextareaBlur = (\n event: React.FocusEvent<HTMLTextAreaElement>\n ) => {\n onBlur?.(event.target.value);\n };\n\n // =========================================================================\n // RENDER: EDIT MODE\n // =========================================================================\n if (currentMode === \"edit\") {\n return (\n <li data-testid={`${id}-edit-display`} className={styles.editItem}>\n <div className={styles.editContentSection}>\n {shouldShowThumbnail && (\n <FileListItemThumbnail\n thumbnailImageDataUrl={thumbnailImageDataUrl}\n fileType={fileItem.type}\n />\n )}\n <div className={styles.editDetailsSection}>\n <div\n ref={detailSectionRef}\n className={styles.editNameSection}\n >\n <Typography.BodyMD\n className={styles.editFileNameText}\n weight=\"semibold\"\n >\n {formattedName}\n </Typography.BodyMD>\n <Typography.BodyMD\n className={styles.editFileSizeText}\n >\n {fileSize}\n </Typography.BodyMD>\n </div>\n <Form.Textarea\n ref={textareaRef}\n id={`${id}-description-textarea`}\n data-testid={`${id}-textarea`}\n value={currentDescription}\n maxLength={fileDescriptionMaxLength}\n onChange={handleTextareaChange}\n onBlur={handleTextareaBlur}\n rows={3}\n label={\n descriptionLabel ?? {\n children: \"Photo description\",\n subtitle:\n \"Describe this photo to users who may not be able to see the image.\",\n }\n }\n />\n </div>\n </div>\n <FileItemActions\n mode=\"edit\"\n id={id}\n name={name}\n hasThumbnail={shouldShowThumbnail}\n disableSave={disableSave}\n onSave={handleSave}\n onCancel={handleCancel}\n />\n </li>\n );\n }\n\n // =========================================================================\n // RENDER: DISPLAY / ERROR MODE\n // =========================================================================\n const sortableStyle = {\n transform: CSS.Translate.toString(transform),\n transition,\n };\n\n const sortableProps = {\n style: sortableStyle,\n ...attributes,\n ...listeners,\n };\n\n const thumbnail = shouldShowThumbnail ? (\n <FileListItemThumbnail\n thumbnailImageDataUrl={thumbnailImageDataUrl || \"\"}\n fileType={fileItem.type}\n data-testid={`${id}-thumbnail`}\n />\n ) : null;\n\n return (\n <li\n id={id}\n ref={setNodeRef}\n className={styles.item}\n data-item-state={visualStates.itemState}\n data-testid={`${id}-item`}\n {...(shouldEnableSort ? sortableProps : {})}\n >\n {shouldEnableSort && (\n <DSDragHandleIcon\n data-testid={`${id}-drag-handle`}\n className={styles.dragHandleIcon}\n data-drag-handle-state={visualStates.dragHandleState}\n />\n )}\n <div\n className={styles.box}\n data-box-state={visualStates.boxState}\n data-stack-mobile={!errorMessage && (isLoading || editable)}\n >\n <div\n className={styles.contentSection}\n data-has-thumbnail={\n currentMode === \"display\" && shouldShowThumbnail\n }\n >\n {currentMode === \"display\" && thumbnail}\n <FileItemDetails\n mode={currentMode}\n formattedName={formattedName}\n description={description}\n fileSize={fileSize}\n errorMessage={errorMessage}\n isLoading={isLoading}\n descriptionLabel={descriptionLabel}\n detailSectionRef={detailSectionRef}\n >\n {!readOnly && hasInlineActions && (\n <FileItemActions\n mode=\"display\"\n inline\n id={id}\n name={name}\n editable={!!editable}\n isLoading={isLoading}\n progress={progress}\n disabled={isDisabled}\n onDelete={onDelete}\n onEdit={handleEdit}\n onKeyDown={handleKeyDown}\n />\n )}\n </FileItemDetails>\n </div>\n {!readOnly &&\n !hasInlineActions &&\n (currentMode === \"error\" ? (\n <FileItemActions\n mode=\"error\"\n id={id}\n name={name}\n errorMessage={errorMessage}\n onDelete={onDelete}\n />\n ) : (\n <FileItemActions\n mode=\"display\"\n id={id}\n name={name}\n editable={!!editable}\n isLoading={isLoading}\n progress={progress}\n disabled={isDisabled}\n onDelete={onDelete}\n onEdit={handleEdit}\n onKeyDown={handleKeyDown}\n />\n ))}\n </div>\n </li>\n );\n};\n\nexport const FileListItem = memo(Component);\n"],"names":["FileListItem","memo","fileItem","wrapperWidth","editable","sortable","disabled","readOnly","descriptionLabel","fileDescriptionMaxLength","descriptionRequired","onDelete","onSave","onCancel","onBlur","onModeChange","id","name","size","description","progress","errorMessage","thumbnailImageDataUrl","truncateText","activeId","useContext","FileUploadContext","detailSectionRef","useRef","formattedName","useTruncatedName","computeMode","currentMode","setCurrentMode","useState","attributes","listeners","setNodeRef","transform","transition","useSortable","textareaRef","currentDescription","setCurrentDescription","isLoading","fileSize","FileUploadHelper","formatFileSizeDisplay","shouldShowThumbnail","type","PDF_MIME_TYPE","hasInlineActions","shouldEnableSort","isDisabled","visualStates","useMemo","focusType","itemState","dragHandleState","boxState","disableSave","trim","length","currentModeRef","current","onModeChangeRef","useEffect","_a","call","nextMode","handleEdit","handleKeyDown","event","stopPropagation","handleSave","value","handleCancel","handleTextareaChange","target","handleTextareaBlur","_jsxs","className","styles.editItem","children","styles.editContentSection","_jsx","FileListItemThumbnail","fileType","styles.editDetailsSection","ref","styles.editNameSection","Typography","BodyMD","styles.editFileNameText","weight","styles.editFileSizeText","Form","Textarea","maxLength","onChange","rows","label","subtitle","FileItemActions","mode","hasThumbnail","sortableStyle","CSS","Translate","toString","sortableProps","Object","assign","style","thumbnail","styles.item","DSDragHandleIcon","styles.dragHandleIcon","styles.box","styles.contentSection","FileItemDetails","inline","onEdit","onKeyDown"],"mappings":"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"}
|
|
@@ -1,18 +1,11 @@
|
|
|
1
|
+
export declare const editItem: import("@linaria/core").LinariaClassName;
|
|
2
|
+
export declare const editContentSection: import("@linaria/core").LinariaClassName;
|
|
3
|
+
export declare const editDetailsSection: import("@linaria/core").LinariaClassName;
|
|
4
|
+
export declare const editNameSection: import("@linaria/core").LinariaClassName;
|
|
5
|
+
export declare const editFileNameText: import("@linaria/core").LinariaClassName;
|
|
6
|
+
export declare const editFileSizeText: import("@linaria/core").LinariaClassName;
|
|
1
7
|
export type ItemFocusType = "self" | "others" | "none";
|
|
2
8
|
export declare const item: import("@linaria/core").LinariaClassName;
|
|
3
9
|
export declare const dragHandleIcon: import("@linaria/core").LinariaClassName;
|
|
4
10
|
export declare const box: import("@linaria/core").LinariaClassName;
|
|
5
11
|
export declare const contentSection: import("@linaria/core").LinariaClassName;
|
|
6
|
-
export declare const nameSection: import("@linaria/core").LinariaClassName;
|
|
7
|
-
export declare const extendedNameSection: import("@linaria/core").LinariaClassName;
|
|
8
|
-
export declare const fileSizeSection: import("@linaria/core").LinariaClassName;
|
|
9
|
-
export declare const fileSizeText: import("@linaria/core").LinariaClassName;
|
|
10
|
-
export declare const descriptionFileSizeText: import("@linaria/core").LinariaClassName;
|
|
11
|
-
export declare const itemDescriptionLabel: import("@linaria/core").LinariaClassName;
|
|
12
|
-
export declare const itemDescriptionText: import("@linaria/core").LinariaClassName;
|
|
13
|
-
export declare const errorIcon: import("@linaria/core").LinariaClassName;
|
|
14
|
-
export declare const desktopErrorMessage: import("@linaria/core").LinariaClassName;
|
|
15
|
-
export declare const mobileErrorMessage: import("@linaria/core").LinariaClassName;
|
|
16
|
-
export declare const actionContainer: import("@linaria/core").LinariaClassName;
|
|
17
|
-
export declare const inlineActionContainer: import("@linaria/core").LinariaClassName;
|
|
18
|
-
export declare const iconButton: import("@linaria/core").LinariaClassName;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"./file-list-item.
|
|
1
|
+
import"./file-list-item.styles_x3a500.css";const e="e18pxk0j",l="eqb8x5u",i="eddx9rr",t="e1dhzflv",s="ek38w4a",d="elwke9e",f="i14h64yt",o="d1wv8fjl",x="bivlkvo",k="c1jm950n";export{x as box,k as contentSection,o as dragHandleIcon,l as editContentSection,i as editDetailsSection,s as editFileNameText,d as editFileSizeText,e as editItem,t as editNameSection,f as item};
|
|
2
2
|
//# sourceMappingURL=file-list-item.styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-list-item.styles.js","sources":["../../../src/file-upload/file-list-item/file-list-item.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport {\n Border,\n Colour,\n
|
|
1
|
+
{"version":3,"file":"file-list-item.styles.js","sources":["../../../src/file-upload/file-list-item/file-list-item.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport {\n Border,\n Colour,\n MediaQuery,\n Radius,\n Shadow,\n Spacing,\n} from \"../../theme\";\n\n// =============================================================================\n// EDIT MODE STYLES\n// =============================================================================\n\nexport const editItem = css`\n display: flex;\n flex-direction: column;\n padding: ${Spacing[\"spacing-32\"]};\n background: ${Colour[\"bg-primary-subtlest\"]};\n border: ${Border[\"width-010\"]} ${Border.solid} ${Colour.border};\n border-radius: ${Radius[\"sm\"]};\n\n &:not(:last-child) {\n margin-bottom: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const editContentSection = css`\n display: flex;\n align-items: flex-start;\n margin-bottom: ${Spacing[\"spacing-16\"]};\n width: 100%;\n`;\n\nexport const editDetailsSection = css`\n display: flex;\n flex: 1;\n flex-direction: column;\n`;\n\nexport const editNameSection = css`\n width: 100%;\n display: flex;\n justify-content: space-between;\n margin-bottom: ${Spacing[\"spacing-16\"]};\n\n ${MediaQuery.MaxWidth.md} {\n flex-direction: column;\n justify-content: flex-start;\n }\n`;\n\nexport const editFileNameText = css`\n display: flex;\n flex: 1;\n margin-right: ${Spacing[\"spacing-16\"]};\n\n ${MediaQuery.MaxWidth.md} {\n margin-right: 0;\n margin-bottom: ${Spacing[\"spacing-8\"]};\n }\n`;\n\nexport const editFileSizeText = css`\n color: ${Colour[\"text-subtler\"]};\n`;\n\n// =============================================================================\n// DISPLAY / ERROR MODE STYLES\n// =============================================================================\n\nexport type ItemFocusType = \"self\" | \"others\" | \"none\";\n\nexport const item = css`\n display: flex;\n align-items: center;\n width: 100%;\n border: none;\n\n &:not(:last-child) {\n margin-bottom: ${Spacing[\"spacing-16\"]};\n }\n &[data-item-state=\"disabled\"] {\n cursor: not-allowed;\n }\n\n &[data-item-state=\"sortable\"] {\n &:hover {\n cursor: grab;\n }\n\n // Following recommendation by the library for touch events\n // https://docs.dndkit.com/api-documentation/sensors/touch#recommendations\n touch-action: manipulation;\n }\n\n &[data-item-state=\"sortable-active\"] {\n cursor: grabbing;\n\n // Following recommendation by the library for touch events\n // https://docs.dndkit.com/api-documentation/sensors/touch#recommendations\n touch-action: manipulation;\n }\n`;\n\nexport const dragHandleIcon = css`\n margin-right: ${Spacing[\"spacing-16\"]};\n height: 1.5rem;\n width: 1.5rem;\n color: ${Colour[\"icon\"]};\n\n &[data-drag-handle-state=\"active\"] {\n color: ${Colour[\"icon-primary\"]};\n }\n\n &[data-drag-handle-state=\"disabled\"] {\n color: ${Colour[\"icon-disabled\"]};\n }\n`;\n\nexport const box = css`\n background: ${Colour[\"bg-primary-subtlest\"]};\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n border-radius: ${Radius[\"sm\"]};\n padding: ${Spacing[\"spacing-16\"]} ${Spacing[\"spacing-32\"]};\n display: flex;\n align-items: center;\n width: 100%;\n\n ${MediaQuery.MaxWidth.md} {\n padding: ${Spacing[\"spacing-16\"]};\n }\n\n &[data-box-state=\"focused\"] {\n border-color: ${Colour[\"border-focus\"]};\n box-shadow: ${Shadow[\"xs-focus-strong\"]};\n }\n\n &[data-box-state=\"disabled\"] {\n border-color: ${Colour[\"border-disabled\"]};\n }\n\n &[data-box-state=\"error\"] {\n background: ${Colour[\"bg-error\"]};\n border-color: ${Colour[\"border-error\"]};\n }\n\n &[data-stack-mobile=\"true\"] {\n ${MediaQuery.MaxWidth.md} {\n flex-direction: column;\n align-items: flex-start;\n }\n }\n`;\n\nexport const contentSection = css`\n display: flex;\n flex: 1;\n align-items: center;\n\n ${MediaQuery.MaxWidth.md} {\n flex-direction: column;\n width: 100%;\n align-items: flex-start;\n }\n\n &[data-has-thumbnail=\"true\"] {\n align-items: center;\n\n ${MediaQuery.MaxWidth.md} {\n flex-direction: row;\n align-items: center;\n }\n }\n`;\n"],"names":["editItem","editContentSection","editDetailsSection","editNameSection","editFileNameText","editFileSizeText","item","dragHandleIcon","box","contentSection"],"mappings":"qFAeO,MAAMA,EAAQ,WAaRC,EAAkB,UAOlBC,EAAkB,UAMlBC,EAAe,WAYfC,EAAgB,UAWhBC,EAAgB,UAUhBC,EAAI,WAgCJC,EAAc,WAedC,EAAG,UAmCHC,EAAc"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
@layer fds{.e18pxk0j{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding:var(--fds-spacing-32);background:var(--fds-colour-bg-primary-subtlest);border:var(--fds-border-width-010) var(--fds-border-style-solid) var(--fds-colour-border);border-radius:var(--fds-radius-sm);}.e18pxk0j:not(:last-child){margin-bottom:var(--fds-spacing-16);}
|
|
2
|
+
.eqb8x5u{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;margin-bottom:var(--fds-spacing-16);width:100%;}
|
|
3
|
+
.eddx9rr{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1;-ms-flex:1;flex:1;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}
|
|
4
|
+
.e1dhzflv{width:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:space-between;-webkit-justify-content:space-between;justify-content:space-between;margin-bottom:var(--fds-spacing-16);}:where(body.fds-breakpoint-md-max) .e1dhzflv{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:start;-ms-flex-pack:start;-webkit-justify-content:flex-start;justify-content:flex-start;}
|
|
5
|
+
.ek38w4a{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1;-ms-flex:1;flex:1;margin-right:var(--fds-spacing-16);}:where(body.fds-breakpoint-md-max) .ek38w4a{margin-right:0;margin-bottom:var(--fds-spacing-8);}
|
|
6
|
+
.elwke9e{color:var(--fds-colour-text-subtler);}
|
|
7
|
+
.i14h64yt{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;width:100%;border:none;}.i14h64yt:not(:last-child){margin-bottom:var(--fds-spacing-16);}.i14h64yt[data-item-state="disabled"]{cursor:not-allowed;}.i14h64yt[data-item-state="sortable"]{touch-action:manipulation;}.i14h64yt[data-item-state="sortable"]:hover{cursor:-webkit-grab;cursor:grab;}.i14h64yt[data-item-state="sortable-active"]{cursor:-webkit-grabbing;cursor:grabbing;touch-action:manipulation;}
|
|
8
|
+
.d1wv8fjl{margin-right:var(--fds-spacing-16);height:1.5rem;width:1.5rem;color:var(--fds-colour-icon);}.d1wv8fjl[data-drag-handle-state="active"]{color:var(--fds-colour-icon-primary);}.d1wv8fjl[data-drag-handle-state="disabled"]{color:var(--fds-colour-icon-disabled);}
|
|
9
|
+
.bivlkvo{background:var(--fds-colour-bg-primary-subtlest);border:var(--fds-border-width-010) var(--fds-border-style-solid) var(--fds-colour-border);border-radius:var(--fds-radius-sm);padding:var(--fds-spacing-16) var(--fds-spacing-32);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;width:100%;}:where(body.fds-breakpoint-md-max) .bivlkvo{padding:var(--fds-spacing-16);}.bivlkvo[data-box-state="focused"]{border-color:var(--fds-colour-border-focus);box-shadow:var(--fds-shadow-xs-focus-strong);}.bivlkvo[data-box-state="disabled"]{border-color:var(--fds-colour-border-disabled);}.bivlkvo[data-box-state="error"]{background:var(--fds-colour-bg-error);border-color:var(--fds-colour-border-error);}:where(body.fds-breakpoint-md-max) .bivlkvo[data-stack-mobile="true"]{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;}
|
|
10
|
+
.c1jm950n{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1;-ms-flex:1;flex:1;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}:where(body.fds-breakpoint-md-max) .c1jm950n{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;width:100%;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;}.c1jm950n[data-has-thumbnail="true"]{-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}:where(body.fds-breakpoint-md-max) .c1jm950n[data-has-thumbnail="true"]{-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}}
|