{"_id":"@bowenhuang/react-virtual-masonry","name":"@bowenhuang/react-virtual-masonry","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@bowenhuang/react-virtual-masonry","version":"0.1.0","description":"A virtualized masonry layout component for React.","main":"dist/index.cjs","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"sideEffects":["**/*.css"],"scripts":{"build":"tsup src/index.ts --format esm,cjs --dts --clean","dev":"tsup src/index.ts --format esm,cjs --dts --watch","typecheck":"tsc --noEmit","test":"vitest run","test:watch":"vitest","demo":"vite --config vite.demo.config.ts","demo:build":"vite build --config vite.demo.config.ts"},"keywords":["react","masonry","virtual-list","virtualized","waterfall"],"author":"","license":"MIT","publishConfig":{"access":"public"},"peerDependencies":{"react":">=18"},"devDependencies":{"@testing-library/jest-dom":"^6.6.3","@testing-library/react":"^16.2.0","@types/react-dom":"^18.3.2","@vitejs/plugin-react":"^4.3.4","@types/react":"^18.3.12","jsdom":"^26.0.0","react":"^18.3.1","react-dom":"^18.3.1","tsup":"^8.3.5","typescript":"^5.6.3","vite":"^5.4.10","vitest":"^2.1.4"},"_id":"@bowenhuang/react-virtual-masonry@0.1.0","gitHead":"033ca2222335576f06ef163173c3d8088c1c26bc","_nodeVersion":"22.12.0","_npmVersion":"10.9.0","dist":{"integrity":"sha512-Z0BJMJc1d9u7xwHviBmF/Gfm0b2bKDA8yY6JbavgQdmwnqVcT/ef7nMBgH5s0HsOeppfqhjgG4v8N5ft3UUbcQ==","shasum":"57f5a7b23993a7542ac3e3ae7bb5404d375ec9cc","tarball":"https://registry.npmjs.org/@bowenhuang/react-virtual-masonry/-/react-virtual-masonry-0.1.0.tgz","fileCount":8,"unpackedSize":36970,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD2iu8ZlOB9SFVUB1qp9qAMLANAMP4IA0YyWTv0zpNA2wIhAOAc+ZyVrgXgDEu6+bfuW7DOrmPlHJwM4GPRTxWLgrds"}]},"_npmUser":{"name":"bowenhuang","email":"huang_bx@qq.com"},"directories":{},"maintainers":[{"name":"bowenhuang","email":"huang_bx@qq.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/react-virtual-masonry_0.1.0_1772704131438_0.7960064789573815"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-05T09:48:51.339Z","0.1.0":"2026-03-05T09:48:51.574Z","modified":"2026-03-05T09:48:51.763Z"},"maintainers":[{"name":"bowenhuang","email":"huang_bx@qq.com"}],"description":"A virtualized masonry layout component for React.","keywords":["react","masonry","virtual-list","virtualized","waterfall"],"license":"MIT","readme":"# react-virtual-masonry\n\n[English](./README.md)\n\n一个面向 React 的高性能虚拟瀑布流组件。\n\n适用于「长列表 + 分页追加 + 卡片高度不固定」的场景，重点解决滚动卡顿和布局抖动问题。\n\n## 特性\n\n- 支持虚拟渲染（windowing + overscan）。\n- 支持不等高卡片（基于 `ResizeObserver` 实时测量）。\n- 支持分页追加时的增量布局。\n- 卡片高度变化时优先局部重排，尽量避免全量重排。\n- 快速滑动兜底，降低短暂白屏概率。\n- 同时支持 window 滚动和自定义滚动容器。\n\n## 安装\n\n```bash\nnpm install @bowenhuang/react-virtual-masonry\n```\n\n## 快速使用\n\n```tsx\nimport { VirtualMasonry } from '@bowenhuang/react-virtual-masonry';\n\ntype Item = { id: string; title: string; cover: string };\n\nexport default function Demo({ items }: { items: Item[] }) {\n  return (\n    <VirtualMasonry\n      items={items}\n      column={2}\n      gap={8}\n      overscan={900}\n      estimateHeight={320}\n      getItemKey={(item) => item.id}\n      renderItem={({ item }) => (\n        <article style={{ padding: 12, background: '#fff', borderRadius: 12 }}>\n          <img src={item.cover} alt=\"\" style={{ width: '100%', borderRadius: 8 }} />\n          <h4>{item.title}</h4>\n        </article>\n      )}\n    />\n  );\n}\n```\n\n## API\n\n### `VirtualMasonryProps<T>`\n\n| 参数 | 类型 | 默认值 | 说明 |\n| --- | --- | --- | --- |\n| `items` | `T[]` | - | 列表数据源。 |\n| `column` | `number` | - | 列数。 |\n| `gap` | `number` | `7` | 列间距和卡片间距（px）。 |\n| `overscan` | `number` | `900` | 可视区上下额外渲染距离（px）。 |\n| `estimateHeight` | `number` | `320` | 首次测量前的预估高度（px）。 |\n| `className` | `string` | - | 根容器类名。 |\n| `itemClassName` | `string` | - | 卡片外层类名。 |\n| `getItemKey` | `(item: T, index: number) => string` | - | 稳定且唯一的 key（必填）。 |\n| `getItemId` | `(item: T, index: number) => string \\| undefined` | - | 卡片外层可选 id。 |\n| `renderItem` | `({ item, index }) => ReactNode` | - | 卡片渲染函数（必填）。 |\n| `scrollContainer` | `string \\| HTMLElement \\| null \\| (() => HTMLElement \\| null)` | `'.taro_page' -> window` | 自定义滚动容器。 |\n| `minScrollDelta` | `number` | `8` | 触发可视区更新的最小滚动位移。 |\n\n## 滚动容器示例\n\n使用默认逻辑（优先 `.taro_page`，否则 window）：\n\n```tsx\n<VirtualMasonry {...props} />\n```\n\n使用选择器：\n\n```tsx\n<VirtualMasonry {...props} scrollContainer=\".my-scroll-container\" />\n```\n\n使用 DOM 节点：\n\n```tsx\n<VirtualMasonry {...props} scrollContainer={containerRef.current} />\n```\n\n使用函数返回节点：\n\n```tsx\n<VirtualMasonry {...props} scrollContainer={() => document.getElementById('scroll-root')} />\n```\n\n## 性能建议\n\n- `getItemKey` 必须稳定且唯一（推荐使用后端 id）。\n- `estimateHeight` 尽量贴近卡片平均高度，减少首屏重排。\n- 根据场景调优 `overscan`：\n  - 大：快速滑动更稳，但 DOM 更多；\n  - 小：DOM 更少，但可能更容易出现“补渲染感”。\n- 复杂卡片建议配合 `React.memo`。\n- 避免在 `renderItem` 中执行高开销计算。\n\n## 本地构建（贡献者）\n\n```bash\nnpm install\nnpm run typecheck\nnpm run test\nnpm run build\n```\n\n## 运行 Demo\n\n```bash\nnpm install\nnpm run demo\n```\n\n构建 Demo 静态资源：\n\n```bash\nnpm run demo:build\n```\n\n## 运行测试\n\n```bash\nnpm run test\n```\n\n监听模式：\n\n```bash\nnpm run test:watch\n```\n\n## License\n\nMIT\n","readmeFilename":"README.zh-CN.md","_rev":"1-75be4e8ccd79810f043cd7a32f384fee"}