Skip to content

Commit

Permalink
Support Array syntax for breakpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
sibiraj-s committed Oct 2, 2023
1 parent c826724 commit 4e6c69c
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 7 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,23 @@ const ResponsiveColumnsMasonry = () => {
export default ResponsiveColumnsMasonry;
```

or use the array syntax

```js
<Masonry columns={[1, undefined, undefined, 3]} />
```

this will be converted to

```json
{
"640": 1,
"1280": 3
}
```

The array's order corresponds to the default breakpoints, which are `640, 786, 1024, 1280, 1536`.

### Column Props

The `columnProps` prop allows you to apply additional props to the container of each column. Here's an example:
Expand Down
29 changes: 26 additions & 3 deletions src/breakpoints.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,30 @@
import { BreakPoints } from './types';
import { BreakPointSpec, BreakPoints, BreakPointsArray } from './types';

const findBreakpoint = (breakpoints: BreakPoints, windowWidth: number): number => {
const sortedBreakPoints = Object.keys(breakpoints)
const defaultBreakpoints = [640, 786, 1024, 1280, 1536];

const arrayToBreakpoints = (breakPoints: BreakPointsArray): BreakPoints => {
return breakPoints.reduce((obj, bpValue, bpIndex) => {
if (typeof bpValue !== 'number') {
return obj;
}

return {
...obj,
...{ [defaultBreakpoints[bpIndex]]: bpValue },
};
}, {});
};

export const normalizeBreakPoints = (breakPoints: BreakPointSpec): BreakPoints => {
if (!Array.isArray(breakPoints)) {
return breakPoints;
}

return arrayToBreakpoints(breakPoints);
};

const findBreakpoint = (breakpoints: BreakPointSpec, windowWidth: number): number => {
const sortedBreakPoints = Object.keys(normalizeBreakPoints(breakpoints))
.map(Number)
.sort((a, b) => a - b);

Expand Down
7 changes: 5 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { ComponentPropsWithRef, ComponentPropsWithoutRef, ElementType, PropsWithChildren } from 'react';

export type BreakPoints = Record<number, number>;
export type Columns = number | BreakPoints;
export type BreakPoints = Record<number, number> | Array<number | undefined>;
export type BreakPointsArray = Array<number | undefined>;

export type BreakPointSpec = BreakPoints | BreakPointsArray;
export type Columns = number | BreakPointSpec;

type AsProp<T extends ElementType> = {
as?: T;
Expand Down
2 changes: 1 addition & 1 deletion test/Masonry.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ describe('Masonry: Responsive Columns', () => {
const breakpointSpec = Object.entries(breakpoints).map(([key, value]) => [value <= 1 ? 1 : value - 1, Number(key)]);
const items = createItems(10);

it.each(breakpointSpec)('should render %i columns with breakpoint %1', (noOfColumns, windowWidth) => {
it.each(breakpointSpec)('should render %i columns with breakpoint %i', (noOfColumns, windowWidth) => {
window.innerWidth = windowWidth;

const { container } = render(
Expand Down
22 changes: 21 additions & 1 deletion test/breakpoints.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, expect, it } from 'vitest';

import findBreakpoint from '../src/breakpoints';
import findBreakpoint, { normalizeBreakPoints } from '../src/breakpoints';

const specs = [
[640, 700],
Expand All @@ -17,4 +17,24 @@ describe('BreakPoints', () => {
it.each(specs)('should return breakpoint `%i` for window width `%i` correctly', (expectedBp, windowWidth) => {
expect(findBreakpoint(breakpoints, windowWidth)).toBe(expectedBp);
});

it('should return object breakpoints as is', () => {
expect(normalizeBreakPoints(breakpoints)).toBe(breakpoints);
});

it('should map array of breakpoints correctly', () => {
expect(normalizeBreakPoints([1, 2, 3, 4, 5])).toMatchObject({
640: 1,
786: 2,
1024: 3,
1280: 4,
1536: 5,
});

expect(normalizeBreakPoints([1, undefined, 3, undefined, 5])).toMatchObject({
640: 1,
1024: 3,
1536: 5,
});
});
});

0 comments on commit 4e6c69c

Please sign in to comment.