From 07e9a823c2a47bc0f95a00d82d086a5910791ccc Mon Sep 17 00:00:00 2001 From: Eugene Kim Date: Sun, 22 Sep 2024 17:22:56 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20Table=20=EC=BD=94=EB=93=9C=20=EA=B9=94?= =?UTF-8?q?=EB=81=94=ED=95=98=EA=B2=8C=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/wow-ui/package.json | 33 +++++--- packages/wow-ui/rollup.config.js | 7 +- .../src/components/Table/Table.stories.tsx | 2 +- .../wow-ui/src/components/Table/Table.tsx | 78 +++++------------- .../components/Table/TableBodyContainer.tsx | 21 ----- .../src/components/Table/TableContext.ts | 12 +++ .../src/components/Table/TableHeader.tsx | 32 -------- .../wow-ui/src/components/Table/Tbody.tsx | 6 +- packages/wow-ui/src/components/Table/Td.tsx | 44 +++++----- packages/wow-ui/src/components/Table/Th.tsx | 22 ++--- .../wow-ui/src/components/Table/Thead.tsx | 69 ++++++++++------ packages/wow-ui/src/components/Table/Tr.tsx | 80 ++++++++++--------- packages/wow-ui/src/hooks/useCountRow.ts | 25 ++++++ .../wow-ui/src/hooks/useTableCheckState.ts | 3 - packages/wow-ui/src/types/table.ts | 19 +++++ 15 files changed, 230 insertions(+), 223 deletions(-) delete mode 100644 packages/wow-ui/src/components/Table/TableBodyContainer.tsx create mode 100644 packages/wow-ui/src/components/Table/TableContext.ts delete mode 100644 packages/wow-ui/src/components/Table/TableHeader.tsx create mode 100644 packages/wow-ui/src/hooks/useCountRow.ts create mode 100644 packages/wow-ui/src/types/table.ts diff --git a/packages/wow-ui/package.json b/packages/wow-ui/package.json index dc301539..53cdffa5 100644 --- a/packages/wow-ui/package.json +++ b/packages/wow-ui/package.json @@ -45,11 +45,6 @@ "require": "./dist/TableBodyContainer.cjs", "import": "./dist/TableBodyContainer.js" }, - "./TableCell": { - "types": "./dist/components/Table/TableCell.d.ts", - "require": "./dist/TableCell.cjs", - "import": "./dist/TableCell.js" - }, "./TableContainer": { "types": "./dist/components/Table/TableContainer.d.ts", "require": "./dist/TableContainer.cjs", @@ -60,10 +55,30 @@ "require": "./dist/TableHeader.cjs", "import": "./dist/TableHeader.js" }, - "./TableRow": { - "types": "./dist/components/Table/TableRow.d.ts", - "require": "./dist/TableRow.cjs", - "import": "./dist/TableRow.js" + "./Tbody": { + "types": "./dist/components/Table/Tbody.d.ts", + "require": "./dist/Tbody.cjs", + "import": "./dist/Tbody.js" + }, + "./Td": { + "types": "./dist/components/Table/Td.d.ts", + "require": "./dist/Td.cjs", + "import": "./dist/Td.js" + }, + "./Th": { + "types": "./dist/components/Table/Th.d.ts", + "require": "./dist/Th.cjs", + "import": "./dist/Th.js" + }, + "./Thead": { + "types": "./dist/components/Table/Thead.d.ts", + "require": "./dist/Thead.cjs", + "import": "./dist/Thead.js" + }, + "./Tr": { + "types": "./dist/components/Table/Tr.d.ts", + "require": "./dist/Tr.cjs", + "import": "./dist/Tr.js" }, "./Switch": { "types": "./dist/components/Switch/index.d.ts", diff --git a/packages/wow-ui/rollup.config.js b/packages/wow-ui/rollup.config.js index 0b83a5cb..fd2fb3b2 100644 --- a/packages/wow-ui/rollup.config.js +++ b/packages/wow-ui/rollup.config.js @@ -25,10 +25,13 @@ export default { Tag: "./src/components/Tag", Table: "./src/components/Table/Table", TableBodyContainer: "./src/components/Table/TableBodyContainer", - TableCell: "./src/components/Table/TableCell", TableContainer: "./src/components/Table/TableContainer", TableHeader: "./src/components/Table/TableHeader", - TableRow: "./src/components/Table/TableRow", + Tbody: "./src/components/Table/Tbody", + Td: "./src/components/Table/Td", + Th: "./src/components/Table/Th", + Thead: "./src/components/Table/Thead", + Tr: "./src/components/Table/Tr", Switch: "./src/components/Switch", Stepper: "./src/components/Stepper", BlueSpinner: "./src/components/Spinner/BlueSpinner", diff --git a/packages/wow-ui/src/components/Table/Table.stories.tsx b/packages/wow-ui/src/components/Table/Table.stories.tsx index 2d234c35..be372fbb 100644 --- a/packages/wow-ui/src/components/Table/Table.stories.tsx +++ b/packages/wow-ui/src/components/Table/Table.stories.tsx @@ -304,7 +304,7 @@ const ControlledTable = () => { 선택한 테이블 요소 모두 초기화 diff --git a/packages/wow-ui/src/components/Table/Table.tsx b/packages/wow-ui/src/components/Table/Table.tsx index 5376d528..faf78fa3 100644 --- a/packages/wow-ui/src/components/Table/Table.tsx +++ b/packages/wow-ui/src/components/Table/Table.tsx @@ -2,33 +2,24 @@ import { css, cva } from "@styled-system/css"; import { styled } from "@styled-system/jsx"; import { clsx } from "clsx"; -import type { - CSSProperties, - ForwardRefExoticComponent, - ReactNode, - Ref, -} from "react"; -import React, { - Children, - createContext, - forwardRef, - isValidElement, - useEffect, - useState, -} from "react"; +import type { CSSProperties, ReactNode, Ref } from "react"; +import { forwardRef } from "react"; +import { TableContext } from "@/components/Table/TableContext"; import Tbody from "@/components/Table/Tbody"; import Td from "@/components/Table/Td"; import Th from "@/components/Table/Th"; import Thead from "@/components/Table/Thead"; import Tr from "@/components/Table/Tr"; +import useCountRow from "@/hooks/useCountRow"; import useTableCheckState from "@/hooks/useTableCheckState"; +import type { TableComponentType } from "@/types/table"; /** * @description 데이터 및 비동기 결과물을 나타낼 수 있는 테이블 컴포넌트입니다. * @param {string} [tableCaption] 테이블에 대한 설명을 나타내는 캡션입니다. - * @param {TableOptionProps} [options] 테이블에 대한 상세한 옵션값을 설정합니다. - * @param {number[]} [selectedRows] default 값을 설정하거나, 외부에서 table의 체크 상태 관리할 수 있는 변수입니다. + * @param {showCheckbox} [boolean] 테이블에 대한 상세한 옵션값을 설정합니다. + * @param {number[]} [selectedRowsProp] default 값을 설정하거나, 외부에서 table의 체크 상태 관리할 수 있는 변수입니다. * @param {(selectedRows: number[]) => void} [onChange] 외부 활성 상태가 변경될 때 호출되는 함수입니다. * @param {() => void} [className] table 컴포넌트에게 전달할 className을 정의합니다. * @param {() => void} [fullWidth=false] table 컴포넌트의 가로 길이를 결정할 수 있습니다. @@ -36,27 +27,25 @@ import useTableCheckState from "@/hooks/useTableCheckState"; * @param {Ref} [ref] ref 렌더링된 요소 또는 컴포넌트에 연결할 ref입니다. */ -interface TableProps { +export interface TableProps { tableCaption?: string; showCheckbox?: boolean; - selectedRowsProps?: number[]; + selectedRowsProp?: number[]; onChange?: (selectedRows: number[]) => void; - className?: string; fullWidth?: boolean; style?: CSSProperties; children: ReactNode; + className?: string; } -export const TableContext = createContext(null); - const TableComponent = forwardRef( - function PaginationTable( + function TableFunction( { tableCaption = "", children, showCheckbox, className, - selectedRowsProps, + selectedRowsProp, onChange, fullWidth = false, style, @@ -64,40 +53,20 @@ const TableComponent = forwardRef( }: TableProps, ref: Ref ) { - const [rowValue, setRowValues] = useState([]); - useEffect(() => { - Children.forEach(children, (child) => { - if (isValidElement(child) && child.type === Table.Tbody) { - Children.forEach(child.props.children, (row) => { - if (isValidElement(row) && row.type === Table.Tr) { - const rowProps = row.props as { value: number }; - setRowValues((prevValues) => [...prevValues, rowProps.value]); - } - }); - } - }); - }, []); - + const { rowValues } = useCountRow(children); const { handleRowCheckboxChange, handleHeaderCheckboxChange, selectedRows, - } = useTableCheckState(rowValue, selectedRowsProps, onChange); + } = useTableCheckState(rowValues, selectedRowsProp, onChange); const contextValue: ReturnType & - TableProps & { rowValue: number[] } = { - rowValue, - handleRowCheckboxChange, - handleHeaderCheckboxChange, + Omit & { rowValues: number[] } = { + rowValues, selectedRows, - children, showCheckbox, - tableCaption, - selectedRowsProps, - onChange, - className, - fullWidth, - style, + handleRowCheckboxChange, + handleHeaderCheckboxChange, }; return ( @@ -128,17 +97,6 @@ const TableComponent = forwardRef( } ); -interface TableComponentType - extends ForwardRefExoticComponent< - TableProps & React.RefAttributes - > { - Thead: typeof Thead; - Th: typeof Th; - Tbody: typeof Tbody; - Tr: typeof Tr; - Td: typeof Td; -} - const Table = TableComponent as TableComponentType; Table.Thead = Thead; Table.Th = Th; diff --git a/packages/wow-ui/src/components/Table/TableBodyContainer.tsx b/packages/wow-ui/src/components/Table/TableBodyContainer.tsx deleted file mode 100644 index 7bb35d9d..00000000 --- a/packages/wow-ui/src/components/Table/TableBodyContainer.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { styled } from "@styled-system/jsx"; -import type { CSSProperties, PropsWithChildren } from "react"; -import { forwardRef } from "react"; - -interface TableBodyProps extends PropsWithChildren { - style?: CSSProperties; -} - -const TableBodyContainer = forwardRef( - (props, ref) => { - const { children } = props; - - return ( - - {children} - - ); - } -); - -export default TableBodyContainer; diff --git a/packages/wow-ui/src/components/Table/TableContext.ts b/packages/wow-ui/src/components/Table/TableContext.ts new file mode 100644 index 00000000..cb457378 --- /dev/null +++ b/packages/wow-ui/src/components/Table/TableContext.ts @@ -0,0 +1,12 @@ +import { createContext } from "react"; + +import useSafeContext from "@/hooks/useSafeContext"; + +export const TableContext = createContext(null); + +export const useTableContext = () => { + const context = useSafeContext(TableContext); + return context; +}; + +export const TableCheckedContext = createContext(0); diff --git a/packages/wow-ui/src/components/Table/TableHeader.tsx b/packages/wow-ui/src/components/Table/TableHeader.tsx deleted file mode 100644 index 68f69b8b..00000000 --- a/packages/wow-ui/src/components/Table/TableHeader.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { css } from "@styled-system/css"; -import type { CSSProperties, PropsWithChildren } from "react"; - -interface TableHeaderProps extends PropsWithChildren { - style?: CSSProperties; -} -const TableHeader = (props: TableHeaderProps) => { - const { children } = props; - return ( - - ); -}; - -const TableHeaderStyle = css({ - alignItems: "center", - backgroundColor: "backgroundAlternative", - color: "sub", - height: "44px", - letterSpacing: "wider", - maxWidth: "300px", - minWidth: "74px", - overflow: "hidden", - paddingX: "sm", - textAlign: "start", - textOverflow: "ellipsis", - textStyle: "label2", - whiteSpace: "nowrap", -}); - -export default TableHeader; diff --git a/packages/wow-ui/src/components/Table/Tbody.tsx b/packages/wow-ui/src/components/Table/Tbody.tsx index 377434b1..28f87088 100644 --- a/packages/wow-ui/src/components/Table/Tbody.tsx +++ b/packages/wow-ui/src/components/Table/Tbody.tsx @@ -4,14 +4,14 @@ import React, { forwardRef } from "react"; interface TableBodyProps extends PropsWithChildren { style?: CSSProperties; + className?: string; } const Tbody = forwardRef( (props, ref) => { - const { children } = props; - + const { children, ...rest } = props; return ( - + {children} ); diff --git a/packages/wow-ui/src/components/Table/Td.tsx b/packages/wow-ui/src/components/Table/Td.tsx index ec0d53d4..9b8b247b 100644 --- a/packages/wow-ui/src/components/Table/Td.tsx +++ b/packages/wow-ui/src/components/Table/Td.tsx @@ -1,31 +1,37 @@ import { cva } from "@styled-system/css"; import { styled } from "@styled-system/jsx"; -import { type CSSProperties, type PropsWithChildren, useContext } from "react"; +import type { CSSProperties, PropsWithChildren, Ref } from "react"; +import { forwardRef, useContext } from "react"; -import { TableContext } from "@/components/Table/Table"; -import { TableCheckedContext } from "@/components/Table/Tr"; -import useSafeContext from "@/hooks/useSafeContext"; +import { + TableCheckedContext, + useTableContext, +} from "@/components/Table/TableContext"; interface TableCellProps extends PropsWithChildren { style?: CSSProperties; + className?: string; } -const Td = (props: TableCellProps) => { - const { children } = props; - const { selectedRows } = useSafeContext(TableContext); - const value = useContext(TableCheckedContext); - const isSelected = selectedRows.some((row: number) => row === value); +const Td = forwardRef( + (props: TableCellProps, ref: Ref) => { + const { children, ...rest } = props; + const { selectedRows } = useTableContext(); + const value = useContext(TableCheckedContext); + const isSelected = selectedRows.some((row: number) => row === value); - return ( - - {children} - - ); -}; + return ( + + {children} + + ); + } +); const TableCellStyle = cva({ base: { diff --git a/packages/wow-ui/src/components/Table/Th.tsx b/packages/wow-ui/src/components/Table/Th.tsx index 0849c636..8d6efff4 100644 --- a/packages/wow-ui/src/components/Table/Th.tsx +++ b/packages/wow-ui/src/components/Table/Th.tsx @@ -1,17 +1,21 @@ import { css } from "@styled-system/css"; -import type { CSSProperties, PropsWithChildren } from "react"; +import type { CSSProperties, PropsWithChildren, Ref } from "react"; +import { forwardRef } from "react"; interface TableHeaderProps extends PropsWithChildren { style?: CSSProperties; + className?: string; } -const Th = (props: TableHeaderProps) => { - const { children } = props; - return ( - - ); -}; +const Th = forwardRef( + (props: TableHeaderProps, ref: Ref) => { + const { children, ...rest } = props; + return ( + + ); + } +); const TableHeaderStyle = css({ alignItems: "center", diff --git a/packages/wow-ui/src/components/Table/Thead.tsx b/packages/wow-ui/src/components/Table/Thead.tsx index e03406ae..7b9936ff 100644 --- a/packages/wow-ui/src/components/Table/Thead.tsx +++ b/packages/wow-ui/src/components/Table/Thead.tsx @@ -1,35 +1,54 @@ import { styled } from "@styled-system/jsx"; -import type { PropsWithChildren } from "react"; +import type { CSSProperties, PropsWithChildren, Ref } from "react"; +import { forwardRef } from "react"; import Checkbox from "@/components/Checkbox"; -import { TableContext } from "@/components/Table/Table"; +import { useTableContext } from "@/components/Table/TableContext"; import Th from "@/components/Table/Th"; -import useSafeContext from "@/hooks/useSafeContext"; -interface TheadProps extends PropsWithChildren {} +interface TheadProps extends PropsWithChildren { + style?: CSSProperties; + className?: string; +} -const Thead = (props: TheadProps) => { - const { selectedRows, showCheckbox, handleHeaderCheckboxChange, rowValue } = - useSafeContext(TableContext); +const Thead = forwardRef( + function TheadFunction( + { children, ...rest }: TheadProps, + ref: Ref + ) { + const { + selectedRows, + showCheckbox, + handleHeaderCheckboxChange, + rowValues, + } = useTableContext(); - const isHeaderCheckboxChecked = - selectedRows.length === rowValue.length && rowValue.length > 0; - return ( - - - {showCheckbox && ( - - )} - {props.children} - - - ); -}; + const isHeaderCheckboxChecked = + selectedRows.length === rowValues.length && rowValues.length > 0; + return ( + + + {showCheckbox && ( + + )} + {children} + + + ); + } +); export default Thead; diff --git a/packages/wow-ui/src/components/Table/Tr.tsx b/packages/wow-ui/src/components/Table/Tr.tsx index 49c89bcf..a0a65b81 100644 --- a/packages/wow-ui/src/components/Table/Tr.tsx +++ b/packages/wow-ui/src/components/Table/Tr.tsx @@ -1,52 +1,54 @@ import { styled } from "@styled-system/jsx"; -import { - createContext, - type CSSProperties, - type PropsWithChildren, -} from "react"; +import type { CSSProperties, PropsWithChildren, Ref } from "react"; +import { forwardRef } from "react"; import Checkbox from "@/components/Checkbox"; -import { TableContext } from "@/components/Table/Table"; +import { + TableCheckedContext, + useTableContext, +} from "@/components/Table/TableContext"; import Td from "@/components/Table/Td"; -import useSafeContext from "@/hooks/useSafeContext"; interface TableRowProps extends PropsWithChildren { style?: CSSProperties; value?: number; - id?: string; + className?: string; } -export const TableCheckedContext = createContext(0); - -const TableRow = (props: TableRowProps) => { - const { children, value } = props; - const { selectedRows, handleRowCheckboxChange, showCheckbox } = - useSafeContext(TableContext); - const isSelected = selectedRows.some((row: number) => row === value); - return ( - - - {showCheckbox && ( - - )} - {children} - - - ); -}; +const TableRow = forwardRef( + function TableRowFunction( + props: TableRowProps, + ref: Ref + ) { + const { children, value, ...rest } = props; + const { selectedRows, handleRowCheckboxChange, showCheckbox } = + useTableContext(); + const isSelected = selectedRows.some((row: number) => row === value); + return ( + + + {showCheckbox && ( + + )} + {children} + + + ); + } +); export default TableRow; diff --git a/packages/wow-ui/src/hooks/useCountRow.ts b/packages/wow-ui/src/hooks/useCountRow.ts new file mode 100644 index 00000000..0bf4af9a --- /dev/null +++ b/packages/wow-ui/src/hooks/useCountRow.ts @@ -0,0 +1,25 @@ +import type { ReactNode } from "react"; +import { Children, isValidElement, useLayoutEffect, useState } from "react"; + +import Table from "@/components/Table/Table"; + +const useCountRow = (children: ReactNode) => { + const [rowValues, setRowValues] = useState([]); + + useLayoutEffect(() => { + Children.forEach(children, (child) => { + if (isValidElement(child) && child.type === Table.Tbody) { + Children.forEach(child.props.children, (row) => { + if (isValidElement(row) && row.type === Table.Tr) { + const rowProps = row.props as { value: number }; + setRowValues((prevValues) => [...prevValues, rowProps.value]); + } + }); + } + }); + }, []); + + return { rowValues }; +}; + +export default useCountRow; diff --git a/packages/wow-ui/src/hooks/useTableCheckState.ts b/packages/wow-ui/src/hooks/useTableCheckState.ts index 8833c397..a2de586c 100644 --- a/packages/wow-ui/src/hooks/useTableCheckState.ts +++ b/packages/wow-ui/src/hooks/useTableCheckState.ts @@ -6,7 +6,6 @@ const useTableCheckState = ( onChange?: (selectedRows: number[]) => void ) => { const [selectedRows, setSelectedRows] = useState([]); - console.log(selectedRows); useEffect(() => { if (selectedRowsProp) { @@ -33,8 +32,6 @@ const useTableCheckState = ( const handleHeaderCheckboxChange = useCallback(() => { setSelectedRows((prevSelectedRows) => { - console.log(prevSelectedRows.length); - console.log(data.length); const newSelectedRows = prevSelectedRows.length === data.length ? [] : [...data]; if (onChange) { diff --git a/packages/wow-ui/src/types/table.ts b/packages/wow-ui/src/types/table.ts new file mode 100644 index 00000000..60f9bb7f --- /dev/null +++ b/packages/wow-ui/src/types/table.ts @@ -0,0 +1,19 @@ +import type { ForwardRefExoticComponent } from "react"; + +import type { TableProps } from "@/components/Table/Table"; +import type Tbody from "@/components/Table/Tbody"; +import type Td from "@/components/Table/Td"; +import type Th from "@/components/Table/Th"; +import type Thead from "@/components/Table/Thead"; +import type Tr from "@/components/Table/Tr"; + +export interface TableComponentType + extends ForwardRefExoticComponent< + TableProps & React.RefAttributes + > { + Thead: typeof Thead; + Th: typeof Th; + Tbody: typeof Tbody; + Tr: typeof Tr; + Td: typeof Td; +}
- {children} - - {children} - + {children} +
- -
+ +
- handleRowCheckboxChange(props.value)} - /> - + handleRowCheckboxChange(value)} + /> +