Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[고급 레이아웃 컴포넌트] 가브리엘(윤주현) 미션 제출합니다. #62

Merged
merged 92 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
0b2381c
chore: vite 설치
gabrielyoon7 Sep 13, 2023
8e49320
chore: typescript for vite 설정 수정
gabrielyoon7 Sep 16, 2023
fe96857
chore: vite의 기본 context path 설정
gabrielyoon7 Sep 16, 2023
9afcfda
chore: vite의 github pages 자동 배포 설정
gabrielyoon7 Sep 16, 2023
f0b32f9
chore: vite의 github pages 자동 배포 설정 (오탈자 수정)
gabrielyoon7 Sep 16, 2023
0d55c95
chore: vite의 github pages 자동 배포 설정 (오탈자 수정)
gabrielyoon7 Sep 16, 2023
7b75ae2
chore: vite의 github pages 자동 배포 설정 (오탈자 수정)
gabrielyoon7 Sep 16, 2023
f6f6880
chore: vite의 github pages 자동 배포 설정 (오탈자 수정)
gabrielyoon7 Sep 16, 2023
e9dafd1
chore: vite의 github pages 자동 배포를 yarn이 설치하도록 변경
gabrielyoon7 Sep 16, 2023
b2f4827
chore: vite의 github pages 자동 배포를 yarn이 yarn.lock 파일을 참조하지 못하도록 변경
gabrielyoon7 Sep 16, 2023
109919b
chore: storybook 설치
gabrielyoon7 Sep 17, 2023
cf46080
chore: chromatic 설치
gabrielyoon7 Sep 17, 2023
8ed89ff
docs: 리드미 작성
gabrielyoon7 Sep 17, 2023
8d140a4
chore: chromatic 자동 배포 스크립트 추가
gabrielyoon7 Sep 17, 2023
d079e66
fix: 누락된 스토리북 파일 추가
gabrielyoon7 Sep 17, 2023
c8684b5
chore: styled-components 설치
gabrielyoon7 Sep 17, 2023
fd1aa03
chore: css 초기화
gabrielyoon7 Sep 17, 2023
f9c0d8e
chore: react-router-dom 설치 및 기본 페이지 추가
gabrielyoon7 Sep 17, 2023
30489bb
refactor: html, body, #root 기본 영역 설정
gabrielyoon7 Sep 17, 2023
88d5b41
refactor: vite 기본 index.css 제거
gabrielyoon7 Sep 17, 2023
b6a6056
refactor: storybook 기본 파일 제거
gabrielyoon7 Sep 17, 2023
0634417
feat: Container 컴포넌트 구현
gabrielyoon7 Sep 17, 2023
6eee7fb
feat: Container 예제 페이지 구현
gabrielyoon7 Sep 17, 2023
61a63d8
refactor: storybook 예제 개선
gabrielyoon7 Sep 17, 2023
df11769
Update README.md
gabrielyoon7 Sep 17, 2023
55600f1
docs: 리드미 수정
gabrielyoon7 Sep 17, 2023
2821779
feat: Grid 구현 및 예제 추가
gabrielyoon7 Sep 17, 2023
9fca256
refactor: Grid 스타일 분리
gabrielyoon7 Sep 17, 2023
c20ccc6
refactor: Grid 스토리북 작성
gabrielyoon7 Sep 17, 2023
6e1b28c
feat: Flex 컴포넌트 작성
gabrielyoon7 Sep 17, 2023
fe4448e
refactor: Flex 스타일드 컴포넌트 분리
gabrielyoon7 Sep 17, 2023
6bcbf25
test: Flex 스토리북 작성
gabrielyoon7 Sep 17, 2023
d0aecaf
refactor: ThemeProvider 도입 및 spacing 정의
gabrielyoon7 Sep 18, 2023
1d706ee
refactor: ThemeProvider의 spacing 적용
gabrielyoon7 Sep 18, 2023
f6ff274
test: MinWidth 예제 추가
gabrielyoon7 Sep 18, 2023
e3429ed
fix: Unknown Prop Warning 문제 해결
gabrielyoon7 Sep 18, 2023
9ceeb46
fix: Unknown Prop Warning 문제 해결
gabrielyoon7 Sep 18, 2023
4295de7
fix: Unknown Prop Warning 문제 해결
gabrielyoon7 Sep 18, 2023
f85c013
fix: key가 없는 오류 수정
gabrielyoon7 Sep 18, 2023
bf5f8cb
refactor: 기본 배경에 노란색 적용
gabrielyoon7 Sep 18, 2023
3d51cc4
test: Flex props 설명 추가
gabrielyoon7 Sep 18, 2023
1d7b81a
refactor: 타입 위치 수정
gabrielyoon7 Sep 18, 2023
36a8f45
fix: 웹스톰 오류 수정
gabrielyoon7 Sep 18, 2023
debd0ce
style: prettier 일괄 적용
gabrielyoon7 Sep 18, 2023
b9dbe63
refactor: lib 폴더 적용
gabrielyoon7 Sep 18, 2023
8c8b981
chore: path @types/node vite-plugin-dts 설치
gabrielyoon7 Sep 18, 2023
a3ea011
chore: 배포를 위한 빌드 설정
gabrielyoon7 Sep 18, 2023
bf49e5a
refactor: 구조 개선
gabrielyoon7 Sep 18, 2023
d7cf2ca
chore: npm 배포 설정
gabrielyoon7 Sep 18, 2023
3e54c5d
chore: npm 배포 설정
gabrielyoon7 Sep 18, 2023
f12fabf
refactor: 미사용 코드 제거
gabrielyoon7 Sep 18, 2023
8e5abc3
chore: 배포 오류 수정
gabrielyoon7 Sep 18, 2023
2a60d90
docs: readme 수정
gabrielyoon7 Sep 18, 2023
9eef417
chore: 배포 설정 수정
gabrielyoon7 Sep 18, 2023
8cb7c86
chore: 배포 설정 수정
gabrielyoon7 Sep 18, 2023
7d7915a
chore: github 자동 배포 설정 수정
gabrielyoon7 Sep 18, 2023
5cd49ee
chore: github pages 자동 배포 오류 수정
gabrielyoon7 Sep 18, 2023
91c12a4
chore: github pages 자동 배포 오류 수정
gabrielyoon7 Sep 18, 2023
5e77b85
refactor: 그리드의 속성을 옵셔널 하게 변경
gabrielyoon7 Sep 18, 2023
902470d
docs: readme 작성
gabrielyoon7 Sep 18, 2023
cc09fae
refactor: 불필요한 코드 및 파일 제거
gabrielyoon7 Sep 24, 2023
c68852d
feat: SplitPane 뼈대 파일 추가
gabrielyoon7 Sep 25, 2023
4a8d256
refactor: styled-components 분리
gabrielyoon7 Sep 25, 2023
f24ada6
refactor: 주석 추가
gabrielyoon7 Sep 25, 2023
0d9f49a
docs: 리드미 수정
gabrielyoon7 Sep 25, 2023
f472124
refactor: 배포 설정 수정
gabrielyoon7 Sep 25, 2023
4e37a25
docs: 스토리북 배포 링크 수정
gabrielyoon7 Sep 25, 2023
ab9debe
refactor: SplitPane 배포 설정
gabrielyoon7 Sep 25, 2023
338b838
refactor: SplitPane 배포 설정
gabrielyoon7 Sep 25, 2023
ff44c2e
test: 스토리북 예제 추가
gabrielyoon7 Sep 25, 2023
fd69069
docs: readme 주소 개선
gabrielyoon7 Sep 25, 2023
b621af7
chore: npmjs 버전 수정
gabrielyoon7 Sep 25, 2023
fb8a9f4
Merge branch 'gabrielyoon7' into step2
gabrielyoon7 Sep 25, 2023
790ccdb
test: 중첩 예제 추가
gabrielyoon7 Sep 26, 2023
e2cd604
Merge remote-tracking branch 'origin/step2' into step2
gabrielyoon7 Sep 26, 2023
fa867ad
refactor: SplitPaneContainer의 children 속성을 필수로 지정
gabrielyoon7 Sep 29, 2023
72b6979
refactor: SplitPane의 타입 오류 메시지가 출력되지 않도록 개선
gabrielyoon7 Sep 29, 2023
37143e8
refactor: 가운데 조절 막대의 디자인을 개선
gabrielyoon7 Sep 29, 2023
7b05fb0
refactor: 모바일 터치 대응
gabrielyoon7 Sep 29, 2023
0b97ba0
chore: vitest 설치
gabrielyoon7 Sep 29, 2023
3231d5c
refactor: ErrorBoundary.tsx 구현 및 적용
gabrielyoon7 Sep 30, 2023
ffea388
refactor: 자식의 길이가 2가 아닌 경우 경고
gabrielyoon7 Sep 30, 2023
154b692
refactor: 불필요한 속성 제거
gabrielyoon7 Sep 30, 2023
63089e3
refactor: 속성 값에 대한 검사를 진행
gabrielyoon7 Sep 30, 2023
7bf23c6
refactor: 다시 시도하기 버튼 구현
gabrielyoon7 Sep 30, 2023
60b2f74
fix: 영역 설정이 제대로 되지 않는 문제를 수정
gabrielyoon7 Sep 30, 2023
e68197f
refactor: 프롭 검사기 추가
gabrielyoon7 Sep 30, 2023
6f7daf0
refactor: constants 분리
gabrielyoon7 Sep 30, 2023
0903fc8
test: 테스트 케이스 추가
gabrielyoon7 Sep 30, 2023
7dc2aad
chore: readme 및 버전 수정
gabrielyoon7 Sep 30, 2023
ab50987
chore: readme 및 버전 수정
gabrielyoon7 Sep 30, 2023
d8f6f68
refactor: 불필요한 출력문 제거
gabrielyoon7 Sep 30, 2023
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
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Deploy static content to Pages

