useDragDropDataTransfer: improve

This commit is contained in:
Enrico Ros
2024-08-07 12:55:58 -07:00
parent 8b9a103fd3
commit 226e4b0f8b
3 changed files with 74 additions and 36 deletions
@@ -1,5 +1,8 @@
import * as React from 'react';
import { SvgIcon } from '@mui/joy';
import AttachFileRoundedIcon from '@mui/icons-material/AttachFileRounded';
import { useDragDropDataTransfer } from '~/common/components/useDragDropDataTransfer';
@@ -40,5 +43,5 @@ export function useComposerDragDrop(
}, [onDataTransfer]);
return useDragDropDataTransfer(enabled, 'I will hold on to this for you.', handleComposerDrop);
return useDragDropDataTransfer(enabled, 'I will hold on to this for you.', AttachFileRoundedIcon as typeof SvgIcon, 'largeIcon', handleComposerDrop);
}
@@ -1,8 +1,7 @@
import * as React from 'react';
import type { SxProps } from '@mui/joy/styles/types';
import { Card, Typography } from '@mui/joy';
import AttachFileRoundedIcon from '@mui/icons-material/AttachFileRounded';
import { Card, SvgIcon, Typography } from '@mui/joy';
// constants
@@ -39,7 +38,13 @@ const dropCardDraggingCardSx: SxProps = {
// Drag/Drop that can be used in any component and invokes a DataTransfer callback on success
export function useDragDropDataTransfer(enabled: boolean, dropText: string, onDropCallback: (dataTransfer: DataTransfer) => Promise<any>) {
export function useDragDropDataTransfer(
enabled: boolean,
dropText: string, // that the button says
DropIcon: typeof SvgIcon | null, // icon on the button
dropVariant: 'largeIcon' | 'startDecorator',
onDropCallback: (dataTransfer: DataTransfer) => Promise<any>,
) {
// state
const [isDragging, setIsDragging] = React.useState(false);
@@ -86,6 +91,7 @@ export function useDragDropDataTransfer(enabled: boolean, dropText: string, onDr
}, [_eatDragEvent, onDropCallback]);
// Standardized component looks, only customized based on `dropText` and `DropIcon`
const dropComponent = React.useMemo(() => {
if (!enabled) return null;
@@ -99,13 +105,21 @@ export function useDragDropDataTransfer(enabled: boolean, dropText: string, onDr
onDrop={_handleDrop}
sx={isDragging ? dropCardDraggingCardSx : dropCardInactiveSx}
>
{isDragging && <AttachFileRoundedIcon sx={{ width: 36, height: 36, pointerEvents: 'none' }} />}
{isDragging && <Typography level='title-sm' sx={{ pointerEvents: 'none' }}>
{dropText}
</Typography>}
{isDragging && dropVariant === 'largeIcon' && !!DropIcon && (
<DropIcon sx={{ width: 36, height: 36, pointerEvents: 'none' }} />
)}
{isDragging && (
<Typography
level='title-sm'
startDecorator={dropVariant === 'startDecorator' && !!DropIcon && <DropIcon />}
sx={{ pointerEvents: 'none' }}
>
{dropText}
</Typography>
)}
</Card>
);
}, [enabled, isDragging, _handleDragLeave, _handleDragOver, _handleDrop, dropText]);
}, [enabled, isDragging, _handleDragLeave, _handleDragOver, _handleDrop, dropVariant, DropIcon, dropText]);
return {
+48 -27
View File
@@ -1,8 +1,9 @@
import * as React from 'react';
import { Button } from '@mui/joy';
import { Box, Button } from '@mui/joy';
import { TooltipOutlined } from '~/common/components/TooltipOutlined';
import { useDragDropDataTransfer } from '~/common/components/useDragDropDataTransfer';
import { LiveFileChooseIcon, LiveFileIcon } from './liveFile.icons';
@@ -14,33 +15,53 @@ export function LiveFileSyncButton(props: {
handleSyncButtonClicked: () => void;
}) {
const handleDataTransfer = React.useCallback(async (dataTransfer: DataTransfer) => {
console.log('LiveFileSyncButton: handleDataTransfer', dataTransfer);
}, []);
const {
dragContainerSx,
dropComponent,
handleContainerDragEnter,
handleContainerDragStart,
} = useDragDropDataTransfer(true, 'Pair', null, 'startDecorator', handleDataTransfer);
return <TooltipOutlined
title={
props.fileHasContent ? 'Click to reload the File and compare.'
: props.isPairingValid ? 'Click to compare with the File contents.'
: 'Setup LiveFile pairing.'
}
color={props.fileHasContent ? 'primary' : 'success'}
variant={props.fileHasContent ? undefined : 'solid'}
>
<Button
variant='soft'
color={props.fileHasContent ? 'primary' : 'success'}
size='sm'
disabled={props.isSavingFile}
onClick={props.handleSyncButtonClicked}
startDecorator={
props.fileHasContent ? <LiveFileIcon />
: (props.isPairingValid ? <LiveFileIcon />
: <LiveFileChooseIcon />)
}
aria-label={props.isPairingValid ? 'Sync File' : 'Choose File'}
return (
<Box
onDragEnter={handleContainerDragEnter}
onDragStart={handleContainerDragStart}
sx={dragContainerSx}
>
{props.fileHasContent ? 'Refresh'
: props.isPairingValid ? 'Sync File'
: 'Pair File'}
</Button>
</TooltipOutlined>;
<TooltipOutlined
title={
props.fileHasContent ? 'Click to reload the File and compare.'
: props.isPairingValid ? 'Click to compare with the File contents.'
: 'Setup LiveFile pairing.'
}
color={props.fileHasContent ? 'primary' : 'success'}
variant={props.fileHasContent ? undefined : 'solid'}
>
<Button
variant='soft'
color={props.fileHasContent ? 'primary' : 'success'}
size='sm'
disabled={props.isSavingFile}
onClick={props.handleSyncButtonClicked}
startDecorator={
props.fileHasContent ? <LiveFileIcon />
: (props.isPairingValid ? <LiveFileIcon />
: <LiveFileChooseIcon />)
}
aria-label={props.isPairingValid ? 'Sync File' : 'Choose File'}
>
{props.fileHasContent ? 'Refresh'
: props.isPairingValid ? 'Sync File'
: 'Pair File'}
</Button>
</TooltipOutlined>
{dropComponent}
</Box>
);
}