Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Meta } from '@storybook/blocks';
import LinkTo from '@storybook/addon-links/react';
import { TableInterface } from '~storybook/components/TableInterface';

<Meta title="Components API/DropzoneCompact" />

# DropzoneCompact API

```js
import { DropzoneCompact } from '@esfront/react';
```

## Component name

The name `ESDropzoneCompact` can be used when providing default props.

## Props

<TableInterface name="DropzoneCompactProps" variant="props" />

<br />

## Demos

<ul>
<li>
<LinkTo kind="components-DropzoneCompact" story="demo">
<code>DropzoneCompact</code>
</LinkTo>
</li>
</ul>
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Args, Meta, StoryContext, StoryObj } from '@storybook/react';

import { DropzoneCompact } from '.';

import { Button } from '../Button';

const getText = (args: Args, context: StoryContext<unknown>) => {
return args.children || (context.globals.locale === 'en' ? 'Drag over this area' : 'Переместите в эту область');
};

const getButtonText = (context: StoryContext<unknown>) => {
return context.globals.locale === 'en' ? 'Drag this button' : 'Переместите кнопку';
};

const meta: Meta<typeof DropzoneCompact> = {
tags: ['autodocs'],
component: DropzoneCompact,
parameters: {
references: ['DropzoneCompact'],
},
argTypes: {
children: {
control: {
type: 'text',
},
},
},
};

export default meta;

type Story = StoryObj<typeof DropzoneCompact>;

export const Demo: Story = {
render: (args, context) => {
const onDrop = () => {
console.info('DROP');
};

return (
<>
<Button disableTouchRipple draggable color="tertiary" size="500" variant="contained">
{getButtonText(context)}
</Button>
<DropzoneCompact {...args} className="mt-16" onDrop={onDrop}>
{getText(args, context)}
</DropzoneCompact>
</>
);
},
};
64 changes: 64 additions & 0 deletions packages/react/src/components/DropzoneCompact/DropzoneCompact.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { forwardRef } from 'react';

import { DropzoneCompactProps } from './DropzoneCompact.types';

import clsx from 'clsx';

import { useDefaultProps } from '@mui/system/DefaultPropsProvider';

import { useDragOver } from '../../hooks/useDragOver';

/**
* This component allows to create droppable area when using dnd.
*/
export const DropzoneCompact = forwardRef<HTMLDivElement, DropzoneCompactProps>(function DropzoneCompact(inProps, ref) {
const {
className,
style,
children,
onDragEnter: onDragEnterProp,
onDragLeave: onDragLeaveProp,
onDragOver: onDragOverProp,
onDrop: onDropProp,
} = useDefaultProps({
props: inProps,
name: 'ESDropzoneCompact',
});

const { isDragOver, onDragEnter, onDragLeave, onDrop } = useDragOver();

const onDropzoneDragEnter = (event: React.DragEvent<HTMLDivElement>) => {
onDragEnter();
onDragEnterProp?.(event);
};

const onDropzoneDragLeave = (event: React.DragEvent<HTMLDivElement>) => {
onDragLeave();
onDragLeaveProp?.(event);
};

const onDropzoneDragOver = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
onDragOverProp?.(event);
};

const onDropzoneDrop = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
onDrop();
onDropProp?.(event);
};

