diff --git a/.vscode/settings.json b/.vscode/settings.json index cc2d0f3b..72cc008f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,7 @@ { "editor.codeActionsOnSave": { - "source.organizeImports": false, - "source.fixAll.eslint": true, + "source.organizeImports": "never", + "source.fixAll.eslint": "always" }, "editor.formatOnSave": false, "eslint.format.enable": false, diff --git a/packages/react-components-lab/src/components/ClippedBox/ClippedBox.stories.tsx b/packages/react-components-lab/src/components/ClippedBox/ClippedBox.stories.tsx new file mode 100644 index 00000000..a6545365 --- /dev/null +++ b/packages/react-components-lab/src/components/ClippedBox/ClippedBox.stories.tsx @@ -0,0 +1,50 @@ +/* eslint-disable react/destructuring-assignment */ +import { Meta, Story } from '@storybook/react/types-6-0'; +import React from 'react'; +import { Box } from '@mui/material'; +import ClippedBox from './ClippedBox'; +import { ClippedBoxProps } from './types'; +import getDhiPalette from '../ThemeProvider/getDhiPalette'; + +const dhiPalette = getDhiPalette('light'); + +const Template: Story = (args) => ( + + } + overlay={ + + } + /> +); + +export const Default = Template.bind({}); +Default.args = { + direction: 'horizontal', + height: 100, +}; + +export const Vertical = Template.bind({}); +Vertical.args = { + direction: 'vertical', + height: 400, +}; + +export default { + title: 'Components/ClippedBox', + component: ClippedBox, +} as Meta; diff --git a/packages/react-components-lab/src/components/ClippedBox/ClippedBox.tsx b/packages/react-components-lab/src/components/ClippedBox/ClippedBox.tsx new file mode 100644 index 00000000..fddb88e1 --- /dev/null +++ b/packages/react-components-lab/src/components/ClippedBox/ClippedBox.tsx @@ -0,0 +1,143 @@ +import { UnfoldMore } from '@mui/icons-material'; +import { Box, Stack } from '@mui/material'; +import React, { FC, ReactNode, useEffect, useRef, useState } from 'react'; +import { ClippedBoxProps } from './types'; + +const ClippedBox: FC = ({ + height, + base, + overlay, + direction = 'horizontal', +}) => { + const horizontal = direction === 'horizontal'; + + const [handlePosition, setHandlePosition] = useState(50); + const [isDragging, setIsDragging] = useState(false); + const containerRef = useRef(null); + + const startDrag = (e: MouseEvent) => { + setIsDragging(true); + e.preventDefault(); + }; + + const onDrag = (e: MouseEvent) => { + if (!isDragging || !containerRef.current) { + return; + } + + const bounds = containerRef.current.getBoundingClientRect(); + const newPosition = horizontal + ? ((e.clientX - bounds.left) / bounds.width) * 100 + : ((e.clientY - bounds.top) / bounds.height) * 100; + setHandlePosition(Math.min(Math.max(newPosition, 0), 100)); + }; + + const stopDrag = () => { + setIsDragging(false); + }; + + useEffect(() => { + if (!isDragging) { + return () => {}; + } + + document.addEventListener('mousemove', onDrag); + document.addEventListener('mouseup', stopDrag); + + return () => { + document.removeEventListener('mousemove', onDrag); + document.removeEventListener('mouseup', stopDrag); + }; + }, [isDragging]); + + const clipPathValue = horizontal + ? `polygon(0 0, ${handlePosition}% 0, ${handlePosition}% 100%, 0 100%)` + : `polygon(0 0, 100% 0, 100% ${handlePosition}%, 0 ${handlePosition}%)`; + + return ( + + + {base} + + + + {overlay} + + + + + + + + + + + ); +}; + +export default ClippedBox; diff --git a/packages/react-components-lab/src/components/ClippedBox/types.ts b/packages/react-components-lab/src/components/ClippedBox/types.ts new file mode 100644 index 00000000..a06d9921 --- /dev/null +++ b/packages/react-components-lab/src/components/ClippedBox/types.ts @@ -0,0 +1,6 @@ +export interface ClippedBoxProps { + height: number | string + base: ReactNode + overlay: ReactNode + direction?: 'horizontal' | 'vertical' +} \ No newline at end of file