Skip to content

Commit 748b56a

Browse files
committed
add custom classes + update changelog
1 parent 1a5e71c commit 748b56a

File tree

10 files changed

+86
-19
lines changed

10 files changed

+86
-19
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
# CHANGELOG
22

3+
## 0.4.5
4+
5+
_2023-09-27_
6+
7+
### Features
8+
9+
- Added the ability to provide a footer using the `footerComponent` property
10+
- If `footerComponent` is defined, can also provide a `stickyFooter` prop to make the footer sticky.
11+
- Since the last deploy, upgraded all the dependencies to fix Dependabot alerts
12+
- Can provide classNames to several different properties to make it more Tailwind friendly
13+
- The example site is powered by Vite as opposed to create-react-app
14+
- The example site is now in Typescript
15+
316
## 0.4.2
417

518
_2020-09-07_

example/src/Props.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,23 @@ const data: PropData[] = [
177177
type: "object",
178178
description: "Add custom css styles to the table header"
179179
},
180+
{
181+
prop: "headerClassname",
182+
type: "object",
183+
description: "Add custom css className to the table header"
184+
},
180185
{
181186
prop: "rowStyle",
182187
type: "object | (index: number) => object",
183188
description:
184189
"Add custom css styles to each row element. One can also pass in a function that takes in the row number in order to provide custom styling for particular rows."
185190
},
191+
{
192+
prop: "rowClassname",
193+
type: "string | (index: number) => string",
194+
description:
195+
"Add custom css className to each row element. One can also pass in a function that takes in the row number in order to provide custom styling for particular rows."
196+
},
186197
{
187198
prop: "subComponent",
188199
type: "Element",

index.d.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ export interface RowRenderProps<T> {
7979
* the cells for the row
8080
*/
8181
children: ReactNode;
82+
/**
83+
* the className for the row-renderer
84+
*/
85+
className?: string;
8286
}
8387

8488
export interface SubComponentProps<T> {
@@ -216,11 +220,20 @@ export interface TableProps<T> {
216220
* React styles used for customizing the header.
217221
*/
218222
headerStyle?: CSSProperties;
223+
/**
224+
* a className used to customize the header
225+
*/
226+
headerClassname?: string;
219227
/**
220228
* React styles used for customizing each row. Could be an object or
221229
* a function that takes the index of the row and returns an object.
222230
*/
223231
rowStyle?: CSSProperties | ((index: number) => CSSProperties);
232+
/**
233+
* React className used for customizing each row. Could be an object or
234+
* a function that takes the index of the row and returns an object.
235+
*/
236+
rowClassname?: string | ((index: number) => string);
224237
/**
225238
* generates a unique identifier for the row
226239
* @param row the row

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-fluid-table",
3-
"version": "0.4.4",
3+
"version": "0.4.5",
44
"description": "A React table inspired by react-window",
55
"author": "Mckervin Ceme <mckervinc@live.com>",
66
"license": "MIT",

src/Footer.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { useContext } from "react";
22
import { TableContext } from "./TableContext";
3+
import { cx } from "./util";
34

45
const Footer = () => {
56
const { uuid, stickyFooter, footerComponent: FooterComponent } = useContext(TableContext);
@@ -12,7 +13,7 @@ const Footer = () => {
1213
return (
1314
<div
1415
data-footer-key={`${uuid}-footer`}
15-
className={`react-fluid-table-footer ${stickyFooter ? "sticky" : ""}`.trim()}
16+
className={cx(["react-fluid-table-footer", stickyFooter && "sticky"])}
1617
>
1718
<FooterComponent />
1819
</div>

src/Header.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { forwardRef, useContext } from "react";
22
import { ColumnProps, SortDirection } from "../index";
33
import { TableContext } from "./TableContext";
44
import { NO_NODE } from "./constants";
5+
import { cx } from "./util";
56

67
interface HeaderCellProps<T> {
78
width: number;
@@ -10,7 +11,7 @@ interface HeaderCellProps<T> {
1011

1112
interface HeaderProps {
1213
children: React.ReactNode;
13-
style: React.CSSProperties
14+
style: React.CSSProperties;
1415
}
1516

1617
function InnerHeaderCell<T>({ column, width }: HeaderCellProps<T>) {
@@ -77,7 +78,7 @@ HeaderCell.displayName = "HeaderCell";
7778

7879
const Header = forwardRef(({ children, ...rest }: HeaderProps, ref: any) => {
7980
// hooks
80-
const { uuid, columns, pixelWidths, headerStyle } = useContext(TableContext);
81+
const { uuid, columns, pixelWidths, headerStyle, headerClassname } = useContext(TableContext);
8182

8283
// variables
8384
const { scrollWidth, clientWidth } = ref.current || NO_NODE;
@@ -92,7 +93,7 @@ const Header = forwardRef(({ children, ...rest }: HeaderProps, ref: any) => {
9293
>
9394
<div className="sticky-header" data-header-key={`${uuid}-header`}>
9495
<div className="row-wrapper" style={{ width }}>
95-
<div className="react-fluid-table-header" style={headerStyle}>
96+
<div className={cx(["react-fluid-table-header", headerClassname])} style={headerStyle}>
9697
{columns.map((c, i) => (
9798
<HeaderCell key={c.key} column={c} width={pixelWidths[i]} />
9899
))}

src/Row.tsx

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Minus from "./svg/minus-circle.svg";
66
import Plus from "./svg/plus-circle.svg";
77
import { TableContext } from "./TableContext";
88
import { ListChildComponentProps } from "react-window";
9+
import { cx } from "./util";
910

1011
interface TableCellProps<T> {
1112
row: T;
@@ -20,6 +21,7 @@ interface TableCellProps<T> {
2021
interface RowContainerProps<T> {
2122
row: T;
2223
index: number;
24+
className?: string;
2325
children: React.ReactNode;
2426
containerStyle: React.CSSProperties;
2527
onRowClick: (event: React.MouseEvent<Element, MouseEvent>, data: { index: number }) => void;
@@ -30,6 +32,7 @@ interface RowProps<T> extends Omit<ListChildComponentProps<T>, "data"> {
3032
row: T;
3133
borders: boolean;
3234
rowHeight: number;
35+
rowClassname: string | ((index: number) => string);
3336
rowStyle: React.CSSProperties | ((index: number) => React.CSSProperties);
3437
useRowWidth: boolean;
3538
clearSizeCache: CacheFunction;
@@ -44,6 +47,7 @@ interface RowProps<T> extends Omit<ListChildComponentProps<T>, "data"> {
4447
}
4548

4649
type CSSFunction = (index: number) => React.CSSProperties;
50+
type CSSClassFunction = (index: number) => string;
4751

4852
const getRowStyle = (index: number, rowStyle?: React.CSSProperties | CSSFunction) => {
4953
if (!rowStyle) {
@@ -53,6 +57,14 @@ const getRowStyle = (index: number, rowStyle?: React.CSSProperties | CSSFunction
5357
return typeof rowStyle === "function" ? rowStyle(index) : rowStyle;
5458
};
5559

60+
const getRowClassname = (index: number, rowClassname?: string | CSSClassFunction) => {
61+
if (!rowClassname) {
62+
return undefined;
63+
}
64+
65+
return typeof rowClassname === "function" ? rowClassname(index) : rowClassname;
66+
};
67+
5668
function InnerTableCell<T>({
5769
row,
5870
index,
@@ -116,6 +128,7 @@ function RowContainer<T>({
116128
row,
117129
index,
118130
children,
131+
className,
119132
onRowClick,
120133
containerStyle,
121134
rowRenderer: RowRenderer
@@ -135,14 +148,18 @@ function RowContainer<T>({
135148
display: "flex"
136149
};
137150
return (
138-
<RowRenderer row={row} index={index} style={style}>
151+
<RowRenderer row={row} index={index} className={className} style={style}>
139152
{children}
140153
</RowRenderer>
141154
);
142155
}
143156

144157
return (
145-
<div className="row-container" style={containerStyle} onClick={onContainerClick}>
158+
<div
159+
className={cx(["row-container", className])}
160+
style={containerStyle}
161+
onClick={onContainerClick}
162+
>
146163
{children}
147164
</div>
148165
);
@@ -156,6 +173,7 @@ function Row<T>({
156173
rowStyle,
157174
rowHeight,
158175
onRowClick,
176+
rowClassname,
159177
useRowWidth,
160178
rowRenderer,
161179
clearSizeCache,
@@ -188,6 +206,7 @@ function Row<T>({
188206
height: containerHeight,
189207
...getRowStyle(index, rowStyle)
190208
};
209+
const containerClassname = getRowClassname(index, rowClassname);
191210

192211
// function(s)
193212
const onExpanderClick = useCallback(() => {
@@ -231,6 +250,7 @@ function Row<T>({
231250
index={index}
232251
onRowClick={onRowClick}
233252
rowRenderer={rowRenderer}
253+
className={containerClassname}
234254
containerStyle={containerStyle}
235255
>
236256
{columns.map((c, i) => (

src/Table.tsx

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { DEFAULT_HEADER_HEIGHT, DEFAULT_ROW_HEIGHT, NO_NODE } from "./constants"
2020
import {
2121
arraysMatch,
2222
calculateColumnWidths,
23+
cx,
2324
findHeaderByUuid,
2425
findRowByUuidAndKey,
2526
guessTableHeight,
@@ -42,16 +43,7 @@ interface ListProps<T> extends Omit<TableProps<T>, "columns" | "borders"> {
4243
*/
4344
const ListComponent = forwardRef(
4445
(
45-
{
46-
data,
47-
width,
48-
height,
49-
itemKey,
50-
rowHeight,
51-
className,
52-
headerHeight,
53-
...rest
54-
}: ListProps<any>,
46+
{ data, width, height, itemKey, rowHeight, className, headerHeight, ...rest }: ListProps<any>,
5547
ref: React.ForwardedRef<TableRef>
5648
) => {
5749
// hooks
@@ -136,7 +128,7 @@ const ListComponent = forwardRef(
136128

137129
const shouldUseRowWidth = useCallback(() => {
138130
const parentElement = tableRef.current?.parentElement || NO_NODE;
139-
setUseRowWidth(parentElement.scrollWidth <= parentElement.clientWidth);
131+
setUseRowWidth(parentElement.scrollWidth <= parentElement.clientWidth);
140132
}, [tableRef]);
141133

142134
// effects
@@ -236,7 +228,7 @@ const ListComponent = forwardRef(
236228

237229
return (
238230
<VariableSizeList
239-
className={`react-fluid-table ${className || ""}`.trim()}
231+
className={cx(["react-fluid-table", className])}
240232
ref={listRef}
241233
innerRef={tableRef}
242234
innerElementType={Header}
@@ -316,6 +308,7 @@ const Table = forwardRef(
316308
tableWidth,
317309
tableStyle,
318310
headerStyle,
311+
headerClassname,
319312
footerComponent,
320313
borders = false,
321314
minColumnWidth = 80,
@@ -341,6 +334,7 @@ const Table = forwardRef(
341334
sortDirection,
342335
tableStyle,
343336
headerStyle,
337+
headerClassname,
344338
stickyFooter,
345339
footerComponent
346340
}}

src/TableContext.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ interface TableState extends ReactContext {
3232
onSort?: (col: string | null, dir: SortDirection) => void;
3333
tableStyle?: React.CSSProperties;
3434
headerStyle?: React.CSSProperties;
35+
headerClassname?: string;
3536
}
3637

3738
const baseState: TableState = {
@@ -56,6 +57,7 @@ const fields = [
5657
"columns",
5758
"tableStyle",
5859
"headerStyle",
60+
"headerClassname",
5961
"stickyFooter",
6062
"footerComponent"
6163
];

src/util.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
import { ColumnProps } from "..";
22
import { DEFAULT_HEADER_HEIGHT, DEFAULT_ROW_HEIGHT } from "./constants";
33

4+
/**
5+
* combines multiple classNames conditionally
6+
* @param classes list of potential className strings
7+
* @returns a combined className string
8+
*/
9+
export const cx = (classes: any[]) => {
10+
return classes
11+
.filter(x => !!x && typeof x === "string")
12+
.map((x: string) => x.trim())
13+
.join(" ");
14+
};
15+
416
export const arraysMatch = <T>(arr1: T[], arr2: T[]) => {
517
if (arr1.length !== arr2.length) {
618
return false;

0 commit comments

Comments
 (0)