chore: Use WDS Tokens in Table Body (#32421)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Enhanced typography styling with dynamic font size adjustments. - Introduced feature flag checks for new functionalities. - Implemented `VirtualTableBody` for efficient data rendering. - Added `onClickRow` functionality in table rows for improved interactivity. - Improved table accessibility with explicit cell roles. - Added pagination controls refinement in table headers. - **Refactor** - Simplified table header and body component structures for better maintainability. - Streamlined feature flag usage for cleaner logic. - Refined `WDSTableWidget` component by optimizing width calculations and event handling. - **Style** - Introduced a new CSS module for comprehensive table styling. - Removed outdated styling configurations to align with updated design system. - **Bug Fixes** - Fixed accessibility issues by adding proper roles to table cells. - **Chores** - Removed unused functions and properties related to theme and styling adjustments. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Pawan Kumar <pawankumar@Pawans-MacBook-Pro-2.local>
This commit is contained in:
parent
159399d8f4
commit
46498aa93a
|
|
@ -81,6 +81,11 @@
|
|||
padding: 0;
|
||||
}
|
||||
|
||||
/* this is required so that separator ( <Item isSeprator /> ) if passed with a text as children, the text is hidden */
|
||||
.menuList li[data-separator] > * {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* making sure the first and last child are not displayed when they have the data-separator attribute */
|
||||
.menuList li:is(:first-child, :last-child):is([data-separator]) {
|
||||
display: none;
|
||||
|
|
|
|||
|
|
@ -85,7 +85,6 @@ const StaticTable = (props: StaticTableProps) => {
|
|||
selectTableRow={props.selectTableRow}
|
||||
selectedRowIndex={props.selectedRowIndex}
|
||||
selectedRowIndices={props.selectedRowIndices}
|
||||
tableSizes={props.tableSizes}
|
||||
useVirtual={props.useVirtual}
|
||||
width={props.width - TABLE_SCROLLBAR_WIDTH / 2}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -19,17 +19,11 @@ import type {
|
|||
AddNewRowActions,
|
||||
StickyType,
|
||||
} from "./Constants";
|
||||
import {
|
||||
TABLE_SIZES,
|
||||
CompactModeTypes,
|
||||
TABLE_SCROLLBAR_HEIGHT,
|
||||
} from "./Constants";
|
||||
import { TABLE_SIZES, CompactModeTypes } from "./Constants";
|
||||
import { Colors } from "constants/Colors";
|
||||
import type { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import type { EditableCell, TableVariant } from "../constants";
|
||||
import "simplebar-react/dist/simplebar.min.css";
|
||||
import { createGlobalStyle } from "styled-components";
|
||||
import { Classes as PopOver2Classes } from "@blueprintjs/popover2";
|
||||
import StaticTable from "./StaticTable";
|
||||
import VirtualTable from "./VirtualTable";
|
||||
import { ConnectDataOverlay } from "widgets/ConnectDataOverlay";
|
||||
|
|
@ -38,25 +32,7 @@ import {
|
|||
createMessage,
|
||||
CONNECT_BUTTON_TEXT,
|
||||
} from "@appsmith/constants/messages";
|
||||
|
||||
const SCROLL_BAR_OFFSET = 2;
|
||||
const HEADER_MENU_PORTAL_CLASS = ".header-menu-portal";
|
||||
|
||||
const PopoverStyles = createGlobalStyle<{
|
||||
widgetId: string;
|
||||
borderRadius: string;
|
||||
}>`
|
||||
${HEADER_MENU_PORTAL_CLASS}-${({ widgetId }) => widgetId} {
|
||||
font-family: var(--wds-font-family) !important;
|
||||
|
||||
& .${PopOver2Classes.POPOVER2},
|
||||
.${PopOver2Classes.POPOVER2_CONTENT},
|
||||
.bp3-menu {
|
||||
border-radius: ${({ borderRadius }) =>
|
||||
borderRadius >= `1.5rem` ? `0.375rem` : borderRadius} !important;
|
||||
}
|
||||
}
|
||||
`;
|
||||
import styles from "./styles.module.css";
|
||||
|
||||
export interface TableProps {
|
||||
width: number;
|
||||
|
|
@ -286,21 +262,18 @@ export function Table(props: TableProps) {
|
|||
props.isVisiblePagination ||
|
||||
props.allowAddNewRow;
|
||||
|
||||
const scrollContainerStyles = useMemo(() => {
|
||||
return {
|
||||
height: isHeaderVisible
|
||||
? props.height -
|
||||
tableSizes.TABLE_HEADER_HEIGHT -
|
||||
TABLE_SCROLLBAR_HEIGHT -
|
||||
SCROLL_BAR_OFFSET
|
||||
: props.height - TABLE_SCROLLBAR_HEIGHT - SCROLL_BAR_OFFSET,
|
||||
};
|
||||
}, [isHeaderVisible, props.height, tableSizes.TABLE_HEADER_HEIGHT]);
|
||||
|
||||
const shouldUseVirtual =
|
||||
props.serverSidePaginationEnabled &&
|
||||
!props.columns.some((column) => column.columnProperties.allowCellWrapping);
|
||||
|
||||
const variant = (() => {
|
||||
if (props.variant === "DEFAULT") return "default";
|
||||
if (props.variant === "VARIANT2") return "no-borders";
|
||||
if (props.variant === "VARIANT3") return "horizontal-borders";
|
||||
|
||||
return "default";
|
||||
})();
|
||||
|
||||
return (
|
||||
<>
|
||||
{showConnectDataOverlay && (
|
||||
|
|
@ -317,21 +290,20 @@ export function Table(props: TableProps) {
|
|||
borderRadius={props.borderRadius}
|
||||
borderWidth={props.borderWidth}
|
||||
boxShadow={props.boxShadow}
|
||||
className={styles.table}
|
||||
data-status={props.isAddRowInProgress ? "add-row-in-progress" : ""}
|
||||
data-type={shouldUseVirtual ? "virtualized" : "static"}
|
||||
data-variant={variant}
|
||||
height={props.height}
|
||||
id={`table${props.widgetId}`}
|
||||
isAddRowInProgress={props.isAddRowInProgress}
|
||||
isHeaderVisible={isHeaderVisible}
|
||||
isResizingColumn={isResizingColumn.current}
|
||||
multiRowSelection={props.multiRowSelection}
|
||||
tableSizes={tableSizes}
|
||||
triggerRowSelection={props.triggerRowSelection}
|
||||
variant={props.variant}
|
||||
width={props.width}
|
||||
>
|
||||
<PopoverStyles
|
||||
borderRadius={props.borderRadius}
|
||||
widgetId={props.widgetId}
|
||||
/>
|
||||
{isHeaderVisible && (
|
||||
<TableHeader
|
||||
allowAddNewRow={props.allowAddNewRow}
|
||||
|
|
@ -375,6 +347,7 @@ export function Table(props: TableProps) {
|
|||
? " virtual"
|
||||
: ""
|
||||
}`}
|
||||
data-table-wrapper=""
|
||||
>
|
||||
<div {...getTableProps()} className="table column-freeze">
|
||||
{!shouldUseVirtual && (
|
||||
|
|
@ -435,7 +408,6 @@ export function Table(props: TableProps) {
|
|||
prepareRow={prepareRow}
|
||||
primaryColumnId={props.primaryColumnId}
|
||||
rowSelectionState={rowSelectionState}
|
||||
scrollContainerStyles={scrollContainerStyles}
|
||||
selectTableRow={props.selectTableRow}
|
||||
selectedRowIndex={props.selectedRowIndex}
|
||||
selectedRowIndices={props.selectedRowIndices}
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
import React from "react";
|
||||
import { Tooltip } from "@blueprintjs/core";
|
||||
import { IconWrapper } from "constants/IconConstants";
|
||||
import { Colors } from "constants/Colors";
|
||||
import { TableIconWrapper } from "./TableStyledWrappers";
|
||||
|
||||
interface TableActionIconProps {
|
||||
tooltip: string;
|
||||
selected: boolean;
|
||||
selectMenu: (selected: boolean) => void;
|
||||
className: string;
|
||||
children: React.ReactNode;
|
||||
icon?: React.ReactNode;
|
||||
}
|
||||
|
||||
function TableActionIcon(props: TableActionIconProps) {
|
||||
return (
|
||||
<Tooltip
|
||||
autoFocus={false}
|
||||
content={props.tooltip}
|
||||
hoverOpenDelay={1000}
|
||||
modifiers={{
|
||||
preventOverflow: { enabled: false },
|
||||
flip: { enabled: false },
|
||||
}}
|
||||
position="top"
|
||||
>
|
||||
<TableIconWrapper
|
||||
className={props.className}
|
||||
onClick={(e) => {
|
||||
props.selectMenu(!props.selected);
|
||||
e.stopPropagation();
|
||||
}}
|
||||
selected={props.selected}
|
||||
>
|
||||
<IconWrapper
|
||||
color={props.selected ? Colors.CODE_GRAY : Colors.GRAY}
|
||||
height={20}
|
||||
width={20}
|
||||
>
|
||||
{props.children}
|
||||
</IconWrapper>
|
||||
</TableIconWrapper>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
export default TableActionIcon;
|
||||
|
|
@ -44,28 +44,29 @@ export function Row(props: RowType) {
|
|||
(primaryColumnId && (props.row.original[primaryColumnId] as Key)) ||
|
||||
props.index;
|
||||
|
||||
if (!isAddRowInProgress) {
|
||||
rowProps["role"] = "button";
|
||||
}
|
||||
const onClickRow = (e: React.MouseEvent) => {
|
||||
props.row.toggleRowSelected();
|
||||
selectTableRow?.(props.row);
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
{...rowProps}
|
||||
aria-checked={isRowSelected}
|
||||
className={`tr ${isRowSelected ? "selected-row" : ""} ${
|
||||
props.className || ""
|
||||
} ${isAddRowInProgress && props.index === 0 ? "new-row" : ""}`}
|
||||
}`}
|
||||
data-is-new={isAddRowInProgress && props.index === 0 ? "" : undefined}
|
||||
data-rowindex={props.index}
|
||||
key={key}
|
||||
onClick={(e) => {
|
||||
props.row.toggleRowSelected();
|
||||
selectTableRow?.(props.row);
|
||||
e.stopPropagation();
|
||||
}}
|
||||
onClick={onClickRow}
|
||||
>
|
||||
{multiRowSelection &&
|
||||
renderBodyCheckBoxCell(isRowSelected, accentColor, borderRadius)}
|
||||
{props.row.cells.map((cell, cellIndex) => {
|
||||
const cellProperties = cell.getCellProps();
|
||||
|
||||
cellProperties["style"] = {
|
||||
...cellProperties.style,
|
||||
left:
|
||||
|
|
@ -76,6 +77,7 @@ export function Row(props: RowType) {
|
|||
return (
|
||||
<div
|
||||
{...cellProperties}
|
||||
aria-hidden={columns[cellIndex].isHidden ? "true" : undefined}
|
||||
className={
|
||||
columns[cellIndex].isHidden
|
||||
? "td hidden-cell"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
import React from "react";
|
||||
import { EmptyRows, Row } from "./Row";
|
||||
import type { StaticTableProps } from "./types";
|
||||
|
||||
export const StaticTableBody = (props: StaticTableProps) => {
|
||||
return (
|
||||
<div {...props.getTableBodyProps()} className="tbody body">
|
||||
{props.rows.map((row, index) => {
|
||||
return <Row index={index} key={index} row={row} />;
|
||||
})}
|
||||
{props.pageSize > props.rows.length && (
|
||||
<EmptyRows rowCount={props.pageSize - props.rows.length} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
import React, { useCallback } from "react";
|
||||
import { useLayoutEffect, useRef } from "react";
|
||||
import type { VirtualTableBodyProps } from "./types";
|
||||
|
||||
import { FixedSizeList, areEqual } from "react-window";
|
||||
import type { ListChildComponentProps } from "react-window";
|
||||
import { Row, EmptyRow } from "./Row";
|
||||
import { useResizeObserver } from "@react-aria/utils";
|
||||
|
||||
export const VirtualTableBody = (props: VirtualTableBodyProps) => {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const [horizontalScrollbarHeight, setHorizontalScrollbarHeight] =
|
||||
React.useState(0);
|
||||
const [itemHeight, setItemHeight] = React.useState("0px");
|
||||
const [headerHeight, setHeaderHeight] = React.useState("0px");
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (ref.current) {
|
||||
const horizontalScrollbar = ref.current;
|
||||
if (horizontalScrollbar) {
|
||||
setHorizontalScrollbarHeight(
|
||||
horizontalScrollbar.offsetHeight - horizontalScrollbar.clientHeight,
|
||||
);
|
||||
}
|
||||
}
|
||||
}, [ref.current]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (ref.current) {
|
||||
const table = ref.current.closest("[role='table']");
|
||||
|
||||
if (table && table instanceof HTMLElement) {
|
||||
const style = window.getComputedStyle(table);
|
||||
|
||||
const thHeight = style.getPropertyValue("background-position-x");
|
||||
const trHeight = style.getPropertyValue("background-position-y");
|
||||
|
||||
setHeaderHeight(thHeight);
|
||||
setItemHeight(trHeight);
|
||||
}
|
||||
}
|
||||
}, [props.pageSize, ref.current]);
|
||||
|
||||
const onSizeChange = useCallback(() => {
|
||||
if (ref.current) {
|
||||
const table = ref.current.closest("[role='table']");
|
||||
|
||||
if (table && table instanceof HTMLElement) {
|
||||
const style = window.getComputedStyle(table);
|
||||
|
||||
const thHeight = style.getPropertyValue("background-position-x");
|
||||
const trHeight = style.getPropertyValue("background-position-y");
|
||||
|
||||
setHeaderHeight(thHeight);
|
||||
setItemHeight(trHeight);
|
||||
}
|
||||
}
|
||||
}, [props.pageSize, ref.current]);
|
||||
|
||||
useResizeObserver({
|
||||
ref: ref,
|
||||
onResize: onSizeChange,
|
||||
});
|
||||
|
||||
return (
|
||||
<FixedSizeList
|
||||
data-virtual-list=""
|
||||
height={
|
||||
props.pageSize * parseFloat(itemHeight) +
|
||||
parseFloat(headerHeight) +
|
||||
horizontalScrollbarHeight
|
||||
}
|
||||
innerElementType={props.innerElementType}
|
||||
itemCount={Math.max(props.rows.length, props.pageSize)}
|
||||
itemData={props.rows}
|
||||
itemSize={parseFloat(itemHeight)}
|
||||
outerRef={ref}
|
||||
style={{
|
||||
overflow: "auto",
|
||||
scrollbarColor: "initial",
|
||||
}}
|
||||
width="100cqw"
|
||||
>
|
||||
{rowRenderer}
|
||||
</FixedSizeList>
|
||||
);
|
||||
};
|
||||
|
||||
const rowRenderer = React.memo((rowProps: ListChildComponentProps) => {
|
||||
const { data, index, style } = rowProps;
|
||||
|
||||
if (index < data.length) {
|
||||
const row = data[index];
|
||||
|
||||
return (
|
||||
<Row
|
||||
className="t--virtual-row"
|
||||
index={index}
|
||||
key={index}
|
||||
row={row}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return <EmptyRow style={style} />;
|
||||
}
|
||||
}, areEqual);
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
import React, { useLayoutEffect } from "react";
|
||||
import React from "react";
|
||||
import type {
|
||||
Row as ReactTableRowType,
|
||||
TableBodyPropGetter,
|
||||
TableBodyProps,
|
||||
} from "react-table";
|
||||
import type { ListChildComponentProps, ReactElementType } from "react-window";
|
||||
import { FixedSizeList, areEqual } from "react-window";
|
||||
import { EmptyRows, EmptyRow, Row } from "./Row";
|
||||
import type { ReactTableColumnProps, TableSizes } from "../Constants";
|
||||
import type { ReactTableColumnProps } from "../Constants";
|
||||
import type { HeaderComponentProps } from "../Table";
|
||||
import { StaticTableBody } from "./StaticTableBody";
|
||||
import { VirtualTableBody } from "./VirtualTableBody";
|
||||
import type { VirtualTableBodyProps } from "./types";
|
||||
|
||||
export type BodyContextType = {
|
||||
accentColor: string;
|
||||
|
|
@ -46,97 +46,8 @@ export const BodyContext = React.createContext<BodyContextType>({
|
|||
totalColumnsWidth: 0,
|
||||
});
|
||||
|
||||
const rowRenderer = React.memo((rowProps: ListChildComponentProps) => {
|
||||
const { data, index, style } = rowProps;
|
||||
|
||||
if (index < data.length) {
|
||||
const row = data[index];
|
||||
|
||||
return (
|
||||
<Row
|
||||
className="t--virtual-row"
|
||||
index={index}
|
||||
key={index}
|
||||
row={row}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return <EmptyRow style={style} />;
|
||||
}
|
||||
}, areEqual);
|
||||
|
||||
interface BodyPropsType {
|
||||
getTableBodyProps(
|
||||
propGetter?: TableBodyPropGetter<Record<string, unknown>> | undefined,
|
||||
): TableBodyProps;
|
||||
pageSize: number;
|
||||
rows: ReactTableRowType<Record<string, unknown>>[];
|
||||
height: number;
|
||||
width?: number;
|
||||
tableSizes: TableSizes;
|
||||
innerElementType?: ReactElementType;
|
||||
}
|
||||
|
||||
const TableVirtualBodyComponent = (props: BodyPropsType) => {
|
||||
const ref = React.useRef<HTMLDivElement>(null);
|
||||
const [horizontalScrollbarHeight, setHorizontalScrollbarHeight] =
|
||||
React.useState(0);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (ref.current) {
|
||||
const horizontalScrollbar = ref.current;
|
||||
if (horizontalScrollbar) {
|
||||
setHorizontalScrollbarHeight(
|
||||
horizontalScrollbar.offsetHeight - horizontalScrollbar.clientHeight,
|
||||
);
|
||||
}
|
||||
}
|
||||
}, [ref.current]);
|
||||
|
||||
return (
|
||||
<FixedSizeList
|
||||
data-virtual-list=""
|
||||
height={
|
||||
props.height +
|
||||
props.tableSizes.COLUMN_HEADER_HEIGHT +
|
||||
horizontalScrollbarHeight
|
||||
}
|
||||
innerElementType={props.innerElementType}
|
||||
itemCount={Math.max(props.rows.length, props.pageSize)}
|
||||
itemData={props.rows}
|
||||
itemSize={props.tableSizes.ROW_HEIGHT}
|
||||
outerRef={ref}
|
||||
style={{
|
||||
overflow: "auto",
|
||||
scrollbarColor: "initial",
|
||||
}}
|
||||
width="100cqw"
|
||||
>
|
||||
{rowRenderer}
|
||||
</FixedSizeList>
|
||||
);
|
||||
};
|
||||
|
||||
const TableBodyComponent = (props: BodyPropsType) => {
|
||||
return (
|
||||
<div
|
||||
{...props.getTableBodyProps()}
|
||||
className="tbody body"
|
||||
style={{ height: props.height }}
|
||||
>
|
||||
{props.rows.map((row, index) => {
|
||||
return <Row index={index} key={index} row={row} />;
|
||||
})}
|
||||
{props.pageSize > props.rows.length && (
|
||||
<EmptyRows rowCount={props.pageSize - props.rows.length} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const TableBody = (
|
||||
props: BodyPropsType & BodyContextType & { useVirtual: boolean },
|
||||
props: VirtualTableBodyProps & BodyContextType & { useVirtual: boolean },
|
||||
) => {
|
||||
const {
|
||||
accentColor,
|
||||
|
|
@ -203,9 +114,9 @@ export const TableBody = (
|
|||
}}
|
||||
>
|
||||
{useVirtual ? (
|
||||
<TableVirtualBodyComponent rows={rows} width={width} {...restOfProps} />
|
||||
<VirtualTableBody rows={rows} width={width} {...restOfProps} />
|
||||
) : (
|
||||
<TableBodyComponent rows={rows} {...restOfProps} />
|
||||
<StaticTableBody rows={rows} {...restOfProps} />
|
||||
)}
|
||||
</BodyContext.Provider>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
import type {
|
||||
TableBodyProps,
|
||||
TableBodyPropGetter,
|
||||
Row as ReactTableRowType,
|
||||
} from "react-table";
|
||||
import type { ReactElementType } from "react-window";
|
||||
|
||||
export interface StaticTableProps {
|
||||
getTableBodyProps(
|
||||
propGetter?: TableBodyPropGetter<Record<string, unknown>> | undefined,
|
||||
): TableBodyProps;
|
||||
pageSize: number;
|
||||
rows: ReactTableRowType<Record<string, unknown>>[];
|
||||
height: number;
|
||||
width?: number;
|
||||
}
|
||||
|
||||
export interface VirtualTableBodyProps extends StaticTableProps {
|
||||
innerElementType?: ReactElementType;
|
||||
}
|
||||
|
|
@ -51,11 +51,11 @@ export const Pagination = (props: PaginationProps) => {
|
|||
props.isVisiblePagination &&
|
||||
props.serverSidePaginationEnabled && (
|
||||
<div data-table-header-pagination="">
|
||||
{props.totalRecordsCount && (
|
||||
{props.totalRecordsCount ? (
|
||||
<Text lineClamp={1} variant="footnote">
|
||||
{props.totalRecordsCount} Records
|
||||
</Text>
|
||||
)}
|
||||
) : null}
|
||||
<IconButton
|
||||
icon="chevron-left"
|
||||
isDisabled={props.pageNo === 0}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import { StickyType } from "../Constants";
|
|||
import type { Row as ReactTableRowType } from "react-table";
|
||||
import { renderHeaderCheckBoxCell } from "../cellComponents/SelectionCheckboxCell";
|
||||
import { renderEmptyRows } from "../cellComponents/EmptyCell";
|
||||
import styled from "styled-components";
|
||||
|
||||
export interface TableColumnHeaderProps {
|
||||
enableDrag: () => void;
|
||||
|
|
@ -34,12 +33,6 @@ export interface TableColumnHeaderProps {
|
|||
widgetId: string;
|
||||
}
|
||||
|
||||
const StyledHeaderGroup = styled.div<{
|
||||
headerWidth: number;
|
||||
}>`
|
||||
display: flex;
|
||||
width: ${(props) => props.headerWidth}px !important;
|
||||
`;
|
||||
const TableColumnHeader = (props: TableColumnHeaderProps) => {
|
||||
const currentDraggedColumn = React.useRef<string>("");
|
||||
const columnOrder = props.columns.map((col) => col.alias);
|
||||
|
|
@ -59,22 +52,17 @@ const TableColumnHeader = (props: TableColumnHeaderProps) => {
|
|||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="thead"
|
||||
onMouseLeave={props.enableDrag}
|
||||
onMouseOver={props.disableDrag}
|
||||
>
|
||||
<thead onMouseLeave={props.enableDrag} onMouseOver={props.disableDrag}>
|
||||
{props.headerGroups.map((headerGroup: any, index: number) => {
|
||||
const headerRowProps = {
|
||||
...headerGroup.getHeaderGroupProps(),
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledHeaderGroup
|
||||
<tr
|
||||
{...headerRowProps}
|
||||
className="tr header"
|
||||
headerWidth={props.headerWidth}
|
||||
key={index}
|
||||
style={{ width: props.headerWidth }}
|
||||
>
|
||||
{props.multiRowSelection &&
|
||||
renderHeaderCheckBoxCell(
|
||||
|
|
@ -123,7 +111,7 @@ const TableColumnHeader = (props: TableColumnHeaderProps) => {
|
|||
/>
|
||||
);
|
||||
})}
|
||||
</StyledHeaderGroup>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
|
||||
|
|
@ -139,7 +127,7 @@ const TableColumnHeader = (props: TableColumnHeaderProps) => {
|
|||
{},
|
||||
props.prepareRow,
|
||||
)}
|
||||
</div>
|
||||
</thead>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import { lightenColor, darkenColor } from "widgets/WidgetUtils";
|
|||
import { FontStyleTypes } from "constants/WidgetConstants";
|
||||
import { Classes } from "@blueprintjs/core";
|
||||
import type { TableVariant } from "../constants";
|
||||
import { TableVariantTypes } from "../constants";
|
||||
import { Layers } from "constants/Layers";
|
||||
|
||||
const BORDER_RADIUS = "border-radius: 4px;";
|
||||
|
|
@ -44,271 +43,8 @@ export const TableWrapper = styled.div<{
|
|||
isResizingColumn?: boolean;
|
||||
variant?: TableVariant;
|
||||
isAddRowInProgress: boolean;
|
||||
multiRowSelection?: boolean;
|
||||
}>`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--color-bg-secondary);
|
||||
border-style: solid;
|
||||
border-width: ${({ borderWidth }) => `${borderWidth}px`};
|
||||
border-color: ${({ borderColor }) => borderColor};
|
||||
border-radius: var(--border-radius-elevation-3);
|
||||
box-shadow: ${({ boxShadow }) => `${boxShadow}`} !important;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
|
||||
/* wriiten exclusively for safari */
|
||||
position: sticky;
|
||||
}
|
||||
.tableWrap {
|
||||
height: 100%;
|
||||
display: block;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
overflow: auto hidden;
|
||||
scrollbar-color: initial;
|
||||
container-type: inline-size;
|
||||
|
||||
&.virtual {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
.table {
|
||||
border-spacing: 0;
|
||||
color: ${Colors.THUNDER};
|
||||
position: relative;
|
||||
display: table;
|
||||
width: 100%;
|
||||
tab .tbody {
|
||||
height: fit-content;
|
||||
width: fit-content;
|
||||
}
|
||||
.tr {
|
||||
cursor: ${(props) => props.triggerRowSelection && "pointer"};
|
||||
background: ${Colors.WHITE};
|
||||
&.selected-row {
|
||||
background: ${({ accentColor }) =>
|
||||
`${lightenColor(accentColor)}`} !important;
|
||||
|
||||
&:hover {
|
||||
background: ${({ accentColor }) =>
|
||||
`${lightenColor(accentColor, "0.9")}`} !important;
|
||||
}
|
||||
}
|
||||
|
||||
${(props) => {
|
||||
if (!props.isAddRowInProgress) {
|
||||
return `&:hover {
|
||||
background: var(--wds-color-bg-hover) !important;
|
||||
}`;
|
||||
}
|
||||
}}
|
||||
&.new-row {
|
||||
background: ${({ accentColor }) =>
|
||||
`${lightenColor(accentColor)}`} !important;
|
||||
}
|
||||
}
|
||||
.th,
|
||||
.td {
|
||||
margin: 0;
|
||||
border-bottom: ${(props) =>
|
||||
props.variant === TableVariantTypes.DEFAULT ||
|
||||
props.variant === undefined ||
|
||||
props.variant === TableVariantTypes.VARIANT3
|
||||
? "1px solid var(--wds-color-border-onaccent)"
|
||||
: "none"};
|
||||
border-right: ${(props) =>
|
||||
props.variant === TableVariantTypes.DEFAULT ||
|
||||
props.variant === undefined ||
|
||||
props.isResizingColumn
|
||||
? "1px solid var(--wds-color-border-onaccent)"
|
||||
: "none"};
|
||||
position: relative;
|
||||
font-size: ${(props) => props.tableSizes.ROW_FONT_SIZE}px;
|
||||
line-height: ${(props) => props.tableSizes.ROW_FONT_SIZE}px;
|
||||
:last-child {
|
||||
border-right: 0;
|
||||
.resizer {
|
||||
right: 5px;
|
||||
}
|
||||
}
|
||||
.resizer {
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
transform: translateX(50%);
|
||||
z-index: 1;
|
||||
${"" /* prevents from scrolling while dragging on touch devices */}
|
||||
touch-action:none;
|
||||
&.isResizing {
|
||||
cursor: isResizing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.th {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.th {
|
||||
padding: 0 10px 0 0;
|
||||
height: ${(props) =>
|
||||
props.isHeaderVisible ? props.tableSizes.COLUMN_HEADER_HEIGHT : 40}px;
|
||||
line-height: ${(props) =>
|
||||
props.isHeaderVisible ? props.tableSizes.COLUMN_HEADER_HEIGHT : 40}px;
|
||||
background: var(--wds-color-bg);
|
||||
font-weight: bold;
|
||||
}
|
||||
.td {
|
||||
min-height: ${(props) => props.tableSizes.ROW_HEIGHT}px;
|
||||
padding: 0;
|
||||
}
|
||||
.thead {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
|
||||
.column-freeze {
|
||||
.body {
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
[role="columnheader"] {
|
||||
background-color: var(--wds-color-bg) !important;
|
||||
}
|
||||
|
||||
[data-sticky-td] {
|
||||
position: sticky;
|
||||
position: -webkit-sticky;
|
||||
background-color: inherit;
|
||||
border-bottom: ${(props) =>
|
||||
props.variant === TableVariantTypes.VARIANT2
|
||||
? "none"
|
||||
: "1px solid var(--wds-color-border-onaccent)"};
|
||||
& .draggable-header {
|
||||
cursor: pointer;
|
||||
}
|
||||
&.hidden-cell,
|
||||
&:has(> .hidden-header) {
|
||||
z-index: 0;
|
||||
position: unset !important;
|
||||
}
|
||||
|
||||
&:has(> .hidden-header) .resizer {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
[data-sticky-last-left-td] {
|
||||
left: 0px;
|
||||
border-right: 3px solid var(--wds-color-border);
|
||||
&.hidden-cell,
|
||||
&:has(> .hidden-header) {
|
||||
border-right: 0.5px solid var(--wds-color-border);
|
||||
}
|
||||
}
|
||||
|
||||
[data-sticky-first-right-td] {
|
||||
right: 0px;
|
||||
border-left: 3px solid var(--wds-color-border);
|
||||
&.hidden-cell,
|
||||
&:has(> .hidden-header) {
|
||||
border-left: none;
|
||||
}
|
||||
}
|
||||
|
||||
& .sticky-right-modifier {
|
||||
border-left: 3px solid var(--wds-color-border);
|
||||
}
|
||||
}
|
||||
|
||||
.draggable-header,
|
||||
.hidden-header {
|
||||
width: 100%;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
color: ${Colors.OXFORD_BLUE};
|
||||
padding-left: 10px;
|
||||
&.sorted {
|
||||
padding-left: 5px;
|
||||
}
|
||||
}
|
||||
.draggable-header {
|
||||
cursor: grab;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: ${(props) => props.tableSizes.COLUMN_HEADER_HEIGHT};
|
||||
&.reorder-line {
|
||||
width: 1px;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.hidden-header {
|
||||
opacity: 0.6;
|
||||
|
||||
${invisible};
|
||||
}
|
||||
.header-menu {
|
||||
cursor: pointer;
|
||||
width: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.bp3-popover2-target {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&.hide-menu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.hide {
|
||||
&:hover {
|
||||
.bp3-popover2-target {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.bp3-popover2-target {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.column-menu {
|
||||
cursor: pointer;
|
||||
height: ${(props) => props.tableSizes.COLUMN_HEADER_HEIGHT}px;
|
||||
line-height: ${(props) => props.tableSizes.COLUMN_HEADER_HEIGHT}px;
|
||||
}
|
||||
.th {
|
||||
display: flex !important;
|
||||
justify-content: space-between;
|
||||
&.highlight-left {
|
||||
border-left: 2px solid ${Colors.GREEN};
|
||||
}
|
||||
&.highlight-right {
|
||||
border-right: 2px solid ${Colors.GREEN};
|
||||
}
|
||||
& .draggable-header--dragging {
|
||||
background: #efefef;
|
||||
border-radius: 4px;
|
||||
z-index: 100;
|
||||
width: 100%;
|
||||
text-overflow: none;
|
||||
overflow: none;
|
||||
}
|
||||
}
|
||||
.input-group {
|
||||
height: ${(props) => props.tableSizes.COLUMN_HEADER_HEIGHT}px;
|
||||
line-height: ${(props) => props.tableSizes.COLUMN_HEADER_HEIGHT}px;
|
||||
padding: 0 5px;
|
||||
}
|
||||
`;
|
||||
|
||||
|
|
@ -352,51 +88,6 @@ export const OptionWrapper = styled.div<{
|
|||
}
|
||||
`;
|
||||
|
||||
export const PaginationItemWrapper = styled.div<{
|
||||
disabled?: boolean;
|
||||
selected?: boolean;
|
||||
borderRadius: string;
|
||||
accentColor: string;
|
||||
}>`
|
||||
background: ${(props) =>
|
||||
props.disabled ? `var(--wds-color-bg-disabled)` : `var(--wds-color-bg)`};
|
||||
border: 1px solid
|
||||
${(props) =>
|
||||
props.disabled
|
||||
? `var(--wds-color-border-disabled)`
|
||||
: `var(--wds-color-border)`};
|
||||
box-sizing: border-box;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 0 4px;
|
||||
cursor: ${(props) => (props.disabled ? "not-allowed" : "pointer")};
|
||||
border-radius: ${({ borderRadius }) => borderRadius};
|
||||
|
||||
& > * {
|
||||
pointer-events: ${(props) => props.disabled && "none"};
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
& svg {
|
||||
fill: ${(props) =>
|
||||
props.disabled
|
||||
? `var(--wds-color-icon-disabled)`
|
||||
: `var(--wds-color-icon)`};
|
||||
}
|
||||
${({ disabled }) =>
|
||||
!disabled &&
|
||||
`&:hover {
|
||||
border-color: var(--wds-color-border-hover);
|
||||
background-color: var(--wds-color-bg-hover);
|
||||
}`}
|
||||
`;
|
||||
|
||||
export const MenuColumnWrapper = styled.div<{ selected: boolean }>`
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ type VirtualTableProps = TableColumnHeaderProps & {
|
|||
primaryColumnId?: string;
|
||||
isAddRowInProgress: boolean;
|
||||
totalColumnsWidth?: number;
|
||||
scrollContainerStyles: any;
|
||||
useVirtual: boolean;
|
||||
};
|
||||
|
||||
|
|
@ -65,7 +64,6 @@ const VirtualTable = (props: VirtualTableProps) => {
|
|||
selectedRowIndex={props.selectedRowIndex}
|
||||
selectedRowIndices={props.selectedRowIndices}
|
||||
sortTableColumn={props.sortTableColumn}
|
||||
tableSizes={props.tableSizes}
|
||||
totalColumnsWidth={props?.totalColumnsWidth}
|
||||
useVirtual={props.useVirtual}
|
||||
widgetId={props.widgetId}
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ export const renderEmptyRows = (
|
|||
|
||||
return rows.map((row: string, index: number) => {
|
||||
return (
|
||||
<EmptyRow className="tr" key={index} style={style}>
|
||||
<EmptyRow className="tr" key={index} role="row" style={style}>
|
||||
{multiRowSelection &&
|
||||
renderBodyCheckBoxCell(false, accentColor, borderRadius)}
|
||||
{tableColumns.map((column: any, colIndex: number) => {
|
||||
|
|
@ -155,6 +155,7 @@ export const renderEmptyRows = (
|
|||
? "td hidden-cell"
|
||||
: `td${addStickyModifierClass(columns, colIndex)}`
|
||||
}
|
||||
role="cell"
|
||||
{...stickyAttributes}
|
||||
key={colIndex}
|
||||
sticky={column?.sticky ?? StickyType.NONE}
|
||||
|
|
|
|||
|
|
@ -1,131 +1,17 @@
|
|||
import React, {
|
||||
createRef,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useState,
|
||||
memo,
|
||||
} from "react";
|
||||
import { MenuItem, Tooltip, Menu } from "@blueprintjs/core";
|
||||
import type { Key } from "react";
|
||||
import React, { useCallback, memo } from "react";
|
||||
|
||||
import { Colors } from "constants/Colors";
|
||||
import styled from "styled-components";
|
||||
import { ControlIcons } from "icons/ControlIcons";
|
||||
import type { CellAlignment } from "../Constants";
|
||||
import {
|
||||
HEADER_MENU_PORTAL_CLASS,
|
||||
JUSTIFY_CONTENT,
|
||||
MENU_CONTENT_CLASS,
|
||||
MULTISELECT_CHECKBOX_WIDTH,
|
||||
POPOVER_ITEMS_TEXT_MAP,
|
||||
StickyType,
|
||||
} from "../Constants";
|
||||
import { TooltipContentWrapper } from "../TableStyledWrappers";
|
||||
import { MULTISELECT_CHECKBOX_WIDTH, StickyType } from "../Constants";
|
||||
import { isColumnTypeEditable } from "widgets/wds/WDSTableWidget/widget/utilities";
|
||||
import { Popover2 } from "@blueprintjs/popover2";
|
||||
import { MenuDivider } from "@design-system/widgets-old";
|
||||
import { importRemixIcon, importSvg } from "@design-system/widgets-old";
|
||||
import { CANVAS_ART_BOARD } from "constants/componentClassNameConstants";
|
||||
|
||||
const Check = importRemixIcon(
|
||||
async () => import("remixicon-react/CheckFillIcon"),
|
||||
);
|
||||
const ArrowDownIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/ArrowDownSLineIcon"),
|
||||
);
|
||||
const EditIcon = importSvg(
|
||||
async () => import("assets/icons/control/edit-variant1.svg"),
|
||||
);
|
||||
|
||||
const AscendingIcon = styled(ControlIcons.SORT_CONTROL)`
|
||||
padding: 0;
|
||||
position: relative;
|
||||
top: 3px;
|
||||
cursor: pointer;
|
||||
transform: rotate(180deg);
|
||||
&& svg {
|
||||
path {
|
||||
fill: ${Colors.LIGHT_GREYISH_BLUE};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const DescendingIcon = styled(ControlIcons.SORT_CONTROL)`
|
||||
padding: 0;
|
||||
position: relative;
|
||||
top: 3px;
|
||||
cursor: pointer;
|
||||
&& svg {
|
||||
path {
|
||||
fill: ${Colors.LIGHT_GREYISH_BLUE};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const ColumnNameContainer = styled.div<{
|
||||
horizontalAlignment: CellAlignment;
|
||||
}>`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: ${(props) =>
|
||||
props?.horizontalAlignment && JUSTIFY_CONTENT[props.horizontalAlignment]};
|
||||
`;
|
||||
|
||||
const StyledEditIcon = styled(EditIcon)`
|
||||
width: 14px;
|
||||
min-width: 14px;
|
||||
margin-right: 3px;
|
||||
`;
|
||||
|
||||
const TitleWrapper = styled.div`
|
||||
&,
|
||||
span {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
`;
|
||||
|
||||
interface TitleProps {
|
||||
children: React.ReactNode;
|
||||
tableWidth?: number;
|
||||
width?: number;
|
||||
}
|
||||
|
||||
function Title(props: TitleProps) {
|
||||
const ref = createRef<HTMLDivElement>();
|
||||
const [useToolTip, updateToolTip] = useState(false);
|
||||
useEffect(() => {
|
||||
const element = ref.current;
|
||||
if (element && element.offsetWidth < element.scrollWidth) {
|
||||
updateToolTip(true);
|
||||
} else {
|
||||
updateToolTip(false);
|
||||
}
|
||||
}, [ref.current, props.width, props.children]);
|
||||
|
||||
return (
|
||||
<TitleWrapper ref={ref}>
|
||||
{useToolTip && props.children ? (
|
||||
<Tooltip
|
||||
autoFocus={false}
|
||||
content={
|
||||
<TooltipContentWrapper width={(props.tableWidth || 300) - 32}>
|
||||
{props.children}
|
||||
</TooltipContentWrapper>
|
||||
}
|
||||
hoverOpenDelay={1000}
|
||||
position="top"
|
||||
>
|
||||
{props.children}
|
||||
</Tooltip>
|
||||
) : (
|
||||
props.children
|
||||
)}
|
||||
</TitleWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
const ICON_SIZE = 16;
|
||||
import {
|
||||
Flex,
|
||||
Icon,
|
||||
IconButton,
|
||||
Item,
|
||||
Menu,
|
||||
MenuList,
|
||||
Text,
|
||||
} from "@design-system/widgets";
|
||||
|
||||
interface HeaderProps {
|
||||
canFreezeColumn?: boolean;
|
||||
|
|
@ -162,11 +48,11 @@ interface HeaderProps {
|
|||
|
||||
const HeaderCellComponent = (props: HeaderProps) => {
|
||||
const { column, editMode, isSortable } = props;
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||
|
||||
const headerProps = { ...column.getHeaderProps() };
|
||||
headerProps["style"] = {
|
||||
...headerProps.style,
|
||||
display: "flex",
|
||||
left:
|
||||
column.sticky === StickyType.LEFT && props.multiRowSelection
|
||||
? MULTISELECT_CHECKBOX_WIDTH + column.totalLeft
|
||||
|
|
@ -239,14 +125,35 @@ const HeaderCellComponent = (props: HeaderProps) => {
|
|||
[props.onDrop, props.columnIndex],
|
||||
);
|
||||
|
||||
const onActionOnMenu = (key: Key) => {
|
||||
switch (key) {
|
||||
case "sort-asc":
|
||||
props.sortTableColumn(props.columnIndex, true);
|
||||
break;
|
||||
case "sort-desc":
|
||||
props.sortTableColumn(props.columnIndex, false);
|
||||
break;
|
||||
case "freeze-left":
|
||||
toggleColumnFreeze(StickyType.LEFT);
|
||||
break;
|
||||
case "freeze-right":
|
||||
toggleColumnFreeze(StickyType.RIGHT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
<th
|
||||
{...headerProps}
|
||||
aria-hidden={props.isHidden ? "true" : undefined}
|
||||
className={`th header-reorder ${props.stickyRightModifier}`}
|
||||
data-header={props.columnName}
|
||||
>
|
||||
<div
|
||||
className={!props.isHidden ? `draggable-header` : "hidden-header"}
|
||||
data-draggable-header=""
|
||||
draggable={
|
||||
(props.column.sticky === StickyType.NONE && !props.isHidden) ||
|
||||
undefined
|
||||
|
|
@ -259,101 +166,64 @@ const HeaderCellComponent = (props: HeaderProps) => {
|
|||
onDragOver={onDragOver}
|
||||
onDragStart={onDragStart}
|
||||
onDrop={onDrop}
|
||||
style={
|
||||
{
|
||||
"--padding-inline-end": props.isAscOrder
|
||||
? "calc((var(--outer-spacing-2) * 2) + (2 *var(--sizing-7)))"
|
||||
: "calc((var(--outer-spacing-2) * 2) + var(--sizing-7))",
|
||||
} as React.CSSProperties
|
||||
}
|
||||
>
|
||||
<ColumnNameContainer
|
||||
horizontalAlignment={column.columnProperties.horizontalAlignment}
|
||||
<Flex
|
||||
alignItems="center"
|
||||
gap="spacing-1"
|
||||
justifyContent={column.columnProperties.horizontalAlignment}
|
||||
>
|
||||
{isColumnEditable && <StyledEditIcon />}
|
||||
<Title width={props.width}>
|
||||
{isColumnEditable && <Icon name="edit" size="small" />}
|
||||
<Text
|
||||
lineClamp={1}
|
||||
title={props.columnName.replace(/\s/g, "\u00a0")}
|
||||
variant="caption"
|
||||
>
|
||||
{props.columnName.replace(/\s/g, "\u00a0")}
|
||||
</Title>
|
||||
</ColumnNameContainer>
|
||||
</Text>
|
||||
</Flex>
|
||||
</div>
|
||||
<div
|
||||
className={`header-menu ${
|
||||
!isSortable && !props.canFreezeColumn && "hide-menu"
|
||||
} ${!isMenuOpen && "hide"}`}
|
||||
>
|
||||
<Popover2
|
||||
content={
|
||||
<Menu className={MENU_CONTENT_CLASS}>
|
||||
<MenuItem
|
||||
disabled={disableSort}
|
||||
labelElement={props.isAscOrder === true ? <Check /> : undefined}
|
||||
onClick={() => {
|
||||
props.sortTableColumn(props.columnIndex, true);
|
||||
}}
|
||||
text={POPOVER_ITEMS_TEXT_MAP.SORT_ASC}
|
||||
/>
|
||||
<MenuItem
|
||||
disabled={disableSort}
|
||||
labelElement={
|
||||
props.isAscOrder === false ? <Check /> : undefined
|
||||
}
|
||||
onClick={() => {
|
||||
props.sortTableColumn(props.columnIndex, false);
|
||||
}}
|
||||
text={POPOVER_ITEMS_TEXT_MAP.SORT_DSC}
|
||||
/>
|
||||
<MenuDivider
|
||||
style={{
|
||||
marginLeft: 0,
|
||||
marginRight: 0,
|
||||
}}
|
||||
/>
|
||||
<MenuItem
|
||||
disabled={!props.canFreezeColumn}
|
||||
labelElement={
|
||||
column.sticky === StickyType.LEFT ? <Check /> : undefined
|
||||
}
|
||||
onClick={() => {
|
||||
toggleColumnFreeze(StickyType.LEFT);
|
||||
}}
|
||||
text={POPOVER_ITEMS_TEXT_MAP.FREEZE_LEFT}
|
||||
/>
|
||||
<MenuItem
|
||||
disabled={!props.canFreezeColumn}
|
||||
labelElement={
|
||||
column.sticky === StickyType.RIGHT ? <Check /> : undefined
|
||||
}
|
||||
onClick={() => {
|
||||
toggleColumnFreeze(StickyType.RIGHT);
|
||||
}}
|
||||
text={POPOVER_ITEMS_TEXT_MAP.FREEZE_RIGHT}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
interactionKind="hover"
|
||||
isOpen={isMenuOpen}
|
||||
minimal
|
||||
onInteraction={setIsMenuOpen}
|
||||
placement="bottom-end"
|
||||
portalClassName={`${HEADER_MENU_PORTAL_CLASS}-${props.widgetId}`}
|
||||
portalContainer={
|
||||
document.getElementById(CANVAS_ART_BOARD) || undefined
|
||||
}
|
||||
>
|
||||
<ArrowDownIcon className="w-5 h-5" color="var(--wds-color-icon)" />
|
||||
</Popover2>
|
||||
</div>
|
||||
{props.isAscOrder !== undefined ? (
|
||||
<div>
|
||||
{props.isAscOrder ? (
|
||||
<AscendingIcon height={ICON_SIZE} width={ICON_SIZE} />
|
||||
) : (
|
||||
<DescendingIcon height={ICON_SIZE} width={ICON_SIZE} />
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
<Flex alignItems="center" gap="spacing-1">
|
||||
{props.isAscOrder !== undefined && (
|
||||
<Icon
|
||||
name={props.isAscOrder ? "arrow-up" : "arrow-down"}
|
||||
size="small"
|
||||
/>
|
||||
)}
|
||||
<Menu disabledKeys={["separator"]} onAction={onActionOnMenu}>
|
||||
<IconButton
|
||||
color="neutral"
|
||||
icon="chevron-down"
|
||||
size="small"
|
||||
variant="ghost"
|
||||
/>
|
||||
<MenuList>
|
||||
<Item key="sort-asc">Sort column ascending</Item>
|
||||
<Item key="sort-desc">Sort column descending</Item>
|
||||
<Item isSeparator key="separator">
|
||||
Separator
|
||||
</Item>
|
||||
<Item key="freeze-left">Freeze column left</Item>
|
||||
<Item key="freeze-right">Freeze column right</Item>
|
||||
</MenuList>
|
||||
</Menu>
|
||||
</Flex>
|
||||
<div
|
||||
{...column.getResizerProps()}
|
||||
className={`resizer ${column.isResizing ? "isResizing" : ""}`}
|
||||
data-resizor=""
|
||||
data-status={column.isResizing ? "resizing" : ""}
|
||||
onClick={(e: React.MouseEvent<HTMLElement>) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</th>
|
||||
);
|
||||
};
|
||||
export const HeaderCell = memo(HeaderCellComponent);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ export const renderBodyCheckBoxCell = (
|
|||
data-sticky-td="true"
|
||||
isCellVisible
|
||||
isChecked={isChecked}
|
||||
role="cell"
|
||||
>
|
||||
<CellCheckbox>
|
||||
{isChecked && <CheckBoxCheckIcon className="th-svg" />}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,224 @@
|
|||
.table {
|
||||
--th-height: calc(
|
||||
var(--caption-line-height) + var(--caption-margin-end) +
|
||||
var(--caption-margin-start) + (2 * var(--outer-spacing-3))
|
||||
);
|
||||
--tr-height: calc(
|
||||
var(--body-line-height) + var(--body-margin-end) + var(--body-margin-start) +
|
||||
(2 * var(--outer-spacing-4))
|
||||
);
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
background: var(--color-bg-elevation-3);
|
||||
border-style: solid;
|
||||
border-width: var(--border-width-1);
|
||||
border-color: var(--color-bd);
|
||||
border-radius: var(--border-radius-elevation-3);
|
||||
box-sizing: border-box;
|
||||
/* adding overflow hidden so that the scollbar at the bottom does not flow out */
|
||||
overflow: hidden;
|
||||
|
||||
& [aria-hidden] {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* WRAPPER
|
||||
*-------------------------------------------------------------------------- */
|
||||
[data-table-wrapper] {
|
||||
display: block;
|
||||
position: relative;
|
||||
overflow: auto hidden;
|
||||
scrollbar-color: initial;
|
||||
container-type: inline-size;
|
||||
}
|
||||
|
||||
&[data-type="virtualized"] [data-table-wrapper] {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* TABLE
|
||||
*-------------------------------------------------------------------------- */
|
||||
& [role="table"] {
|
||||
background-position-x: var(--th-height);
|
||||
background-position-y: var(--tr-height);
|
||||
|
||||
border-spacing: 0;
|
||||
display: table;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* THEAD
|
||||
*-------------------------------------------------------------------------- */
|
||||
& thead {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* ROWGROUP
|
||||
*-------------------------------------------------------------------------- */
|
||||
& [role="rowgroup"] {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* TH
|
||||
*-------------------------------------------------------------------------- */
|
||||
& thead [role="columnheader"] {
|
||||
padding-inline: var(--outer-spacing-1);
|
||||
padding-block: var(--outer-spacing-1);
|
||||
background: var(--color-bg-elevation-3);
|
||||
font-weight: bold;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
border-block-end: var(--border-width-1) solid var(--color-bd);
|
||||
}
|
||||
|
||||
&[data-variant="default"] thead [role="columnheader"] {
|
||||
border-inline-end: var(--border-width-1) solid var(--color-bd);
|
||||
}
|
||||
|
||||
& thead [role="columnheader"]:last-child {
|
||||
border-inline-end: none;
|
||||
}
|
||||
|
||||
& thead [role="columnheader"][data-sticky-td] {
|
||||
position: sticky;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
& thead [role="columnheader"][data-highlight-position="start"] {
|
||||
border-inline-start: 2px solid var(--color-bd-positive);
|
||||
}
|
||||
|
||||
& thead [role="columnheader"][data-highlight-position="end"] {
|
||||
border-inline-end: 2px solid var(--color-bd-positive);
|
||||
}
|
||||
|
||||
& thead [role="columnheader"] [data-draggable-header] {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: items;
|
||||
padding-inline: var(--outer-spacing-2);
|
||||
padding-inline-end: var(--padding-inline-end);
|
||||
}
|
||||
|
||||
&
|
||||
thead
|
||||
[role="columnheader"]:has([data-status="dragging"])
|
||||
[data-draggable-header] {
|
||||
background: var(--color-bg);
|
||||
border-radius: 4px;
|
||||
z-index: 100;
|
||||
width: 100%;
|
||||
text-overflow: none;
|
||||
overflow: none;
|
||||
}
|
||||
|
||||
& thead [role="columnheader"][data-sticky-last-left-td]:not([aria-hidden]) {
|
||||
/*important is added below because the useSticky hooks adds left as inline css */
|
||||
left: 0px !important;
|
||||
border-right: 3px solid var(--color-bd);
|
||||
}
|
||||
|
||||
& thead [role="columnheader"][data-sticky-first-right-td]:not([aria-hidden]) {
|
||||
/*important is added below because the useSticky hooks adds left as inline css */
|
||||
right: 0px !important;
|
||||
border-left: 3px solid var(--color-bd);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* TR
|
||||
*-------------------------------------------------------------------------- */
|
||||
& [role="row"] {
|
||||
display: flex;
|
||||
block-size: var(--tr-height);
|
||||
}
|
||||
|
||||
& [role="row"]:has([role="columnheader"]) {
|
||||
block-size: var(--th-height);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Cell ( td )
|
||||
*-------------------------------------------------------------------------- */
|
||||
& [role="cell"] {
|
||||
background-color: var(--color-bg-elevation-3);
|
||||
}
|
||||
|
||||
& [role="row"][aria-checked="true"] [role="cell"] {
|
||||
background-color: var(--color-bg-accent-subtle);
|
||||
}
|
||||
|
||||
&[data-status="add-row-in-progress"] [role="cell"] {
|
||||
background: var(--color-bg);
|
||||
}
|
||||
|
||||
& [role="row"][data-is-new] [role="cell"] {
|
||||
background: var(--color-bg-accent-subtle);
|
||||
}
|
||||
|
||||
&[data-variant="default"] [role="cell"]:not(:last-child) {
|
||||
border-inline-end: var(--border-width-1) solid var(--color-bd);
|
||||
}
|
||||
|
||||
&:is([data-variant="horizontal-borders"], [data-variant="default"])
|
||||
[role="cell"] {
|
||||
border-block-end: var(--border-width-1) solid var(--color-bd);
|
||||
}
|
||||
|
||||
& [role="cell"][data-sticky-td] {
|
||||
position: sticky;
|
||||
position: -webkit-sticky;
|
||||
}
|
||||
|
||||
& [role="cell"][data-sticky-last-left-td]:not([aria-hidden]) {
|
||||
/*important is added below because the useSticky hooks adds left as inline css */
|
||||
left: 0px !important;
|
||||
border-right: 3px solid var(--color-bd);
|
||||
}
|
||||
|
||||
& [role="cell"][data-sticky-first-right-td]:not([aria-hidden]) {
|
||||
/*important is below here because the useSticky hooks adds left as inline css */
|
||||
right: 0px !important;
|
||||
border-left: 3px solid var(--color-bd);
|
||||
}
|
||||
|
||||
/*important is added below because the useSticky hooks adds styles as inline css */
|
||||
& :is([role="cell"], th)[data-sticky-td][aria-hidden] {
|
||||
position: relative !important;
|
||||
left: unset !important;
|
||||
right: unset !important;
|
||||
}
|
||||
/* --------------------------------------------------------------------------
|
||||
* Resizor
|
||||
*-------------------------------------------------------------------------- */
|
||||
& [data-resizor] {
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
transform: translateX(50%);
|
||||
z-index: 1;
|
||||
/* prevents from scrolling while dragging on touch devices */
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
& [data-resizor][data-status="resizing"] {
|
||||
cursor: isResizing;
|
||||
}
|
||||
|
||||
& thead th:last-child [data-resizor] {
|
||||
right: 5px;
|
||||
}
|
||||
}
|
||||
|
|
@ -13,7 +13,6 @@ import {
|
|||
updateCurrencyDefaultValues,
|
||||
updateMenuItemsSource,
|
||||
updateNumberColumnTypeTextAlignment,
|
||||
updateThemeStylesheetsInColumns,
|
||||
} from "../../../widget/propertyUtils";
|
||||
import { AutocompleteDataType } from "utils/autocomplete/AutocompleteDataType";
|
||||
import { composePropertyUpdateHook } from "widgets/WidgetUtils";
|
||||
|
|
@ -84,7 +83,6 @@ export default {
|
|||
],
|
||||
updateHook: composePropertyUpdateHook([
|
||||
updateNumberColumnTypeTextAlignment,
|
||||
updateThemeStylesheetsInColumns,
|
||||
updateMenuItemsSource,
|
||||
updateCurrencyDefaultValues,
|
||||
]),
|
||||
|
|
|
|||
|
|
@ -194,47 +194,6 @@ export const styleConfig = [
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
propertyName: "borderRadius",
|
||||
label: "Border radius",
|
||||
helpText: "Rounds the corners of the icon button's outer border edge",
|
||||
controlType: "BORDER_RADIUS_OPTIONS",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
{
|
||||
propertyName: "boxShadow",
|
||||
label: "Box shadow",
|
||||
helpText:
|
||||
"Enables you to cast a drop shadow from the frame of the widget",
|
||||
controlType: "BOX_SHADOW_OPTIONS",
|
||||
isJSConvertible: true,
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
{
|
||||
helpText: "Use a html color name, HEX, RGB or RGBA value",
|
||||
placeholderText: "#FFFFFF / Gray / rgb(255, 99, 71)",
|
||||
propertyName: "borderColor",
|
||||
label: "Border color",
|
||||
controlType: "COLOR_PICKER",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.TEXT },
|
||||
},
|
||||
{
|
||||
helpText: "Enter value for border width",
|
||||
propertyName: "borderWidth",
|
||||
label: "Border width",
|
||||
placeholderText: "Enter value in px",
|
||||
controlType: "INPUT_TEXT",
|
||||
isBindProperty: true,
|
||||
isTriggerProperty: false,
|
||||
validation: { type: ValidationTypes.NUMBER },
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import _, {
|
|||
|
||||
import type { WidgetState } from "widgets/BaseWidget";
|
||||
import BaseWidget from "widgets/BaseWidget";
|
||||
import { RenderModes, WIDGET_PADDING } from "constants/WidgetConstants";
|
||||
import { RenderModes } from "constants/WidgetConstants";
|
||||
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import Skeleton from "components/utils/Skeleton";
|
||||
import { noop, retryPromise } from "utils/AppsmithUtils";
|
||||
|
|
@ -910,8 +910,7 @@ export class WDSTableWidget extends BaseWidget<TableWidgetProps, WidgetState> {
|
|||
document
|
||||
.getElementById(getAnvilWidgetDOMId(this.props.widgetId))
|
||||
?.getBoundingClientRect().width || this.props.componentWidth;
|
||||
// (2 * WIDGET_PADDING) gives the total horizontal padding (i.e. paddingLeft + paddingRight)
|
||||
componentWidth = componentWidth - 2 * WIDGET_PADDING;
|
||||
componentWidth = componentWidth;
|
||||
return { componentHeight: 300, componentWidth };
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,10 +6,6 @@ import type { TableWidgetProps } from "../constants";
|
|||
import { ColumnTypes, InlineEditingSaveOptions } from "../constants";
|
||||
import _, { findIndex, get, isBoolean } from "lodash";
|
||||
import { Colors } from "constants/Colors";
|
||||
import {
|
||||
combineDynamicBindings,
|
||||
getDynamicBindings,
|
||||
} from "utils/DynamicBindingUtils";
|
||||
import {
|
||||
createEditActionColumn,
|
||||
generateNewColumnOrderFromStickyValue,
|
||||
|
|
@ -559,72 +555,6 @@ export const updateNumberColumnTypeTextAlignment = (
|
|||
return;
|
||||
};
|
||||
|
||||
/**
|
||||
* updates theme stylesheets
|
||||
*
|
||||
* @param props
|
||||
* @param propertyPath
|
||||
* @param propertyValue
|
||||
*/
|
||||
export function updateThemeStylesheetsInColumns(
|
||||
props: TableWidgetProps,
|
||||
propertyPath: string,
|
||||
propertyValue: any,
|
||||
): Array<PropertyUpdates> | undefined {
|
||||
const regex = /^primaryColumns\.(\w+)\.(.*)$/;
|
||||
const matches = propertyPath.match(regex);
|
||||
const columnId = matches?.[1];
|
||||
const columnProperty = matches?.[2];
|
||||
|
||||
if (columnProperty === "columnType") {
|
||||
const propertiesToUpdate: Array<PropertyUpdates> = [];
|
||||
const oldColumnType = get(props, `primaryColumns.${columnId}.columnType`);
|
||||
const newColumnType = propertyValue;
|
||||
|
||||
const propertiesToRemove = Object.keys(
|
||||
props.childStylesheet[oldColumnType] || {},
|
||||
);
|
||||
|
||||
const propertiesToAdd = Object.keys(
|
||||
props.childStylesheet[newColumnType] || {},
|
||||
);
|
||||
|
||||
propertiesToRemove.forEach((propertyKey) => {
|
||||
propertiesToUpdate.push({
|
||||
propertyPath: `primaryColumns.${columnId}.${propertyKey}`,
|
||||
shouldDeleteProperty: true,
|
||||
});
|
||||
});
|
||||
|
||||
propertiesToAdd.forEach((propertyKey) => {
|
||||
const { jsSnippets, stringSegments } = getDynamicBindings(
|
||||
props.childStylesheet[newColumnType][propertyKey],
|
||||
);
|
||||
|
||||
const js = combineDynamicBindings(jsSnippets, stringSegments);
|
||||
|
||||
propertiesToUpdate.push({
|
||||
propertyPath: `primaryColumns.${columnId}.${propertyKey}`,
|
||||
propertyValue: `{{${props.widgetName}.processedTableData.map((currentRow, currentIndex) => ( ${js}))}}`,
|
||||
});
|
||||
});
|
||||
|
||||
if (propertiesToUpdate.length) {
|
||||
/*
|
||||
* Temporary patch to make evaluations to compute inverseDependencyMap when
|
||||
* column type is changed.
|
||||
* TODO(Balaji): remove once https://github.com/appsmithorg/appsmith/issues/14436 gets fixed
|
||||
*/
|
||||
propertiesToUpdate.push({
|
||||
propertyPath: `primaryColumns.${columnId}.customAlias`,
|
||||
propertyValue: "",
|
||||
});
|
||||
|
||||
return propertiesToUpdate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A function for updateHook to remove the boxShadowColor property post migration.
|
||||
* @param props
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import {
|
|||
getArrayPropertyValue,
|
||||
getColumnType,
|
||||
getDerivedColumns,
|
||||
getHeaderClassNameOnDragDirection,
|
||||
getOriginalRowIndex,
|
||||
getSelectOptions,
|
||||
getSelectRowIndex,
|
||||
|
|
@ -2542,20 +2541,6 @@ describe("generateNewColumnOrderFromStickyValue", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("getHeaderClassNameOnDragDirection", () => {
|
||||
test("Should return left highlight class when dragging from right to left", () => {
|
||||
expect(getHeaderClassNameOnDragDirection(3, 2)).toEqual(
|
||||
"th header-reorder highlight-left",
|
||||
);
|
||||
});
|
||||
|
||||
test("Should return right highlight class when dragging from left to right", () => {
|
||||
expect(getHeaderClassNameOnDragDirection(1, 2)).toEqual(
|
||||
"th header-reorder highlight-right",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getSelectOptions", () => {
|
||||
it("Should return select options when user is not adding a new row", () => {
|
||||
const columnProperties = {
|
||||
|
|
|
|||
|
|
@ -25,11 +25,6 @@ import { SelectColumnOptionsValidations } from "./propertyUtils";
|
|||
import type { TableWidgetProps } from "../constants";
|
||||
import { get } from "lodash";
|
||||
import { getNextEntityName } from "utils/AppsmithUtils";
|
||||
import {
|
||||
combineDynamicBindings,
|
||||
getDynamicBindings,
|
||||
} from "utils/DynamicBindingUtils";
|
||||
import { ButtonVariantTypes } from "components/constants";
|
||||
import { dateFormatOptions } from "WidgetProvider/constants";
|
||||
import moment from "moment";
|
||||
import type { Stylesheet } from "entities/AppTheming";
|
||||
|
|
@ -668,32 +663,11 @@ export const createColumn = (props: TableWidgetProps, baseName: string) => {
|
|||
};
|
||||
|
||||
export const createEditActionColumn = (props: TableWidgetProps) => {
|
||||
const themeProps: Record<string, string> = {};
|
||||
|
||||
if (props.childStylesheet[ColumnTypes.EDIT_ACTIONS]) {
|
||||
Object.entries(props.childStylesheet[ColumnTypes.EDIT_ACTIONS]).forEach(
|
||||
([key, value]) => {
|
||||
const { jsSnippets, stringSegments } = getDynamicBindings(
|
||||
value as string,
|
||||
);
|
||||
|
||||
const js = combineDynamicBindings(jsSnippets, stringSegments);
|
||||
|
||||
themeProps[
|
||||
key
|
||||
] = `{{${props.widgetName}.processedTableData.map((currentRow, currentIndex) => ( ${js}))}}`;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
const column = {
|
||||
...createColumn(props, "EditActions"),
|
||||
...getEditActionColumnProperties(),
|
||||
...themeProps,
|
||||
columnType: ColumnTypes.EDIT_ACTIONS,
|
||||
label: "Save / Discard",
|
||||
discardButtonVariant: ButtonVariantTypes.TERTIARY,
|
||||
discardButtonColor: Colors.DANGER_SOLID,
|
||||
sticky: StickyType.RIGHT,
|
||||
};
|
||||
const columnOrder = [...(props.columnOrder || [])];
|
||||
|
|
@ -944,26 +918,27 @@ export const getAllStickyColumnsCount = (columns: TableColumnProps[]) => {
|
|||
};
|
||||
|
||||
/**
|
||||
* returns the highlight position when the column header is dragged
|
||||
*
|
||||
* @param currentIndex: current dragging item index
|
||||
* @param targetIndex: Index poistion of of header that is being hovered
|
||||
* @returns
|
||||
* @returns "start" | "end" | "none
|
||||
*/
|
||||
export const getHeaderClassNameOnDragDirection = (
|
||||
export const getHighlightPosition = (
|
||||
currentIndex: number,
|
||||
targetIndex: number,
|
||||
) => {
|
||||
let parentClasses = "th header-reorder";
|
||||
let position = "none";
|
||||
|
||||
if (currentIndex !== -1) {
|
||||
if (targetIndex > currentIndex) {
|
||||
parentClasses += " highlight-right";
|
||||
position = "end";
|
||||
} else if (targetIndex < currentIndex) {
|
||||
parentClasses += " highlight-left";
|
||||
position = "start";
|
||||
}
|
||||
}
|
||||
|
||||
return parentClasses;
|
||||
return position;
|
||||
};
|
||||
|
||||
export const getIndexByColumnName = (
|
||||
|
|
@ -1001,7 +976,7 @@ export const getDragHandlers = (
|
|||
) => {
|
||||
// We get the parent element(.th) so as to apply left and right highlighting
|
||||
const targetElem = e.target as HTMLDivElement;
|
||||
const parentTargetElem = targetElem.closest(".th.header-reorder");
|
||||
const parentTargetElem = targetElem.closest("th");
|
||||
|
||||
const currentIndex = getIndexByColumnName(
|
||||
currentDraggedColumn.current,
|
||||
|
|
@ -1009,30 +984,30 @@ export const getDragHandlers = (
|
|||
);
|
||||
|
||||
if (parentTargetElem) {
|
||||
parentTargetElem.className = getHeaderClassNameOnDragDirection(
|
||||
currentIndex,
|
||||
targetIndex,
|
||||
);
|
||||
if (parentTargetElem) {
|
||||
parentTargetElem.dataset.highlightPosition = getHighlightPosition(
|
||||
currentIndex,
|
||||
targetIndex,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
const onDragEnd = (e: React.DragEvent<HTMLDivElement>) => {
|
||||
const targetElem = e.target as HTMLDivElement;
|
||||
targetElem.className = targetElem.className.replace(
|
||||
" draggable-header--dragging",
|
||||
"",
|
||||
);
|
||||
targetElem.dataset.status = "";
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
const onDragLeave = (e: React.DragEvent<HTMLDivElement>) => {
|
||||
const targetElem = e.target as HTMLDivElement;
|
||||
const parentTargetElem = targetElem.closest(".th.header-reorder");
|
||||
const parentTargetElem = targetElem.closest("th");
|
||||
|
||||
if (parentTargetElem) {
|
||||
parentTargetElem.className = "th header-reorder";
|
||||
parentTargetElem.dataset.highlightPosition = "none";
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
|
@ -1043,7 +1018,7 @@ export const getDragHandlers = (
|
|||
) => {
|
||||
// We get the parent element(.th) so as to apply left and right highlighting
|
||||
const targetElem = e.target as HTMLDivElement;
|
||||
const parentTargetElem = targetElem.closest(".th.header-reorder");
|
||||
const parentTargetElem = targetElem.closest("th");
|
||||
|
||||
const currentIndex = getIndexByColumnName(
|
||||
currentDraggedColumn.current,
|
||||
|
|
@ -1051,7 +1026,7 @@ export const getDragHandlers = (
|
|||
);
|
||||
|
||||
if (parentTargetElem) {
|
||||
parentTargetElem.className = getHeaderClassNameOnDragDirection(
|
||||
parentTargetElem.dataset.highlightPosition = getHighlightPosition(
|
||||
currentIndex,
|
||||
targetIndex,
|
||||
);
|
||||
|
|
@ -1064,7 +1039,7 @@ export const getDragHandlers = (
|
|||
const onDragStart = (e: React.DragEvent<HTMLDivElement>, index: number) => {
|
||||
currentDraggedColumn.current = columns[index].alias;
|
||||
const targetElem = e.target as HTMLDivElement;
|
||||
targetElem.className = targetElem.className + " draggable-header--dragging";
|
||||
targetElem.dataset.status = "dragging";
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
|
|
@ -1078,10 +1053,7 @@ export const getDragHandlers = (
|
|||
partialColumnOrder.splice(index, 0, currentDraggedColumn.current);
|
||||
handleReorderColumn(partialColumnOrder);
|
||||
}
|
||||
targetElem.className = targetElem.className.replace(
|
||||
" draggable-header--dragging",
|
||||
"",
|
||||
);
|
||||
targetElem.dataset.status = "";
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user