on:
push:
branches: ["main", "gabrielyoon7", "step1", "step2"]
branches: [ "step1", "step2" ]

workflow_dispatch:

Expand Down
32 changes: 29 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ npm install @gabrielyoon7/layout-component
yarn add @gabrielyoon7/layout-component
```

[스토리북](https://65068c38c8cef469d3e5e634-zeukkiflsp.chromatic.com/)
[npm](https://www.npmjs.com/package/@gabrielyoon7/layout-component)

## Container

### 소개
Expand All @@ -30,7 +33,7 @@ function MyComponent() {

```

[Container 스토리북 보러가기](https://65068c38c8cef469d3e5e634-otupvlrdhy.chromatic.com/?path=/docs/components-container--docs)
[Container 스토리북 보러가기](https://65068c38c8cef469d3e5e634-zeukkiflsp.chromatic.com/?path=/docs/components-container--docs)

## Grid

Expand Down Expand Up @@ -60,7 +63,7 @@ function MyComponent() {

```

[Grid 스토리북 보러가기](https://65068c38c8cef469d3e5e634-otupvlrdhy.chromatic.com/?path=/docs/components-grid--docs)
[Grid 스토리북 보러가기](https://65068c38c8cef469d3e5e634-zeukkiflsp.chromatic.com/?path=/docs/components-grid--docs)

## Flex

Expand All @@ -83,4 +86,27 @@ function MyComponent() {

```

[Flex 스토리북 보러가기](https://65068c38c8cef469d3e5e634-otupvlrdhy.chromatic.com/?path=/docs/components-flex--docs)
[Flex 스토리북 보러가기](https://65068c38c8cef469d3e5e634-zeukkiflsp.chromatic.com/?path=/docs/components-flex--docs)

## SplitPane

### 소개

이 컴포넌트는 SplitPane 레이아웃을 구현하기 위한 React 컴포넌트입니다. 이 컴포넌트를 사용하면 UI 디자인에서 SplitPane 레이아웃을 쉽게 구현할 수 있습니다.

```typescript jsx
import {SplitPane} from "@gabrielyoon7/layout-component";

function MyComponent() {
return (
<SplitPane defaultSize="50%" minSize="10%" maxSize="90%">
<div style={{backgroundColor: 'yellow', height: '100px'}}/>
<div style={{backgroundColor: 'yellowgreen', height: '100px'}}/>
</SplitPane>
)
}

```

[SplitPane 스토리북 보러가기](https://65068c38c8cef469d3e5e634-zeukkiflsp.chromatic.com/?path=/docs/components-splitpane--docs)

8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@gabrielyoon7/layout-component",
"version": "0.0.5",
"version": "0.0.11",
"description": "A layout component for React (with woowacourse)",
"type": "module",
"main": "dist/index.umd.cjs",
Expand All @@ -21,7 +21,8 @@
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
"build-storybook": "storybook build",
"test": "vitest"
},
"dependencies": {
"react": "^18.2.0",
Expand Down Expand Up @@ -53,6 +54,7 @@
"storybook": "^7.4.2",
"typescript": "^5.0.2",
"vite": "^4.4.5",
"vite-plugin-dts": "^3.5.3"
"vite-plugin-dts": "^3.5.3",
"vitest": "^0.34.6"
}
}
1 change: 1 addition & 0 deletions src/lib/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export {default as Container} from "./layouts/Container/Container";
export {default as Flex} from "./layouts/Flex/Flex";
export {default as Grid} from "./layouts/Grid/Grid";
export {default as SplitPane} from "./layouts/SplitPane/SplitPane";
46 changes: 46 additions & 0 deletions src/lib/layouts/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React, {Component, ErrorInfo, ReactNode} from "react";

interface Props {
children?: ReactNode;
}

interface State {
hasError: boolean;
error: Error | null;
errorInfo?: ErrorInfo | null;
}

class ErrorBoundary extends Component<Props, State> {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 아예 에러 바운더리로 처리하셨군요 bb

public state: State = {
hasError: false,
error: null,
};

public static getDerivedStateFromError(error: Error): State {
return {
hasError: true,
error,
};
}

public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
console.error("Uncaught error:", error, errorInfo);
this.setState({errorInfo});
}

public render() {
if (this.state.hasError) {
return (
<div>
<h1>무언가 잘못됐어요...!</h1>
<p>{this.state.error?.toString()}</p>
<button onClick={() => this.setState({hasError: false})}>다시 시도하기</button>
</div>
);
}

return this.props.children;
}
}

export default ErrorBoundary;
130 changes: 130 additions & 0 deletions src/lib/layouts/SplitPane/SplitPane.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import type {Meta} from "@storybook/react";
import SplitPane from "./index.ts";
import {SplitPaneProps} from "./SplitPane.tsx";

const meta = {
title: "Components/SplitPane",
component: SplitPane,
tags: ["autodocs"],
args: {
defaultSize: "20%",
minSize: "10%",
maxSize: "90%",
},
argTypes: {
defaultSize: {
control: {
type: "text",
},
description: "SplitPane의 기본 사이즈를 설정합니다.",
},
minSize: {
control: {
type: "text",
},
description: "SplitPane 좌측 영역의 최소 사이즈를 설정합니다."
},
maxSize: {
control: {
type: "text",
},
description: "SplitPane 좌측 영역의 최대 사이즈를 설정합니다."
}
},
} satisfies Meta<typeof SplitPane>;

export default meta;

const loremIpsum = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis vulputate nunc eu tempor tempor. Maecenas ipsum nisi, placerat sit amet arcu eu, egestas luctus orci. Etiam sed ante eu metus aliquet dapibus. Nullam eget dolor diam. Praesent et lobortis massa. Proin ornare, risus quis pretium vulputate, lacus lacus vehicula ex, eleifend vestibulum sapien augue et quam. Nulla id augue felis. Quisque vitae elit felis. Vestibulum vitae rhoncus elit. Duis imperdiet tortor vitae tellus vulputate, et sagittis est ullamcorper. Fusce dignissim ultricies tristique. Nullam congue mi ut venenatis pellentesque. Proin egestas sodales volutpat.`;

export const Default = (args: SplitPaneProps) => (
<SplitPane {...args}>
<div style={{backgroundColor: 'yellow', height: '100px'}}/>
<div style={{backgroundColor: 'yellowgreen', height: '100px'}}/>
</SplitPane>
);

export const Texts = (args: SplitPaneProps) => (
<SplitPane {...args}>
<div>
{loremIpsum}
</div>
<div>
{loremIpsum}
</div>
</SplitPane>
);

export const Duplicated = (args: SplitPaneProps) => (
<SplitPane {...args}>
<div>
{loremIpsum}
</div>
<SplitPane {...args}>
<div>
{loremIpsum}
</div>
<div>
{loremIpsum}
</div>
</SplitPane>
</SplitPane>
);

export const WrongChildren = (args: SplitPaneProps) => (
<SplitPane {...args}>
<div>
{loremIpsum}
</div>
<div>
{loremIpsum}
</div>
<div>
{loremIpsum}
</div>
</SplitPane>
);

export const WrongArgs = () => (
<SplitPane defaultSize="20%" minSize="10%" maxSize="110%">
<div>
{loremIpsum}
</div>
<div>
{loremIpsum}
</div>
</SplitPane>
);

export const WrongArgs2 = () => (
<SplitPane defaultSize="20%" minSize="10%" maxSize="10%">
<div>
{loremIpsum}
</div>
<div>
{loremIpsum}
</div>
</SplitPane>
);

export const WrongArgs3 = () => (
<SplitPane defaultSize="20" minSize="10%" maxSize="90%">
<div>
{loremIpsum}
</div>
<div>
{loremIpsum}
</div>
</SplitPane>
);

export const WrongArgs4 = () => (
<SplitPane defaultSize="20%" minSize="1a0%" maxSize="90%">
<div>
{loremIpsum}
</div>
<div>
{loremIpsum}
</div>
</SplitPane>
);
23 changes: 23 additions & 0 deletions src/lib/layouts/SplitPane/SplitPane.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import styled from "styled-components";

interface ResizablePaneProps {
$size: string;
}

export const SplitPaneContainer = styled.div`
display: flex;
width: 100%;
`;

export const ResizablePane = styled.div<ResizablePaneProps>`
overflow: auto;
width: ${({$size}) => $size};
`;

export const Resizer = styled.div`
padding: 0px 1px;
margin: 0px 2px;
border-left: 1px solid #b5b5b5;
border-right: 1px solid #b5b5b5;
cursor: col-resize;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 새로운 속성 배워갑니당

`;
21 changes: 21 additions & 0 deletions src/lib/layouts/SplitPane/SplitPane.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {ReactNode} from 'react';
import ErrorBoundary from "../ErrorBoundary.tsx";
import SplitPaneRenderer from "./SplitPaneRenderer.tsx";

export interface SplitPaneProps {
defaultSize: string;
minSize: string;
maxSize: string;
children: ReactNode[];
}

const SplitPane = ({defaultSize, minSize, maxSize, children}: SplitPaneProps) => {

return (
<ErrorBoundary>
<SplitPaneRenderer defaultSize={defaultSize} minSize={minSize} maxSize={maxSize}>{children}</SplitPaneRenderer>
</ErrorBoundary>
);
}

export default SplitPane;
31 changes: 31 additions & 0 deletions src/lib/layouts/SplitPane/SplitPaneRenderer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {useSplitPane} from "./useSplitPane.ts";
import {checkValidProps,} from "./validate.ts";
import {SplitPaneProps} from "./SplitPane.tsx";
import {ResizablePane, Resizer, SplitPaneContainer} from "./SplitPane.styles.ts";

function SplitPaneRenderer({defaultSize, minSize, maxSize, children}: SplitPaneProps) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renderer로 분리하신 이유가 무엇인가요??

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

에러바운더리를 적용하려면 에러가 하위 컴포넌트에서 발생해야 감지가 됐기 때문입니다...!


const {
containerRef,
leftPaneRef,
rightPaneRef,
paneSize,
handleMouseDown,
} = useSplitPane(defaultSize, minSize, maxSize);

checkValidProps({defaultSize, minSize, maxSize, children});

return (
<SplitPaneContainer ref={containerRef}>
<ResizablePane $size={paneSize} ref={leftPaneRef}>
{children[0]}
</ResizablePane>
<Resizer onMouseDown={handleMouseDown}/>
<ResizablePane $size={`calc(100% - ${paneSize} - 3px)`} ref={rightPaneRef}>
{children[1]}
</ResizablePane>
</SplitPaneContainer>
);
}

export default SplitPaneRenderer;
10 changes: 10 additions & 0 deletions src/lib/layouts/SplitPane/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const ERROR_MESSAGE_CHECK_ENDS_WITH_PERCENTAGE = 'defaultSize, minSize, maxSize는 반드시 %로 끝나야 합니다.';
export const ERROR_MESSAGE_CHECK_DEFAULT_SIZE_LESS_THAN_MIN_SIZE = 'defaultSize는 minSize보다 작을 수 없습니다.';
export const ERROR_MESSAGE_CHECK_DEFAULT_SIZE_GREATER_THAN_MAX_SIZE = 'defaultSize는 maxSize보다 클 수 없습니다.';
export const ERROR_MESSAGE_CHECK_CHILDREN_LENGTH = 'SplitPane 컴포넌트의 children은 반드시 2개여야 합니다.';
export const ERROR_MESSAGE_CHECK_DEFAULT_SIZE = 'defaultSize는 0% ~ 100% 사이의 값이어야 합니다.';
export const ERROR_MESSAGE_CHECK_MIN_SIZE = 'minSize는 0% ~ 100% 사이의 값이어야 합니다.';
export const ERROR_MESSAGE_CHECK_MAX_SIZE = 'maxSize는 0% ~ 100% 사이의 값이어야 합니다.';
export const ERROR_MESSAGE_CHECK_DEFAULT_NUMBER_PERCENTAGE = 'defaultSize는 숫자% 형태여야 합니다.';
export const ERROR_MESSAGE_CHECK_MIN_SIZE_NUMBER_PERCENTAGE = 'minSize는 숫자% 형태여야 합니다.';
export const ERROR_MESSAGE_CHECK_MAX_SIZE_NUMBER_PERCENTAGE = 'maxSize는 숫자% 형태여야 합니다.';
3 changes: 3 additions & 0 deletions src/lib/layouts/SplitPane/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import SplitPane from "./SplitPane.tsx";

export default SplitPane;
Loading