From 2d57014cdcbf4921dbd7af290b68fedaa57c1a3e Mon Sep 17 00:00:00 2001 From: Saeed Rahimi Date: Tue, 3 Mar 2020 21:16:55 +0330 Subject: [PATCH 1/6] add rtl direction --- assets/index.less | 42 +++++- examples/fixedColumnsAndHeaderRtl.tsx | 186 ++++++++++++++++++++++++++ src/Body/BodyRow.tsx | 4 +- src/Cell/index.tsx | 7 + src/Header/FixedHeader.tsx | 8 +- src/Header/HeaderRow.tsx | 3 +- src/Table.tsx | 11 +- src/context/TableContext.tsx | 2 + src/hooks/useStickyOffsets.ts | 27 ++-- src/utils/fixUtil.ts | 26 +++- 10 files changed, 292 insertions(+), 24 deletions(-) create mode 100644 examples/fixedColumnsAndHeaderRtl.tsx diff --git a/assets/index.less b/assets/index.less index 170e20b84..3115f72a3 100644 --- a/assets/index.less +++ b/assets/index.less @@ -25,6 +25,9 @@ box-sizing: border-box; position: relative; + &-rtl { + direction: rtl; + } // ================= Global ================= table { border-spacing: 0px; @@ -45,6 +48,10 @@ box-sizing: border-box; white-space: normal; word-break: break-word; + .@{tablePrefixCls}-rtl& { + border-left: @border; + border-right: 0; + } } // ================== Cell ================== @@ -58,6 +65,22 @@ border-right-color: transparent; } + .@{tablePrefixCls}-rtl & { + &-fix-right:last-child { + border-right-color: @border-color; + } + &-fix-left:last-child { + border-left-color: transparent; + } + } + + &-fix-left-first { + .@{tablePrefixCls}-rtl & { + box-shadow: 1px 0 0 @border-color; + } + } + + &-fix-left-first::after, &-fix-left-last::after { pointer-events: none; content: ''; @@ -70,9 +93,14 @@ transform: translateX(100%); } - &-fix-right-first { + &-fix-right-first, + &-fix-right-last { box-shadow: -1px 0 0 @border-color; + .@{tablePrefixCls}-rtl & { + box-shadow: none; + } + &::after { pointer-events: none; content: ''; @@ -92,8 +120,9 @@ text-overflow: ellipsis; // Fixed first or last should special process + &.@{tablePrefixCls}-cell-fix-left-first, &.@{tablePrefixCls}-cell-fix-left-last, - &.@{tablePrefixCls}-cell-fix-right-first { + &.@{tablePrefixCls}-cell-fix-right-first &.@{tablePrefixCls}-cell-fix-right-last { overflow: visible; .@{tablePrefixCls}-cell-content { @@ -106,13 +135,15 @@ } &-ping-left { + .@{tablePrefixCls}-cell-fix-left-first::after, .@{tablePrefixCls}-cell-fix-left-last::after { box-shadow: inset 10px 0 8px -8px green; } } &-ping-right { - .@{tablePrefixCls}-cell-fix-right-first::after { + .@{tablePrefixCls}-cell-fix-right-first::after, + .@{tablePrefixCls}-cell-fix-right-last::after { box-shadow: inset -10px 0 8px -8px green; } } @@ -142,6 +173,11 @@ left: -1px; width: 1px; background: @table-head-background-color; + + .@{tablePrefixCls}-rtl& { + right: -1px; + left: auto; + } } } diff --git a/examples/fixedColumnsAndHeaderRtl.tsx b/examples/fixedColumnsAndHeaderRtl.tsx new file mode 100644 index 000000000..04e504c3b --- /dev/null +++ b/examples/fixedColumnsAndHeaderRtl.tsx @@ -0,0 +1,186 @@ +import React from 'react'; +import Table from '../src'; +import '../assets/index.less'; +import { ColumnsType } from '../src/interface'; +import { useCheckbox } from './utils/useInput'; + +interface RecordType { + a: string; + b?: string; + c: string; + d: number; + key: string; +} + +const originData: RecordType[] = [ + { a: 'aaa', b: 'bbb', c: '内容内容内容内容内容', d: 3, key: '1' }, + { a: 'aaa', b: 'bbb', c: '内容内容内容内容内容', d: 3, key: '2' }, + { a: 'aaa', c: '内容内容内容内容内容', d: 2, key: '3' }, + { a: 'aaa', c: '内容内容内容内容内容', d: 2, key: '4' }, + { a: 'aaa', c: '内容内容内容内容内容', d: 2, key: '5' }, + { a: 'aaa', c: '内容内容内容内容内容', d: 2, key: '6' }, + { a: 'aaa', c: '内容内容内容内容内容', d: 2, key: '7' }, + { a: 'aaa', c: '内容内容内容内容内容', d: 2, key: '8' }, + { a: 'aaa', c: '内容内容内容内容内容', d: 2, key: '9' }, +]; + +const longTextData: RecordType[] = [...originData]; +longTextData[0] = { + ...longTextData[0], + a: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', +}; + +function getFixedRightValue(fixRight: boolean, isRtlCol: boolean): 'left' | 'right' { + if (fixRight) { + return isRtlCol ? 'left' : 'right'; + } + return null; +} + +function getFixedLeftValue(fixLeft: boolean, isRtlCol: boolean): 'right' | 'left' { + if (fixLeft) { + return isRtlCol ? 'right' : 'left'; + } + return null; +} + +const useColumn = ( + fixLeft: boolean, + fixTitle: boolean, + fixRight: boolean, + ellipsis: boolean, + percentage: boolean, + isRtlCol: boolean, +) => { + const columns: ColumnsType = React.useMemo( + () => [ + { + title: 'title1', + dataIndex: 'a', + key: 'a', + width: percentage ? '10%' : 80, + fixed: getFixedLeftValue(fixLeft, isRtlCol), + ellipsis, + }, + { + title: 'title2', + dataIndex: 'b', + key: 'b', + width: 80, + fixed: getFixedLeftValue(fixLeft, isRtlCol), + }, + { + title: 'title3', + fixed: fixTitle ? getFixedLeftValue(fixLeft, isRtlCol) : null, + children: [ + { title: 'title4', dataIndex: 'c', key: 'd', width: 100 }, + { title: 'title5', dataIndex: 'c', key: 'e', width: 100 }, + ], + }, + { title: 'title6', dataIndex: 'c', key: 'f' }, + { title: 'title7', dataIndex: 'c', key: 'g' }, + { title: 'title8', dataIndex: 'c', key: 'h' }, + { title: 'title9', dataIndex: 'b', key: 'i' }, + { title: 'title10', dataIndex: 'b', key: 'j' }, + { + title: 'title11', + dataIndex: 'b', + key: 'k', + width: 100, + fixed: getFixedRightValue(fixRight, isRtlCol), + }, + { + title: 'title12', + dataIndex: 'b', + key: 'l', + width: 80, + fixed: getFixedRightValue(fixRight, isRtlCol), + }, + ], + [fixLeft, fixTitle, fixRight, ellipsis, percentage, isRtlCol], + ); + + return columns; +}; + +const Demo = () => { + const [autoWidth, autoWidthProps] = useCheckbox(false); + const [isRtl, isRtlProps] = useCheckbox(false); + const [longText, longTextProps] = useCheckbox(false); + const [fixHeader, fixHeaderProps] = useCheckbox(true); + const [fixLeft, fixLeftProps] = useCheckbox(true); + const [fixRight, fixRightProps] = useCheckbox(true); + const [fixTitle3, fixTitle3Props] = useCheckbox(false); + const [ellipsis, ellipsisProps] = useCheckbox(false); + const [percentage, percentageProps] = useCheckbox(false); + const [empty, emptyProps] = useCheckbox(false); + const columns = useColumn(fixLeft, fixTitle3, fixRight, ellipsis, percentage, isRtl); + + let mergedData: RecordType[]; + if (empty) { + mergedData = null; + } else if (longText) { + mergedData = longTextData; + } else { + mergedData = originData; + } + + return ( + +
+