return (
<div
ref={ref}
className={clsx(className, 'es-dropzone-compact', isDragOver && 'es-dropzone-compact--drag-over', 'caption')}
style={style}
onDragEnter={onDropzoneDragEnter}
onDragLeave={onDropzoneDragLeave}
onDragOver={onDropzoneDragOver}
onDrop={onDropzoneDrop}
>
{children}
</div>
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { CSSProperties, ReactNode } from 'react';

export interface DropzoneCompactProps {
children?: ReactNode;

/** Class applied to the root element. */
className?: string;
/** Style applied to the root element. */
style?: CSSProperties;

onDragEnter?: (event: React.DragEvent<HTMLDivElement>) => void;
onDragLeave?: (event: React.DragEvent<HTMLDivElement>) => void;
onDragOver?: (event: React.DragEvent<HTMLDivElement>) => void;
onDrop?: (event: React.DragEvent<HTMLDivElement>) => void;
}
2 changes: 2 additions & 0 deletions packages/react/src/components/DropzoneCompact/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { DropzoneCompact } from './DropzoneCompact';
export type { DropzoneCompactProps } from './DropzoneCompact.types';
1 change: 1 addition & 0 deletions packages/react/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export * from './Dialog';
export * from './DialogStack';
export * from './Divider';
export * from './Dropzone';
export * from './DropzoneCompact';
export * from './EmptyState';
export * from './EmptyStateCompact';
export * from './ErrorPage';
Expand Down
14 changes: 7 additions & 7 deletions packages/react/src/hooks/useDragOver/useDragOver.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from 'react';
import { useCallback, useState } from 'react';

/**
* The hook that allows to watch over the drag over state.
Expand All @@ -7,17 +7,17 @@ import { useState } from 'react';
export const useDragOver = () => {
const [count, setCount] = useState(0);

const onDragEnter = () => {
const onDragEnter = useCallback(() => {
setCount((c) => c + 1);
};
}, []);

const onDragLeave = () => {
const onDragLeave = useCallback(() => {
setCount((c) => c - 1);
};
}, []);

const onDrop = () => {
const onDrop = useCallback(() => {
setCount(0);
};
}, []);

return { onDragEnter, onDragLeave, onDrop, isDragOver: count > 0 };
};
5 changes: 5 additions & 0 deletions packages/react/src/overrides.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
} from './components/Dialog';
import { DividerProps } from './components/Divider';
import { DropzoneProps } from './components/Dropzone';
import { DropzoneCompactProps } from './components/DropzoneCompact';
import { EmptyStateProps } from './components/EmptyState';
import { EmptyStateCompactProps } from './components/EmptyStateCompact';
import {
Expand Down Expand Up @@ -208,6 +209,7 @@ declare module '@mui/material/styles/props' {
ESDialogTitle: DialogTitleProps;
ESDivider: DividerProps;
ESDropzone: DropzoneProps;
ESDropzoneCompact: DropzoneCompactProps;
ESEmptyState: EmptyStateProps;
ESEmptyStateCompact: EmptyStateCompactProps;
ESErrorPage: ErrorPageProps;
Expand Down Expand Up @@ -535,6 +537,9 @@ declare module '@mui/material/styles/components' {
ESDropzone?: {
defaultProps?: ComponentsProps['ESDropzone'];
};
ESDropzoneCompact?: {
defaultProps?: ComponentsProps['ESDropzoneCompact'];
};
ESFileIcon?: {
defaultProps?: ComponentsProps['ESFileIcon'];
};
Expand Down
18 changes: 18 additions & 0 deletions packages/theme/lib/components/_dropzone-compact.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
@mixin include() {
.es-dropzone-compact {
align-items: center;
background-color: var(--es-mono-a-a25);
border-radius: 4px;
color: var(--es-mono-a-a550);
display: flex;
justify-content: center;
outline: 1px dashed var(--es-mono-a-a300);
outline-offset: -1px;
padding: 12px;
transition: background-color 200ms;

&--drag-over {
background-color: var(--es-mono-a-a50);
}
}
}
2 changes: 2 additions & 0 deletions packages/theme/lib/components/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
@use './dialog';
@use './divider';
@use './dropzone';
@use './dropzone-compact';
@use './empty-state-compact';
@use './empty-state';
@use './error-page';
Expand Down Expand Up @@ -89,6 +90,7 @@
@include dialog.include;
@include divider.include;
@include dropzone.include;
@include dropzone-compact.include;
@include empty-state-compact.include;
@include empty-state.include;
@include error-page.include;
Expand Down
Loading