Skip to content

Commit

Permalink
Merge pull request #50 from askides/feat/alias
Browse files Browse the repository at this point in the history
feat: add support for the 'as' property
  • Loading branch information
askides authored Dec 17, 2024
2 parents b063368 + 9f0d88f commit ef9558b
Show file tree
Hide file tree
Showing 4 changed files with 192 additions and 93 deletions.
6 changes: 6 additions & 0 deletions libs/react-plock/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,11 @@
},
"peerDependencies": {
"react": "^18.2.0"
},
"devDependencies": {
"@testing-library/dom": "^10.4.0",
"@testing-library/react": "^16.1.0",
"@types/react": "^19.0.1",
"@types/react-dom": "^19.0.2"
}
}
60 changes: 60 additions & 0 deletions libs/react-plock/src/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { describe, it, expect } from 'vitest';
import { createChunks, createDataColumns } from '.';
import { render } from '@testing-library/react';
import { Masonry } from '.';

describe('Plock', () => {
it('should create chunks', () => {
Expand Down Expand Up @@ -76,3 +78,61 @@ describe('Plock', () => {
]);
});
});

describe('Integration Tests', () => {
it('should render with different HTML elements using "as" prop', () => {
const items = [1, 2, 3];
const config = { columns: 3, gap: 10 };

// Test with 'section' element
const { container: sectionContainer } = render(
<Masonry
items={items}
render={(item) => <div key={item}>{item}</div>}
config={config}
as="section"
/>
);

// Test with 'article' element
const { container: articleContainer } = render(
<Masonry
items={items}
render={(item) => <div key={item}>{item}</div>}
config={config}
as="article"
/>
);

expect(sectionContainer.querySelector('section')).toBeTruthy();
expect(articleContainer.querySelector('article')).toBeTruthy();
});

it('should render with custom React component using "as" prop', () => {
const CustomComponent = ({
children,
className,
}: {
children: React.ReactNode;
className?: string;
}) => <div className={`custom-wrapper ${className || ''}`}>{children}</div>;

const items = [1, 2, 3];
const config = { columns: 3, gap: 10 };

const { container } = render(
<Masonry
items={items}
render={(item) => <div key={item}>{item}</div>}
config={config}
as={CustomComponent}
className="test-class"
/>
);

const customElement = container.querySelector('.custom-wrapper');

expect(customElement).toBeTruthy();
expect(customElement?.classList.contains('test-class')).toBeTruthy();
});
});
22 changes: 12 additions & 10 deletions libs/react-plock/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react";
import React, { useEffect, useState } from 'react';

export function useMediaValues(
medias: number[] | undefined,
Expand Down Expand Up @@ -36,27 +36,28 @@ export function useMediaValues(

// Apply Listeners
for (const mediaQuery of mediaQueries) {
mediaQuery.addEventListener("change", onSizeChange);
mediaQuery.addEventListener('change', onSizeChange);
}

return () => {
for (const mediaQuery of mediaQueries) {
mediaQuery.removeEventListener("change", onSizeChange);
mediaQuery.removeEventListener('change', onSizeChange);
}
};
}, [values.columns, values.gap]);

return values;
}

export type MasonryProps<T> = React.ComponentPropsWithoutRef<"div"> & {
export type MasonryProps<T> = React.ComponentPropsWithoutRef<'div'> & {
items: T[];
render: (item: T, idx: number) => React.ReactNode;
config: {
columns: number | number[];
gap: number | number[];
media?: number[];
};
as?: React.ElementType;
};

export function createSafeArray(data: number | number[]) {
Expand All @@ -67,6 +68,7 @@ export function Masonry<T>({
items = [],
render,
config,
as: Component = 'div',
...rest
}: MasonryProps<T>) {
const { columns, gap } = useMediaValues(
Expand All @@ -81,11 +83,11 @@ export function Masonry<T>({
const dataColumns = createDataColumns<T>(chunks, columns);

return (
<div
<Component
{...rest}
style={{
display: "grid",
alignItems: "start",
display: 'grid',
alignItems: 'start',
gridColumnGap: gap,
gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,
}}
Expand All @@ -95,7 +97,7 @@ export function Masonry<T>({
{column.map((item, idx) => render(item, idx))}
</MasonryRow>
))}
</div>
</Component>
);
}

Expand All @@ -109,9 +111,9 @@ export function MasonryRow({
return (
<div
style={{
display: "grid",
display: 'grid',
rowGap: gap,
gridTemplateColumns: "minmax(0, 1fr)",
gridTemplateColumns: 'minmax(0, 1fr)',
}}
>
{children}
Expand Down
Loading

0 comments on commit ef9558b

Please sign in to comment.