Skip to content

Commit 538fb68

Browse files
committed
feat(preact): introduce @masonry-grid/preact package
1 parent bd67ee7 commit 538fb68

File tree

18 files changed

+1444
-0
lines changed

18 files changed

+1444
-0
lines changed

packages/preact/.size-limit.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[
2+
{
3+
"name": "All publics",
4+
"path": "dist/index.js",
5+
"import": "*",
6+
"limit": "1.94 kB"
7+
},
8+
{
9+
"name": "BalancedMasonryGrid",
10+
"path": "dist/index.js",
11+
"import": "{ BalancedMasonryGrid, Frame }",
12+
"limit": "1.72 kB"
13+
}
14+
]

packages/preact/.storybook/main.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import type { StorybookConfig } from '@storybook/preact-vite'
2+
3+
const config: StorybookConfig = {
4+
framework: '@storybook/preact-vite',
5+
stories: ['../src/**/*.stories.tsx']
6+
}
7+
8+
export default config
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import type { Preview } from '@storybook/preact'
2+
3+
const preview: Preview = {
4+
parameters: {
5+
actions: {
6+
argTypesRegex: '^on[A-Z].*'
7+
},
8+
controls: {
9+
matchers: {
10+
color: /(background|color)$/i,
11+
date: /Date$/i
12+
}
13+
}
14+
}
15+
}
16+
17+
export default preview

packages/preact/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2016 - present, TrigenSoftware
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

