Skip to content

Commit fa8c2e0

Browse files
authored
Merge pull request #85 from mckervinc/feature/frozen
add ability to freeze columns
2 parents f5d6265 + 330e731 commit fa8c2e0

15 files changed

+194
-41
lines changed

.prettierrc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
{
2-
"printWidth": 100,
3-
"arrowParens": "avoid",
4-
"trailingComma": "none"
2+
"printWidth": 100,
3+
"arrowParens": "avoid",
4+
"trailingComma": "none",
5+
"tabWidth": 2,
6+
"semi": true
57
}

CHANGELOG.md

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

3+
## 0.5.1
4+
5+
_2023-10-04_
6+
7+
### Features
8+
9+
- adds the ability to freeze columns by adding the `frozen` property
10+
311
## 0.5.0
412

513
_2023-10-02_

example/src/App.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { Example8, Source as Example8Code } from "./examples/08-header";
1212
import { Example9, Source as Example9Code } from "./examples/09-scroll";
1313
import { Example10, Source as Example10Code } from "./examples/10-footer";
1414
import { Example11, Source as Example11Code } from "./examples/11-heights";
15+
import { Example12, Source as Example12Code } from "./examples/12-frozen";
1516

1617
const router = createHashRouter([
1718
{
@@ -102,6 +103,14 @@ const router = createHashRouter([
102103
</Page>
103104
)
104105
},
106+
{
107+
path: "/frozen",
108+
element: (
109+
<Page title="Frozen" code={Example12Code}>
110+
<Example12 />
111+
</Page>
112+
)
113+
},
105114
{
106115
path: "/props",
107116
element: (

example/src/ColumnProps.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,16 @@ const data: PropData[] = [
8888
type: "number",
8989
description: "This sets the maximum pixel width of the column exactly"
9090
},
91+
{
92+
prop: "sortable",
93+
type: "boolean",
94+
description: "This determines if a column is sortable"
95+
},
96+
{
97+
prop: "frozen",
98+
type: "boolean",
99+
description: "This determines if a column is frozen"
100+
},
91101
{
92102
prop: "expander",
93103
type: "boolean | ExpanderElement",

example/src/Page.tsx

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,20 @@ const Content = styled.div`
2121
box-shadow: 0 2px 8px #bbb;
2222
`;
2323

24+
const BaseSegment = styled(Segment)`
25+
flex-grow: 1;
26+
`;
27+
2428
const Title = ({ title }: { title: string }) => (
2529
<Container>
2630
<Header size="huge">{title}</Header>
2731
</Container>
2832
);
2933

3034
const Wrapper = ({ children }: { children: React.ReactNode }) => (
31-
<Segment basic>
35+
<BaseSegment basic>
3236
<Content>{children}</Content>
33-
</Segment>
37+
</BaseSegment>
3438
);
3539

3640
const Application = styled(Sidebar.Pushable)`
@@ -45,12 +49,21 @@ const PageContent = styled(Sidebar.Pusher)`
4549
overflow-y: auto;
4650
}
4751
52+
@media screen and (min-width: 769px) {
53+
display: flex;
54+
flex-direction: column;
55+
}
56+
4857
@media screen and (max-width: 768px) {
4958
width: 100%;
5059
transform: translate3d(0, 0, 0) !important;
5160
}
5261
`;
5362

63+
const SnippetWrapper = styled.div`
64+
flex: 1 1;
65+
`;
66+
5467
const Banner = styled.code`
5568
color: #50f97a;
5669
white-space: pre;
@@ -102,6 +115,9 @@ const LinkContainer = () => (
102115
<Menu.Item as={Link} to="/footer">
103116
Footer
104117
</Menu.Item>
118+
<Menu.Item as={Link} to="/frozen">
119+
Frozen
120+
</Menu.Item>
105121
<Menu.Item as={Link} to="/props">
106122
Table Props
107123
</Menu.Item>
@@ -161,7 +177,11 @@ const Page = ({ title, code, children }: PageProps) => {
161177
<PageContent id="pusher">
162178
{!!title && <Title title={title} />}
163179
<Wrapper>{children}</Wrapper>
164-
{!!code && <Snippet code={code} />}
180+
{!!code && (
181+
<SnippetWrapper>
182+
<Snippet code={code} />
183+
</SnippetWrapper>
184+
)}
165185
</PageContent>
166186
</Application>
167187
);

example/src/Props.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,10 @@ interface ColumnProps<T> {
570570
* Determines whether or not a column is sortable.
571571
*/
572572
sortable?: boolean;
573+
/**
574+
* Determines whether or not the column is frozen during horizontal scrolling.
575+
*/
576+
frozen?: boolean;
573577
/**
574578
* Marks this cell as an expansion cell. The style is pre-determined, and does the
575579
* functionalitty of collapsing/expanding a row.

example/src/examples/01-base.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ interface TestData {
3636
3737
const data: TestData[] = _.range(3000).map(i => ({
3838
id: i + 1,
39-
firstName: faker.name.firstName(),
40-
lastName: faker.name.lastName(),
41-
email: faker.internet.email()
39+
firstName: randFirstName(),
40+
lastName: randLastName(),
41+
email: randEmail()
4242
}));
4343
4444
const columns: ColumnProps<TestData>[] = [

example/src/examples/10-footer.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,13 @@ const Example10 = () => {
107107
) : (
108108
<div style={{ display: "flex" }}>
109109
{columns.map((c, i) => {
110-
const width = `${widths[i]}px`;
110+
const width = widths[i];
111111
const style: React.CSSProperties = {
112112
width,
113113
minWidth: width,
114-
padding: "8px"
114+
padding: "8px",
115+
position: c.frozen ? "sticky" : undefined,
116+
left: c.frozen ? widths.slice(0, i).reduce((pv, c) => pv + c, 0) : undefined
115117
};
116118
return (
117119
<div key={c.key} style={style}>
@@ -296,11 +298,13 @@ const ComplexFooter = ({ stickyFooter }) => {
296298
<Footer>
297299
<div style={{ display: "flex" }}>
298300
{columns.map((c, i) => {
299-
const width = \`\${widths[i]}px\`;
301+
const width = widths[i];
300302
const style: React.CSSProperties = {
301303
width,
302304
minWidth: width,
303-
padding: "8px"
305+
padding: "8px",
306+
position: c.frozen ? "sticky" : undefined,
307+
left: c.frozen ? widths.slice(0, i).reduce((pv, c) => pv + c, 0) : undefined
304308
};
305309
return (
306310
<div key={c.key} style={style}>

example/src/examples/12-frozen.tsx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { ColumnProps, Table } from "react-fluid-table";
2+
import { TestData, testData } from "../data";
3+
4+
const columns: ColumnProps<TestData>[] = [
5+
{
6+
key: "id",
7+
header: "ID",
8+
width: 50,
9+
frozen: true
10+
},
11+
{
12+
key: "firstName",
13+
header: "First",
14+
width: 120,
15+
frozen: true
16+
},
17+
{
18+
key: "lastName",
19+
header: "Last",
20+
width: 120
21+
},
22+
{
23+
key: "email",
24+
header: "Email",
25+
width: 250
26+
}
27+
];
28+
29+
const Example12 = () => <Table data={testData} columns={columns} tableWidth={400} />;
30+
31+
const Source = `
32+
const data = [/* ... */];
33+
34+
const columns: ColumnProps<TestData>[] = [
35+
{ key: "id", header: "ID", width: 50, frozen: true },
36+
{ key: "firstName", header: "First", width: 120, frozen: true },
37+
{ key: "lastName", header: "Last", width: 120 },
38+
{ key: "email", header: "Email", width: 250 }
39+
];
40+
41+
const Example = () => <Table data={data} columns={columns} tableWidth={400} />;
42+
`;
43+
44+
export { Example12, Source };

index.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,10 @@ export interface ColumnProps<T> {
150150
* Determines whether or not a column is sortable.
151151
*/
152152
sortable?: boolean;
153+
/**
154+
* Determines whether or not the column is frozen during horizontal scrolling.
155+
*/
156+
frozen?: boolean;
153157
/**
154158
* Marks this cell as an expansion cell. The style is pre-determined, and does the
155159
* functionalitty of collapsing/expanding a row.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-fluid-table",
3-
"version": "0.5.0",
3+
"version": "0.5.1",
44
"description": "A React table inspired by react-window",
55
"author": "Mckervin Ceme <mckervinc@live.com>",
66
"license": "MIT",
@@ -25,6 +25,7 @@
2525
"npm": ">=5"
2626
},
2727
"scripts": {
28+
"clean": "rm -rf dist",
2829
"build": "rm -rf dist ||: && rollup -c --environment BUILD:production",
2930
"start": "rollup -c -w --environment BUILD:development",
3031
"site:build": "cd example && yarn install && yarn build"

src/Footer.tsx

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,26 @@ import { cx, findTableByUuid } from "./util";
66
interface InnerFooterCellProps<T> {
77
width: number;
88
column: ColumnProps<T>;
9+
prevWidth: number;
910
}
1011

11-
const FooterCell = React.memo(function <T>(props: InnerFooterCellProps<T>) {
12+
const FooterCell = React.memo(function <T>({ prevWidth, ...rest }: InnerFooterCellProps<T>) {
1213
// hooks
1314
const { rows } = useContext(TableContext);
1415

1516
// instance
16-
const { width, column } = props;
17-
const cellWidth = width ? `${width}px` : undefined;
17+
const { width, column } = rest;
1818
const style: React.CSSProperties = {
19-
width: cellWidth,
20-
minWidth: cellWidth,
21-
padding: !column.footer ? 0 : undefined
19+
width: width || undefined,
20+
minWidth: width || undefined,
21+
padding: !column.footer ? 0 : undefined,
22+
left: column.frozen ? prevWidth : undefined
2223
};
2324

2425
const FooterCellComponent = column.footer;
2526
return (
26-
<div className="cell" style={style}>
27-
{!!FooterCellComponent && <FooterCellComponent rows={rows} {...props} />}
27+
<div className={cx(["cell", column.frozen && "frozen"])} style={style}>
28+
{!!FooterCellComponent && <FooterCellComponent rows={rows} {...rest} />}
2829
</div>
2930
);
3031
});
@@ -46,9 +47,8 @@ const Footer = () => {
4647
const ref = useRef<HTMLDivElement>(null);
4748

4849
// constants
49-
const width = pixelWidths.reduce((pv, c) => pv + c, 0);
5050
const style: React.CSSProperties = {
51-
minWidth: stickyFooter ? undefined : `${width}px`,
51+
minWidth: stickyFooter ? undefined : pixelWidths.reduce((pv, c) => pv + c, 0),
5252
...(footerStyle || {})
5353
};
5454

@@ -109,7 +109,12 @@ const Footer = () => {
109109
>
110110
<div className="row-container">
111111
{columns.map((c, i) => (
112-
<FooterCell key={c.key} column={c} width={pixelWidths[i]} />
112+
<FooterCell
113+
key={c.key}
114+
column={c}
115+
width={pixelWidths[i]}
116+
prevWidth={c.frozen ? pixelWidths.slice(0, i).reduce((pv, c) => pv + c, 0) : 0}
117+
/>
113118
))}
114119
</div>
115120
</div>

0 commit comments

Comments
 (0)