Fixed columns and header in RTL direction

+ + + + + + + + + + + + + + columns={columns} + scroll={{ x: 1650, y: fixHeader ? 300 : null }} + data={mergedData} + style={{ width: autoWidth ? null : 800 }} + direction={isRtl ? 'rtl' : 'ltr'} + /> +
+
+ ); +}; + +export default Demo; diff --git a/src/Body/BodyRow.tsx b/src/Body/BodyRow.tsx index d7c9280a8..e8665e6eb 100644 --- a/src/Body/BodyRow.tsx +++ b/src/Body/BodyRow.tsx @@ -49,7 +49,7 @@ function BodyRow(props: BodyRowP cellComponent, childrenColumnName, } = props; - const { prefixCls } = React.useContext(TableContext); + const { prefixCls, direction } = React.useContext(TableContext); const { fixHeader, fixColumn, @@ -77,7 +77,7 @@ function BodyRow(props: BodyRowP // Move to Body to enhance performance const fixedInfoList = flattenColumns.map((column, colIndex) => - getCellFixedInfo(colIndex, colIndex, flattenColumns, stickyOffsets), + getCellFixedInfo(colIndex, colIndex, flattenColumns, stickyOffsets, direction), ); const rowSupportExpand = expandableType === 'row' && (!rowExpandable || rowExpandable(record)); diff --git a/src/Cell/index.tsx b/src/Cell/index.tsx index 4fb343ede..bef1d19ad 100644 --- a/src/Cell/index.tsx +++ b/src/Cell/index.tsx @@ -44,8 +44,10 @@ export interface CellProps { // Fixed fixLeft?: number | false; fixRight?: number | false; + firstFixLeft?: boolean; lastFixLeft?: boolean; firstFixRight?: boolean; + lastFixRight?: boolean; // Additional /** @private Used for `expandable` with nest tree */ @@ -67,8 +69,10 @@ function Cell( rowSpan, fixLeft, fixRight, + firstFixLeft, lastFixLeft, firstFixRight, + lastFixRight, appendNode, additionalProps = {}, ellipsis, @@ -134,6 +138,7 @@ function Cell( } if (isFixRight) { fixedStyle.position = 'sticky'; + fixedStyle.right = fixRight as number; } @@ -163,9 +168,11 @@ function Cell( className, { [`${cellPrefixCls}-fix-left`]: isFixLeft, + [`${cellPrefixCls}-fix-left-first`]: firstFixLeft, [`${cellPrefixCls}-fix-left-last`]: lastFixLeft, [`${cellPrefixCls}-fix-right`]: isFixRight, [`${cellPrefixCls}-fix-right-first`]: firstFixRight, + [`${cellPrefixCls}-fix-right-last`]: lastFixRight, [`${cellPrefixCls}-ellipsis`]: ellipsis, [`${cellPrefixCls}-with-append`]: appendNode, }, diff --git a/src/Header/FixedHeader.tsx b/src/Header/FixedHeader.tsx index c8fd2f557..31a91de98 100644 --- a/src/Header/FixedHeader.tsx +++ b/src/Header/FixedHeader.tsx @@ -7,6 +7,7 @@ import TableContext from '../context/TableContext'; export interface FixedHeaderProps extends HeaderProps { colWidths: number[]; columCount: number; + direction: 'ltr' | 'rtl'; } function FixedHeader({ @@ -15,6 +16,7 @@ function FixedHeader({ colWidths, columCount, stickyOffsets, + direction, ...props }: FixedHeaderProps) { const { prefixCls, scrollbarSize } = React.useContext(TableContext); @@ -40,11 +42,11 @@ function FixedHeader({ // Calculate the sticky offsets const headerStickyOffsets = React.useMemo(() => { - const { right } = stickyOffsets; - + const { right, left } = stickyOffsets; return { ...stickyOffsets, - right: [...right.map(width => width + scrollbarSize), 0], + left: direction === 'rtl' ? [...left.map(width => width + scrollbarSize), 0] : left, + right: direction === 'rtl' ? right : [...right.map(width => width + scrollbarSize), 0], }; }, [scrollbarSize, stickyOffsets]); diff --git a/src/Header/HeaderRow.tsx b/src/Header/HeaderRow.tsx index 15caf9d2a..74c3c39ab 100644 --- a/src/Header/HeaderRow.tsx +++ b/src/Header/HeaderRow.tsx @@ -30,7 +30,7 @@ function HeaderRow({ onHeaderRow, index, }: RowProps) { - const { prefixCls } = React.useContext(TableContext); + const { prefixCls, direction } = React.useContext(TableContext); let rowProps: React.HTMLAttributes; if (onHeaderRow) { @@ -48,6 +48,7 @@ function HeaderRow({ cell.colEnd, flattenColumns, stickyOffsets, + direction, ); let additionalProps: React.HTMLAttributes; diff --git a/src/Table.tsx b/src/Table.tsx index f579bfc89..4878473ea 100644 --- a/src/Table.tsx +++ b/src/Table.tsx @@ -106,6 +106,8 @@ export interface TableProps extends LegacyExpandableProps< onHeaderRow?: GetComponentProps[]>; emptyText?: React.ReactNode | (() => React.ReactNode); + direction?: 'ltr' | 'rtl'; + // =================================== Internal =================================== /** * @private Internal usage, may remove by refactor. Should always use `columns` instead. @@ -142,6 +144,7 @@ function Table(props: TableProps(props: TableProps colsWidths.get(columnKey)); - const stickyOffsets = useStickyOffsets(colWidths, flattenColumns.length); - + const stickyOffsets = useStickyOffsets(colWidths, flattenColumns.length, direction); const fixHeader = hasData && scroll && validateValue(scroll.y); const fixColumn = scroll && validateValue(scroll.x); @@ -505,7 +507,6 @@ function Table(props: TableProps { const colWidth = index === columns.length - 1 ? (width as number) - scrollbarSize : width; - if (typeof colWidth === 'number' && !Number.isNaN(colWidth)) { return colWidth; } @@ -553,7 +554,7 @@ function Table(props: TableProps - + )} @@ -587,6 +588,7 @@ function Table(props: TableProps(props: TableProps (null); diff --git a/src/hooks/useStickyOffsets.ts b/src/hooks/useStickyOffsets.ts index 8b94f431e..3497b8e7a 100644 --- a/src/hooks/useStickyOffsets.ts +++ b/src/hooks/useStickyOffsets.ts @@ -4,7 +4,7 @@ import { StickyOffsets } from '../interface'; /** * Get sticky column offset width */ -function useStickyOffsets(colWidths: number[], columCount: number) { +function useStickyOffsets(colWidths: number[], columCount: number, direction: 'ltr' | 'rtl') { const stickyOffsets: StickyOffsets = useMemo(() => { const leftOffsets: number[] = []; const rightOffsets: number[] = []; @@ -12,14 +12,25 @@ function useStickyOffsets(colWidths: number[], columCount: number) { let right = 0; for (let start = 0; start < columCount; start += 1) { - // Left offset - leftOffsets[start] = left; - left += colWidths[start] || 0; + if (direction === 'rtl') { + // Left offset + rightOffsets[start] = right; + right += colWidths[start] || 0; - // Right offset - const end = columCount - start - 1; - rightOffsets[end] = right; - right += colWidths[end] || 0; + // Right offset + const end = columCount - start - 1; + leftOffsets[end] = left; + left += colWidths[end] || 0; + } else { + // Left offset + leftOffsets[start] = left; + left += colWidths[start] || 0; + + // Right offset + const end = columCount - start - 1; + rightOffsets[end] = right; + right += colWidths[end] || 0; + } } return { diff --git a/src/utils/fixUtil.ts b/src/utils/fixUtil.ts index 1eedf7b51..6bd137d34 100644 --- a/src/utils/fixUtil.ts +++ b/src/utils/fixUtil.ts @@ -5,6 +5,10 @@ export interface FixedInfo { fixRight: number | false; lastFixLeft: boolean; firstFixRight: boolean; + + // For Rtl Direction + lastFixRight: boolean; + firstFixLeft: boolean; } export function getCellFixedInfo( @@ -12,6 +16,7 @@ export function getCellFixedInfo( colEnd: number, columns: { fixed?: FixedType }[], stickyOffsets: StickyOffsets, + direction: 'ltr' | 'rtl', ): FixedInfo { const startColumn = columns[colStart] || {}; const endColumn = columns[colEnd] || {}; @@ -27,12 +32,25 @@ export function getCellFixedInfo( let lastFixLeft: boolean = false; let firstFixRight: boolean = false; - if (fixLeft !== undefined) { - const nextColumn = columns[colEnd + 1]; + + let lastFixRight: boolean = false; + let firstFixLeft: boolean = false; + + const nextColumn = columns[colEnd + 1]; + const prevColumn = columns[colStart - 1]; + + if (direction === 'rtl') { + if (fixLeft !== undefined) { + const prevFixLeft = prevColumn && prevColumn.fixed === 'left'; + firstFixLeft = !prevFixLeft; + } else if (fixRight !== undefined) { + const nextFixRight = nextColumn && nextColumn.fixed === 'right'; + lastFixRight = !nextFixRight; + } + } else if (fixLeft !== undefined) { const nextFixLeft = nextColumn && nextColumn.fixed === 'left'; lastFixLeft = !nextFixLeft; } else if (fixRight !== undefined) { - const prevColumn = columns[colStart - 1]; const prevFixRight = prevColumn && prevColumn.fixed === 'right'; firstFixRight = !prevFixRight; } @@ -42,5 +60,7 @@ export function getCellFixedInfo( fixRight, lastFixLeft, firstFixRight, + lastFixRight, + firstFixLeft, }; } From 841213d07641c17c500941106e4d10ec037a5b97 Mon Sep 17 00:00:00 2001 From: Saeed Rahimi Date: Thu, 5 Mar 2020 19:06:16 +0330 Subject: [PATCH 2/6] auto change fixed left to right --- examples/fixedColumnsAndHeaderRtl.tsx | 49 ++++-------------------- src/Table.tsx | 1 + src/hooks/useColumns.tsx | 55 ++++++++++++++++++++++----- 3 files changed, 54 insertions(+), 51 deletions(-) diff --git a/examples/fixedColumnsAndHeaderRtl.tsx b/examples/fixedColumnsAndHeaderRtl.tsx index 04e504c3b..16ceb0e74 100644 --- a/examples/fixedColumnsAndHeaderRtl.tsx +++ b/examples/fixedColumnsAndHeaderRtl.tsx @@ -30,27 +30,12 @@ longTextData[0] = { a: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', }; -function getFixedRightValue(fixRight: boolean, isRtlCol: boolean): 'left' | 'right' { - if (fixRight) { - return isRtlCol ? 'left' : 'right'; - } - return null; -} - -function getFixedLeftValue(fixLeft: boolean, isRtlCol: boolean): 'right' | 'left' { - if (fixLeft) { - return isRtlCol ? 'right' : 'left'; - } - return null; -} - const useColumn = ( fixLeft: boolean, fixTitle: boolean, fixRight: boolean, ellipsis: boolean, percentage: boolean, - isRtlCol: boolean, ) => { const columns: ColumnsType = React.useMemo( () => [ @@ -59,19 +44,13 @@ const useColumn = ( dataIndex: 'a', key: 'a', width: percentage ? '10%' : 80, - fixed: getFixedLeftValue(fixLeft, isRtlCol), + fixed: fixLeft ? 'left' : null, ellipsis, }, - { - title: 'title2', - dataIndex: 'b', - key: 'b', - width: 80, - fixed: getFixedLeftValue(fixLeft, isRtlCol), - }, + { title: 'title2', dataIndex: 'b', key: 'b', width: 80, fixed: fixLeft ? 'left' : null }, { title: 'title3', - fixed: fixTitle ? getFixedLeftValue(fixLeft, isRtlCol) : null, + fixed: fixLeft && fixTitle ? 'left' : null, children: [ { title: 'title4', dataIndex: 'c', key: 'd', width: 100 }, { title: 'title5', dataIndex: 'c', key: 'e', width: 100 }, @@ -82,22 +61,10 @@ const useColumn = ( { title: 'title8', dataIndex: 'c', key: 'h' }, { title: 'title9', dataIndex: 'b', key: 'i' }, { title: 'title10', dataIndex: 'b', key: 'j' }, - { - title: 'title11', - dataIndex: 'b', - key: 'k', - width: 100, - fixed: getFixedRightValue(fixRight, isRtlCol), - }, - { - title: 'title12', - dataIndex: 'b', - key: 'l', - width: 80, - fixed: getFixedRightValue(fixRight, isRtlCol), - }, + { title: 'title11', dataIndex: 'b', key: 'k', width: 100, fixed: fixRight ? 'right' : null }, + { title: 'title12', dataIndex: 'b', key: 'l', width: 80, fixed: fixRight ? 'right' : null }, ], - [fixLeft, fixTitle, fixRight, ellipsis, percentage, isRtlCol], + [fixLeft, fixTitle, fixRight, ellipsis, percentage], ); return columns; @@ -105,7 +72,7 @@ const useColumn = ( const Demo = () => { const [autoWidth, autoWidthProps] = useCheckbox(false); - const [isRtl, isRtlProps] = useCheckbox(false); + const [isRtl, isRtlProps] = useCheckbox(true); const [longText, longTextProps] = useCheckbox(false); const [fixHeader, fixHeaderProps] = useCheckbox(true); const [fixLeft, fixLeftProps] = useCheckbox(true); @@ -114,7 +81,7 @@ const Demo = () => { const [ellipsis, ellipsisProps] = useCheckbox(false); const [percentage, percentageProps] = useCheckbox(false); const [empty, emptyProps] = useCheckbox(false); - const columns = useColumn(fixLeft, fixTitle3, fixRight, ellipsis, percentage, isRtl); + const columns = useColumn(fixLeft, fixTitle3, fixRight, ellipsis, percentage); let mergedData: RecordType[]; if (empty) { diff --git a/src/Table.tsx b/src/Table.tsx index 4878473ea..d87dc23be 100644 --- a/src/Table.tsx +++ b/src/Table.tsx @@ -321,6 +321,7 @@ function Table(props: TableProps( }); } -function flatColumns(columns: ColumnsType): ColumnType[] { +function flatColumns( + columns: ColumnsType, + direction: 'ltr' | 'rtl', +): ColumnType[] { return columns.reduce((list, column) => { const { fixed } = column; // Convert `fixed='true'` to `fixed='left'` instead - const parsedFixed = fixed === true ? 'left' : fixed; - + let parsedFixed = fixed === true ? 'left' : fixed; + if (direction === 'rtl') { + if (fixed === true || fixed === 'left') { + parsedFixed = 'right'; + } else if (fixed === 'right') { + parsedFixed = 'left'; + } + } if ('children' in column) { return [ ...list, - ...flatColumns(column.children).map(subColum => ({ + ...flatColumns(column.children, direction).map(subColum => ({ fixed: parsedFixed, ...subColum, })), @@ -82,6 +91,31 @@ function warningFixed(flattenColumns: { fixed?: FixedType }[]) { } } +function reverseFixedForRtlDirection( + columns: ColumnsType, + direction: 'ltr' | 'rtl', +): ColumnsType { + return columns.map(value => { + const { fixed, ...restProps } = value; + + // Convert `fixed='true'` to `fixed='left'` instead + let parsedFixed = fixed; + if (direction === 'rtl') { + if (fixed === true || fixed === 'left') { + parsedFixed = 'right'; + } else if (fixed === 'right') { + parsedFixed = 'left'; + } + } + const column = { + fixed: parsedFixed, + ...restProps, + }; + + return column; + }); +} + /** * Parse `columns` & `children` into `columns`. */ @@ -97,6 +131,7 @@ function useColumns( expandIcon, rowExpandable, expandIconColumnIndex, + direction, }: { prefixCls?: string; columns?: ColumnsType; @@ -108,6 +143,7 @@ function useColumns( expandIcon?: RenderExpandIcon; rowExpandable?: (record: RecordType) => boolean; expandIconColumnIndex?: number; + direction?: 'ltr' | 'rtl'; }, transformColumns: (columns: ColumnsType) => ColumnsType, ): [ColumnsType, ColumnType[]] { @@ -151,10 +187,11 @@ function useColumns( return cloneColumns; } return baseColumns; - }, [expandable, baseColumns, getRowKey, expandedKeys, expandIcon]); + }, [expandable, baseColumns, getRowKey, expandedKeys, expandIcon, direction]); const mergedColumns = React.useMemo(() => { let finalColumns = withExpandColumns; + finalColumns = reverseFixedForRtlDirection(finalColumns, direction); if (transformColumns) { finalColumns = transformColumns(finalColumns); } @@ -167,17 +204,15 @@ function useColumns( }, ]; } - return finalColumns; - }, [transformColumns, withExpandColumns]); - - const flattenColumns = React.useMemo(() => flatColumns(mergedColumns), [mergedColumns]); + }, [transformColumns, withExpandColumns, direction]); + let flattenColumns = React.useMemo(() => flatColumns(mergedColumns, direction), [mergedColumns]); + flattenColumns = reverseFixedForRtlDirection(flattenColumns, direction); // Only check out of production since it's waste for each render if (process.env.NODE_ENV !== 'production') { warningFixed(flattenColumns); } - return [mergedColumns, flattenColumns]; } From 4d4b215d36dca2153a6c9b71c6ea0b54b71124b0 Mon Sep 17 00:00:00 2001 From: Saeed Rahimi Date: Thu, 5 Mar 2020 19:27:40 +0330 Subject: [PATCH 3/6] remove redundant code --- src/hooks/useColumns.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hooks/useColumns.tsx b/src/hooks/useColumns.tsx index 7694427c9..57889e509 100644 --- a/src/hooks/useColumns.tsx +++ b/src/hooks/useColumns.tsx @@ -98,7 +98,7 @@ function reverseFixedForRtlDirection( return columns.map(value => { const { fixed, ...restProps } = value; - // Convert `fixed='true'` to `fixed='left'` instead + // Convert `fixed='left'` to `fixed='right'` instead let parsedFixed = fixed; if (direction === 'rtl') { if (fixed === true || fixed === 'left') { @@ -207,8 +207,10 @@ function useColumns( return finalColumns; }, [transformColumns, withExpandColumns, direction]); - let flattenColumns = React.useMemo(() => flatColumns(mergedColumns, direction), [mergedColumns]); - flattenColumns = reverseFixedForRtlDirection(flattenColumns, direction); + const flattenColumns = React.useMemo( + () => reverseFixedForRtlDirection(flatColumns(mergedColumns, direction), direction), + [mergedColumns], + ); // Only check out of production since it's waste for each render if (process.env.NODE_ENV !== 'production') { warningFixed(flattenColumns); From 543718cfabc12ca24a37924c3a11241e9d822605 Mon Sep 17 00:00:00 2001 From: Saeed Rahimi Date: Thu, 5 Mar 2020 19:49:02 +0330 Subject: [PATCH 4/6] add some tests --- tests/FixedColumn.spec.js | 30 + tests/Table.spec.js | 13 +- tests/__snapshots__/FixedColumn.spec.js.snap | 578 +++++++++++++++++++ tests/__snapshots__/Table.spec.js.snap | 57 +- 4 files changed, 676 insertions(+), 2 deletions(-) diff --git a/tests/FixedColumn.spec.js b/tests/FixedColumn.spec.js index db50e8576..d8655f0d9 100644 --- a/tests/FixedColumn.spec.js +++ b/tests/FixedColumn.spec.js @@ -156,4 +156,34 @@ describe('Table.FixedColumn', () => { expect(wrapper.find('tr th').find('.rc-table-cell-content')).toHaveLength(1); expect(wrapper.find('tr td').find('.rc-table-cell-content')).toHaveLength(data.length); }); + + it('fixed column renders correctly RTL', () => { + const wrapper = mount(); + expect(wrapper.render()).toMatchSnapshot(); + }); + it('has correct scroll classNames when table direction is RTL', () => { + const wrapper = mount(
); + + expect(wrapper.find('.rc-table').hasClass('rc-table-rtl')).toBeTruthy(); + + // Left should be right in RTL + expect( + wrapper + .find('.rc-table-row') + .first() + .find('.rc-table-cell') + .first() + .hasClass('rc-table-cell-fix-right'), + ).toBeTruthy(); + + // Right should be left in RTL + expect( + wrapper + .find('.rc-table-row') + .first() + .find('.rc-table-cell') + .last() + .hasClass('rc-table-cell-fix-left'), + ).toBeTruthy(); + }); }); diff --git a/tests/Table.spec.js b/tests/Table.spec.js index 96216c6d1..d91b09b3e 100644 --- a/tests/Table.spec.js +++ b/tests/Table.spec.js @@ -14,6 +14,17 @@ describe('Table.Basic', () => { describe('renders correctly', () => { it('basic', () => { + const wrapper = mount( + createTable({ + prefixCls: 'test-prefix', + className: 'test-class-name', + direction: 'rtl', + }), + ); + expect(wrapper.render()).toMatchSnapshot(); + }); + + it('RTL', () => { const wrapper = mount( createTable({ prefixCls: 'test-prefix', @@ -704,7 +715,7 @@ describe('Table.Basic', () => { - {'Invalidate Column'} + Invalidate Column
, ).render(), ).toMatchSnapshot(); diff --git a/tests/__snapshots__/FixedColumn.spec.js.snap b/tests/__snapshots__/FixedColumn.spec.js.snap index 7f3f23abc..5e4c53814 100644 --- a/tests/__snapshots__/FixedColumn.spec.js.snap +++ b/tests/__snapshots__/FixedColumn.spec.js.snap @@ -1,5 +1,583 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`Table.FixedColumn fixed column renders correctly RTL 1`] = ` +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ title1 + + title2 + + title3 + + title4 + + title5 + + title6 + + title7 + + title8 + + title9 + + title10 + + title11 + + title12 +
+ 123 + + xxxxxxxx + + + xxxxxxxx + + xxxxxxxx + + xxxxxxxx + + xxxxxxxx + + xxxxxxxx + + xxxxxxxx + + xxxxxxxx + + xxxxxxxx + + xxxxxxxx +
+ cdd + + edd12221 + + + edd12221 + + edd12221 + + edd12221 + + edd12221 + + edd12221 + + edd12221 + + edd12221 + + edd12221 + + edd12221 +
+ 133 + + + edd12221 + + + + + + + + + +
+ 133 + + + edd12221 + + + + + + + + + +
+ 133 + + + edd12221 + + + + + + + + + +
+ 133 + + + edd12221 + + + + + + + + + +
+ 133 + + + edd12221 + + + + + + + + + +
+ 133 + + + edd12221 + + + + + + + + + +
+ 133 + + + edd12221 + + + + + + + + + +
+
+
+
+`; + exports[`Table.FixedColumn renders correctly scrollX - with data 1`] = `
`; -exports[`Table.Basic renders correctly basic 1`] = ` +exports[`Table.Basic renders correctly RTL 1`] = `
@@ -431,6 +431,61 @@ exports[`Table.Basic renders correctly basic 1`] = `
`; +exports[`Table.Basic renders correctly basic 1`] = ` +
+
+
+ + + + + + + + + + + + + + + + + +
+ Name +
+ Lucy +
+ Jack +
+
+
+
+`; + exports[`Table.Basic renders correctly no columns 1`] = `
Date: Fri, 6 Mar 2020 10:46:29 +0330 Subject: [PATCH 5/6] some changes to useColumns.tsx --- src/hooks/useColumns.tsx | 49 ++++++++++---------------- tests/Table.spec.js | 2 +- tests/__snapshots__/Table.spec.js.snap | 4 +-- 3 files changed, 21 insertions(+), 34 deletions(-) diff --git a/src/hooks/useColumns.tsx b/src/hooks/useColumns.tsx index 57889e509..4c4f585af 100644 --- a/src/hooks/useColumns.tsx +++ b/src/hooks/useColumns.tsx @@ -32,26 +32,17 @@ export function convertChildrenToColumns( }); } -function flatColumns( - columns: ColumnsType, - direction: 'ltr' | 'rtl', -): ColumnType[] { +function flatColumns(columns: ColumnsType): ColumnType[] { return columns.reduce((list, column) => { const { fixed } = column; // Convert `fixed='true'` to `fixed='left'` instead - let parsedFixed = fixed === true ? 'left' : fixed; - if (direction === 'rtl') { - if (fixed === true || fixed === 'left') { - parsedFixed = 'right'; - } else if (fixed === 'right') { - parsedFixed = 'left'; - } - } + const parsedFixed = fixed === true ? 'left' : fixed; + if ('children' in column) { return [ ...list, - ...flatColumns(column.children, direction).map(subColum => ({ + ...flatColumns(column.children).map(subColum => ({ fixed: parsedFixed, ...subColum, })), @@ -91,28 +82,25 @@ function warningFixed(flattenColumns: { fixed?: FixedType }[]) { } } -function reverseFixedForRtlDirection( - columns: ColumnsType, - direction: 'ltr' | 'rtl', -): ColumnsType { +function revertForRtl(columns: ColumnsType): ColumnsType { return columns.map(value => { const { fixed, ...restProps } = value; // Convert `fixed='left'` to `fixed='right'` instead let parsedFixed = fixed; - if (direction === 'rtl') { - if (fixed === true || fixed === 'left') { - parsedFixed = 'right'; - } else if (fixed === 'right') { - parsedFixed = 'left'; - } + if (fixed === 'left') { + parsedFixed = 'right'; + } else if (fixed === 'right') { + parsedFixed = 'left'; } - const column = { + if ('children' in value) { + value.children = revertForRtl(value.children); + } + + return { fixed: parsedFixed, ...restProps, }; - - return column; }); } @@ -191,7 +179,9 @@ function useColumns( const mergedColumns = React.useMemo(() => { let finalColumns = withExpandColumns; - finalColumns = reverseFixedForRtlDirection(finalColumns, direction); + if (direction === 'rtl') { + finalColumns = revertForRtl(finalColumns); + } if (transformColumns) { finalColumns = transformColumns(finalColumns); } @@ -207,10 +197,7 @@ function useColumns( return finalColumns; }, [transformColumns, withExpandColumns, direction]); - const flattenColumns = React.useMemo( - () => reverseFixedForRtlDirection(flatColumns(mergedColumns, direction), direction), - [mergedColumns], - ); + const flattenColumns = React.useMemo(() => flatColumns(mergedColumns), [mergedColumns]); // Only check out of production since it's waste for each render if (process.env.NODE_ENV !== 'production') { warningFixed(flattenColumns); diff --git a/tests/Table.spec.js b/tests/Table.spec.js index d91b09b3e..cd6ea9225 100644 --- a/tests/Table.spec.js +++ b/tests/Table.spec.js @@ -18,7 +18,6 @@ describe('Table.Basic', () => { createTable({ prefixCls: 'test-prefix', className: 'test-class-name', - direction: 'rtl', }), ); expect(wrapper.render()).toMatchSnapshot(); @@ -29,6 +28,7 @@ describe('Table.Basic', () => { createTable({ prefixCls: 'test-prefix', className: 'test-class-name', + direction: 'rtl', }), ); expect(wrapper.render()).toMatchSnapshot(); diff --git a/tests/__snapshots__/Table.spec.js.snap b/tests/__snapshots__/Table.spec.js.snap index 012edb35c..1d3097342 100644 --- a/tests/__snapshots__/Table.spec.js.snap +++ b/tests/__snapshots__/Table.spec.js.snap @@ -378,7 +378,7 @@ exports[`Table.Basic renders colSpan correctly 1`] = ` exports[`Table.Basic renders correctly RTL 1`] = `
Date: Fri, 6 Mar 2020 15:36:56 +0330 Subject: [PATCH 6/6] fix test coverage issue --- src/hooks/useColumns.tsx | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/hooks/useColumns.tsx b/src/hooks/useColumns.tsx index 4c4f585af..3d527c45b 100644 --- a/src/hooks/useColumns.tsx +++ b/src/hooks/useColumns.tsx @@ -83,8 +83,8 @@ function warningFixed(flattenColumns: { fixed?: FixedType }[]) { } function revertForRtl(columns: ColumnsType): ColumnsType { - return columns.map(value => { - const { fixed, ...restProps } = value; + return columns.map(column => { + const { fixed, ...restProps } = column; // Convert `fixed='left'` to `fixed='right'` instead let parsedFixed = fixed; @@ -93,10 +93,6 @@ function revertForRtl(columns: ColumnsType): ColumnsType } else if (fixed === 'right') { parsedFixed = 'left'; } - if ('children' in value) { - value.children = revertForRtl(value.children); - } - return { fixed: parsedFixed, ...restProps, @@ -179,9 +175,6 @@ function useColumns( const mergedColumns = React.useMemo(() => { let finalColumns = withExpandColumns; - if (direction === 'rtl') { - finalColumns = revertForRtl(finalColumns); - } if (transformColumns) { finalColumns = transformColumns(finalColumns); } @@ -197,7 +190,12 @@ function useColumns( return finalColumns; }, [transformColumns, withExpandColumns, direction]); - const flattenColumns = React.useMemo(() => flatColumns(mergedColumns), [mergedColumns]); + const flattenColumns = React.useMemo(() => { + if (direction === 'rtl') { + return revertForRtl(flatColumns(mergedColumns)); + } + return flatColumns(mergedColumns); + }, [mergedColumns, direction]); // Only check out of production since it's waste for each render if (process.env.NODE_ENV !== 'production') { warningFixed(flattenColumns);