packages/preact/README.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Preact Masonry Grid
2+
3+
<img align="right" width="150" height="150" alt="Logo" src="../../website/src/assets/logo.svg">
4+
5+
[![ESM-only package][package]][package-url]
6+
[![NPM version][npm]][npm-url]
7+
[![Install size][size]][size-url]
8+
[![Build status][build]][build-url]
9+
[![Coverage status][coverage]][coverage-url]
10+
11+
[package]: https://img.shields.io/badge/package-ESM--only-ffe536.svg
12+
[package-url]: https://nodejs.org/api/esm.html
13+
14+
[npm]: https://img.shields.io/npm/v/%40masonry-grid%2Fpreact.svg
15+
[npm-url]: https://npmjs.com/package/@masonry-grid/preact
16+
17+
[size]: https://deno.bundlejs.com/badge?q=%40masonry-grid%2Fpreact
18+
[size-url]: https://bundlejs.com/?q=%40masonry-grid%2Fpreact
19+
20+
[build]: https://img.shields.io/github/actions/workflow/status/TrigenSoftware/masonry-grid/tests.yml?branch=main
21+
[build-url]: https://github.com/TrigenSoftware/masonry-grid/actions
22+
23+
[coverage]: https://img.shields.io/codecov/c/github/TrigenSoftware/masonry-grid.svg
24+
[coverage-url]: https://app.codecov.io/gh/TrigenSoftware/masonry-grid
25+
26+
A fast, lightweight, and responsive masonry grid layout library for Preact.
27+
28+
- 🪶 **Lightweight**. ~1.7 kB (minified and brotlied). Zero dependencies except Preact.
29+
-**Fast**. Built on top of [@masonry-grid/vanilla](../vanilla) with optimized reflow algorithms.
30+
- 📱 **Responsive**. Automatically adapts to container size changes using [ResizeObserver](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver).
31+
- 📘 **TypeScript**-first.
32+
33+
_Read the docs and explore examples at [masonry-grid.js.org](https://masonry-grid.js.org)_
34+
35+
```tsx
36+
import { BalancedMasonryGrid, Frame } from '@masonry-grid/preact'
37+
38+
function Gallery() {
39+
return (
40+
<BalancedMasonryGrid
41+
frameWidth={200}
42+
gap={10}
43+
>
44+
<Frame width={4} height={3}>
45+
<img src='https://picsum.photos/400/300' alt='Photo 1' />
46+
</Frame>
47+
<Frame width={1} height={1}>
48+
<img src='https://picsum.photos/200/200' alt='Photo 2' />
49+
</Frame>
50+
<Frame width={3} height={4}>
51+
<img src='https://picsum.photos/300/400' alt='Photo 3' />
52+
</Frame>
53+
<Frame width={3} height={4}>
54+
<img src='https://picsum.photos/300/400' alt='Photo 4' />
55+
</Frame>
56+
<Frame width={1} height={1}>
57+
<img src='https://picsum.photos/200/200' alt='Photo 5' />
58+
</Frame>
59+
<Frame width={4} height={3}>
60+
<img src='https://picsum.photos/400/300' alt='Photo 6' />
61+
</Frame>
62+
</BalancedMasonryGrid>
63+
)
64+
}
65+
```
66+
67+
## Install
68+
69+
```bash
70+
pnpm add @masonry-grid/preact
71+
# or
72+
npm i @masonry-grid/preact
73+
# or
74+
yarn add @masonry-grid/preact
75+
```
76+
77+
## Docs
78+
79+
- [Guides](https://masonry-grid.js.org/guides/prerequisites/)
80+
- [API Reference](https://masonry-grid.js.org/api/preact/)
81+
- [Examples](https://masonry-grid.js.org/examples/#preact)

packages/preact/eslint.config.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import moduleConfig from '@trigen/eslint-config/module'
2+
import reactConfig from '@trigen/eslint-config/react'
3+
import tsTypeCheckedConfig from '@trigen/eslint-config/typescript-type-checked'
4+
import testConfig from '@trigen/eslint-config/test'
5+
import storybookConfig from '@trigen/eslint-config/storybook'
6+
import env from '@trigen/eslint-config/env'
7+
import rootConfig from '../../eslint.config.js'
8+
9+
export default [
10+
...rootConfig,
11+
...moduleConfig,
12+
...reactConfig,
13+
...tsTypeCheckedConfig,
14+
...testConfig,
15+
...storybookConfig,
16+
env.node,
17+
{
18+
languageOptions: {
19+
parserOptions: {
20+
projectService: true,
21+
tsconfigRootDir: import.meta.dirname
22+
}
23+
},
24+
rules: {
25+
'consistent-return': 'off'
26+
}
27+
}
28+
]

packages/preact/package.json

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
{
2+
"name": "@masonry-grid/preact",
3+
"type": "module",
4+
"version": "1.0.0",
5+
"description": "A fast, lightweight, and responsive masonry grid layout library for Preact.",
6+
"author": "dangreen",
7+
"license": "MIT",
8+
"homepage": "https://masonry-grid.js.org",
9+
"funding": "https://ko-fi.com/dangreen",
10+
"repository": {
11+
"type": "git",
12+
"url": "https://github.com/TrigenSoftware/masonry-grid.git",
13+
"directory": "packages/preact"
14+
},
15+
"bugs": {
16+
"url": "https://github.com/TrigenSoftware/masonry-grid/issues"
17+
},
18+
"keywords": [
19+
"masonry",
20+
"grid",
21+
"layout",
22+
"masonry-grid",
23+
"responsive",
24+
"fast",
25+
"lightweight",
26+
"preact"
27+
],
28+
"engines": {
29+
"node": ">=16"
30+
},
31+
"sideEffects": false,
32+
"exports": {
33+
"./package.json": "./package.json",
34+
".": "./src/index.tsx"
35+
},
36+
"publishConfig": {
37+
"exports": {
38+
"./package.json": "./package.json",
39+
".": {
40+
"types": "./dist/index.d.ts",
41+
"default": "./dist/index.js"
42+
}
43+
},
44+
"directory": "package",
45+
"linkDirectory": false
46+
},
47+
"files": [
48+
"dist"
49+
],
50+
"scripts": {
51+
"clear:package": "del ./package",
52+
"clear:dist": "del ./dist",
53+
"clear": "del ./package ./dist ./coverage",
54+
"prepublishOnly": "run build clear:package clean-publish",
55+
"postpublish": "pnpm clear:package",
56+
"emitDeclarations": "tsc -p ./tsconfig.build.json --emitDeclarationOnly",
57+
"build:dist": "run -p emitDeclarations [ vite build ]",
58+
"build": "run clear:dist build:dist",
59+
"build:storybook": "storybook build",
60+
"lint": "eslint --flag v10_config_lookup_from_file",
61+
"test:install-deps": "playwright install chromium",
62+
"test:unit": "vitest run --coverage",
63+
"test:unit:watch": "vitest watch",
64+
"test:size": "size-limit",
65+
"test:types": "tsc --noEmit",
66+
"test": "run -p lint test:unit test:types",
67+
"storybook": "storybook dev -p 6006 --no-open"
68+
},
69+
"peerDependencies": {
70+
"preact": "^10.0.0"
71+
},
72+
"dependencies": {
73+
"@masonry-grid/vanilla": "workspace:^"
74+
},
75+
"devDependencies": {
76+
"@preact/preset-vite": "^2.9.3",
77+
"@size-limit/preset-small-lib": "^11.1.2",
78+
"@storybook/preact": "^9.1.16",
79+
"@storybook/preact-vite": "^9.1.16",
80+
"@testing-library/dom": "^10.0.0",
81+
"@testing-library/jest-dom": "^6.5.0",
82+
"@testing-library/preact": "^3.2.4",
83+
"@vitest/browser": "^3.2.4",
84+
"@vitest/coverage-v8": "^3.0.0",
85+
"playwright": "^1.56.0",
86+
"preact": "^10.26.1",
87+
"size-limit": "^11.1.2",
88+
"storybook": "^9.1.16",
89+
"typescript": "^5.3.3",
90+
"vite": "^7.1.11",
91+
"vitest": "^3.0.0"
92+
}
93+
}

packages/preact/src/hook.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import {
2+
useLayoutEffect,
3+
useRef
4+
} from 'preact/hooks'
5+
import type { BaseMasonryGrid } from '@masonry-grid/vanilla'
6+
7+
export interface MansoryGridConstructor {
8+
new (container: HTMLElement): BaseMasonryGrid
9+
prototype: BaseMasonryGrid
10+
}
11+
12+
export interface MasonryGridHookProps {
13+
/**
14+
* The MasonryGrid constructor to use.
15+
*/
16+
type: MansoryGridConstructor
17+
/**
18+
* If true, the MasonryGrid will not be initialized.
19+
*/
20+
disabled?: boolean
21+
}
22+
23+
/**
24+
* Hook to create a MasonryGrid on a container element ref.
25+
* @param params
26+
* @param params.type - The MasonryGrid constructor to use.
27+
* @param params.disabled - If true, the MasonryGrid will not be initialized.
28+
* @returns A ref to be attached to the container element.
29+
*/
30+
export function useMasonryGrid<T extends HTMLElement = HTMLElement>({
31+
type: MasonryGrid,
32+
disabled = false
33+
}: MasonryGridHookProps) {
34+
const containerRef = useRef<T>(null)
35+
36+
useLayoutEffect(() => {
37+
const container = containerRef.current
38+
39+
if (!container || disabled) {
40+
return
41+
}
42+
43+
const masonryGrid = new MasonryGrid(container)
44+
45+
return () => masonryGrid.destroy()
46+
}, [MasonryGrid, disabled])
47+
48+
return containerRef
49+
}

0 commit comments

Comments
 (0)