Skip to content

Commit

Permalink
refactor: common path pull up
Browse files Browse the repository at this point in the history
  • Loading branch information
kyechan99 committed Mar 11, 2024
1 parent 831e6e4 commit d8083e7
Show file tree
Hide file tree
Showing 67 changed files with 269 additions and 124 deletions.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react';
import { describe, expect, it } from 'vitest';

import { Checkbox, Label } from '../../';
import { fireEvent, render, screen } from '../../../libs/test';
import { fireEvent, render, screen } from '../../libs/test';

describe('Checkbox', () => {
it('Checkbox icon must be customizable and work when clicked.', () => {
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
InputGroup,
Label,
} from '../../';
import { fireEvent, render, screen } from '../../../libs/test';
import { fireEvent, render, screen } from '../../libs/test';

describe('Dialog', () => {
it('Should appear DialogContent when click DialogToggle', () => {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PortalProvider } from '@/components/portal/PortalProvider';
import { PortalProvider } from '@/components/Portal/PortalProvider';
import { AlignType } from '@/types/align';

interface DropdownProps extends React.PropsWithChildren {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import styled from '@emotion/styled';
import * as React from 'react';

import { PortalContent } from '@/components/portal/PortalContent';
import { PortalContent } from '@/components/Portal/PortalContent';

interface ModalProps extends React.ComponentPropsWithoutRef<'div'> {
width?: React.CSSProperties['width'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { css } from '@emotion/react';
import styled from '@emotion/styled';
import * as React from 'react';

import { PortalContext } from '@/components/portal/PortalContext';
import { PortalContext } from '@/components/Portal/PortalContext';
import useContext from '@/hooks/useContext';
import { composeEventHandlers } from '@/libs/event';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';

import { PortalContext } from '@/components/Portal/PortalContext';
import Slot from '@/components/Slot';
import { PortalContext } from '@/components/portal/PortalContext';
import useContext from '@/hooks/useContext';
import { composeEventHandlers } from '@/libs/event';
import { composeRefs } from '@/libs/ref';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import {
DropdownLabel,
DropdownShortcut,
DropdownToggle,
} from '../../..';
import { fireEvent, render, screen } from '../../../libs/test';
} from '../';
import { fireEvent, render, screen } from '../../libs/test';

describe('UI test', () => {
describe('Dropdown', () => {
it('Should appear DropdownContent when click DropdownToggle', () => {
render(
<Dropdown>
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';

import { PortalProvider } from '@/components/portal/PortalProvider';
import { PortalProvider } from '@/components/Portal/PortalProvider';
import { AlignType } from '@/types/align';

import HoverCardContext from './HoverCardContext';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';

import { PortalContent } from '@/components/portal/PortalContent';
import { PortalContent } from '@/components/Portal/PortalContent';
import { composeEventHandlers, excludeTouchEventHandler } from '@/libs/event';

import useHoverWaiting from './useHoverWaiting';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';

import { PortalContext } from '@/components/portal/PortalContext';
import { PortalContext } from '@/components/Portal/PortalContext';
import useContext from '@/hooks/useContext';
import { composeEventHandlers, excludeTouchEventHandler } from '@/libs/event';
import { composeRefs } from '@/libs/ref';
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';

import { PortalContext } from '@/components/portal/PortalContext';
import { PortalContext } from '@/components/Portal/PortalContext';
import useContext from '@/hooks/useContext';

import HoverCardContext from './HoverCardContext';
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react';
import { expect, it } from 'vitest';

import { Input, InputGroup, Label } from '../..';
import { fireEvent, render, screen } from '../../../libs/test';
import { fireEvent, render, screen } from '../../libs/test';

describe('Input', () => {
it('Fill out the Input', async () => {
Expand Down
File renamed without changes.
79 changes: 79 additions & 0 deletions src/components/Portal/PortalContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { keyframes } from '@emotion/react';
import styled from '@emotion/styled';
import React from 'react';
import { createPortal } from 'react-dom';

import { usePortal } from '@/components/Portal/usePortal';
import useContext from '@/hooks/useContext';
import { composeRefs } from '@/libs/ref';
import { PositionType } from '@/types/position';

import { PortalContext } from './PortalContext';

interface ModalContentProps extends React.ComponentProps<'div'> {
ref: React.ForwardedRef<HTMLDivElement>;
width?: React.CSSProperties['width'];
disabledBG?: boolean;
}

export const PortalContent = ({ children, ref, width, disabledBG = false, ...props }: ModalContentProps) => {
const { showModal, setShowModal, toggleElement } = useContext(PortalContext)!;
const modalRef = React.useRef<HTMLDivElement>(null);
const { reorgPos } = usePortal({ modalRef });

const close = () => {
setShowModal(false);
};

return (
<>
{showModal &&
createPortal(
<>
{!disabledBG && <ModalBG onClick={close} id="bmates-portal-bg" className="bmates-portal-bg" />}
<Modal
ref={composeRefs(modalRef, ref)}
width={width || toggleElement?.getBoundingClientRect().width}
position={reorgPos}
{...props}
>
{children}
</Modal>
</>,
document.body,
)}
</>
);
};

const enter = keyframes`
0% { opacity: 0; }
100% { opacity: 1; }
`;

const ModalBG = styled.div`
position: fixed;
background-color: transparent;
pointer-events: auto;
z-index: 50;
inset: 0;
`;

const Modal = styled.div<{ width?: React.CSSProperties['width']; position: PositionType }>`
display: grid;
min-width: max-content;
${({ width }) => width && `width: ${typeof width === 'string' ? width : `${width}px`};`}
padding: 0.25rem;
border-radius: 0.25rem;
position: fixed;
top: 0px;
left: 0px;
transform: ${({ position }) => `translate(${position.x}px, ${position.y}px)`};
background-color: white;
pointer-events: auto;
z-index: 50;
animation-name: ${enter};
animation-duration: 0.15s;
border: 1px solid ${({ theme }) => theme.colors.gray['300']};
box-shadow: 0px 2px 2px 0px ${({ theme }) => theme.colors.gray['300']};
`;
29 changes: 29 additions & 0 deletions src/components/Portal/PortalContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';

import { AlignType } from '@/types/align';

export interface PortalContextType {
/*
* Modal
*/
showModal: boolean;
setShowModal: (value: boolean) => void;

/*
* Toggle Rect
* - to calcurate element size
*/
toggleElement: HTMLElement | undefined;
setToggleElment: (value: HTMLElement) => void;

/*
* Align
*/
align: AlignType;

/*
* Space Size
*/
space?: number;
}
export const PortalContext = React.createContext<PortalContextType | null>(null);
30 changes: 30 additions & 0 deletions src/components/Portal/PortalProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';

import useModal from '@/hooks/useModal';

import { PortalContext } from './PortalContext';
import { PortalType } from './type';

export interface PortalProviderProps extends React.PropsWithChildren, PortalType {
enableScroll?: boolean;
}

export const PortalProvider = ({ align, space, enableScroll, children }: PortalProviderProps) => {
const [showModal, setShowModal] = useModal(enableScroll);
const [toggleElement, setToggleElment] = React.useState<HTMLElement>();

return (
<PortalContext.Provider
value={{
showModal,
setShowModal,
toggleElement,
setToggleElment,
align,
space,
}}
>
{children}
</PortalContext.Provider>
);
};
3 changes: 3 additions & 0 deletions src/components/Portal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './PortalContent';
export * from './PortalProvider';
export * from './usePortal';
6 changes: 6 additions & 0 deletions src/components/Portal/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { AlignType } from '@/types/align';

export interface PortalType {
align: AlignType;
space: number;
}
60 changes: 60 additions & 0 deletions src/components/Portal/usePortal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from 'react';

import { PortalContext } from '@/components/Portal/PortalContext';
import { PositionType } from '@/types/position';

export const usePortal = ({ modalRef }: { modalRef: React.RefObject<HTMLDivElement> }) => {
const {
showModal,
align,
space = 0,
toggleElement,
setShowModal,
setToggleElment,
} = React.useContext(PortalContext)!;
const [reorgPos, setReorgPos] = React.useState<PositionType>({ x: 0, y: 0 });

React.useEffect(() => {
const adjustmentPos = () => {
if (modalRef.current && toggleElement && showModal) {
const rect = modalRef.current;
const toggleRect = toggleElement.getBoundingClientRect();

const isOverflowing = rect.offsetHeight + toggleRect.bottom + space >= window.innerHeight;
const reorgPos = { x: 0, y: 0 };

switch (align) {
case 'center':
reorgPos.x = toggleRect.x + toggleRect.width / 2 - rect.clientWidth / 2;
break;
case 'start':
reorgPos.x = toggleRect.x;
break;
case 'end':
reorgPos.x = toggleRect.x + toggleRect.width - rect.clientWidth;
break;
}

if (isOverflowing) {
reorgPos.y = toggleRect.y - rect.offsetHeight - space;
} else {
reorgPos.y = toggleRect.y + toggleRect.height + space;
}

if (reorgPos.x <= 0) reorgPos.x = space;
else if (reorgPos.x + rect.offsetWidth >= window.innerWidth)
reorgPos.x = window.innerWidth - rect.offsetWidth - space;

setReorgPos(reorgPos);
}
};
adjustmentPos();

window.addEventListener('resize', adjustmentPos);
return () => {
window.removeEventListener('resize', adjustmentPos);
};
}, [align, showModal, toggleElement, modalRef, space]);

return { showModal, align, toggleElement, setShowModal, setToggleElment, reorgPos };
};
14 changes: 14 additions & 0 deletions src/components/Provider/StyledProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import GlobalStyle from '@/styles/GlobalStyle.tsx';
import theme from '@/styles/theme.ts';
import { ThemeProvider } from '@emotion/react';
import { PropsWithChildren } from 'react';

const StyledProvider = ({ children }: PropsWithChildren) => {
return (
<ThemeProvider theme={theme}>
<GlobalStyle />
{children}
</ThemeProvider>
);
};
export default StyledProvider;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';

import { PortalProvider } from '@/components/portal/PortalProvider';
import { PortalProvider } from '@/components/Portal/PortalProvider';
import { AlignType } from '@/types/align';

import SelectContext from './SelectContext';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import styled from '@emotion/styled';
import * as React from 'react';

import { PortalContent } from '@/components/portal/PortalContent';
import { PortalContent } from '@/components/Portal/PortalContent';

interface ModalProps extends React.ComponentPropsWithoutRef<'div'> {
width?: React.CSSProperties['width'];
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { css } from '@emotion/react';
import styled from '@emotion/styled';
import * as React from 'react';

import { PortalContext } from '@/components/portal/PortalContext';
import { PortalContext } from '@/components/Portal/PortalContext';
import useContext from '@/hooks/useContext';
import { composeEventHandlers } from '@/libs/event';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import styled from '@emotion/styled';
import * as React from 'react';

import { PortalContext } from '@/components/Portal/PortalContext';
import Slot from '@/components/Slot';
import { PortalContext } from '@/components/portal/PortalContext';
import useContext from '@/hooks/useContext';
import { composeEventHandlers } from '@/libs/event';
import { composeRefs } from '@/libs/ref';
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react';
import { describe, expect, it } from 'vitest';

import { Select, SelectContent, SelectDivider, SelectItem, SelectLabel, SelectToggle } from '../';
import { fireEvent, render, screen } from '../../../libs/test';
import { fireEvent, render, screen } from '../../libs/test';

const items = [
{
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import '@testing-library/jest-dom';
import React from 'react';
import { expect, it } from 'vitest';

import { Switch } from '../..';
import { fireEvent, render, screen } from '../../../libs/test';
import { Switch } from '..';
import { fireEvent, render, screen } from '../../libs/test';

describe('Switch', () => {
it('Should be change checked value when click the Switch', async () => {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react';
import { expect, it } from 'vitest';

import { InputDesc, InputGroup, Label, Textarea } from '../..';
import { fireEvent, render, screen } from '../../../libs/test';
import { fireEvent, render, screen } from '../../libs/test';

describe('Textarea', () => {
it('Fill out the Textarea', async () => {
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit d8083e7

Please sign in to comment.