npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

universal-waterfall-layout

v1.1.0

Published

A lightweight, cross-framework waterfall layout library.

Readme

Universal Waterfall Layout

English | 中文

一个轻量级、高性能的瀑布流布局库,支持 Vue 3React原生 JS

特性

  • 🚀 框架无关: 核心逻辑使用原生 TypeScript 编写。
  • 轻量级: 零依赖(核心部分)。
  • 🎨 响应式: 自动处理窗口大小调整。
  • 📐 灵活布局: 同时支持 固定列宽(居中布局)和 固定列数(流式宽度)。
  • 🖼 图片加载: 即使图片尺寸动态变化也能保持稳健布局。
  • 💤 懒加载: 内置支持原生图片懒加载。
  • 状态管理: 内置加载中(骨架屏)和空状态支持。
  • 🚀 虚拟列表: 支持万级数据渲染,基于 $O(\log N)$ 算法实现高性能检索。
  • 滚动锚定: 解决动态高度撑开导致的布局跳动,保持丝滑滑动体验。
  • 🔌 可扩展: 易于扩展自定义动画。

安装

npm install universal-waterfall-layout
# or
pnpm add universal-waterfall-layout

Vue 3 使用方法

/vue 子路径导入 Waterfall 组件。

<template>
  <!-- 策略 1: 固定列宽 (居中布局) -->
  <Waterfall 
    :gap="20" 
    :columnWidth="250"
    :loading="isLoading"
    :lazyload="true"
  >
    <div v-for="item in items" class="card">...</div>
    
    <!-- 自定义加载插槽 -->
    <template #loading>
       <div>加载中...</div>
    </template>

    <!-- 自定义空状态插槽 -->
    <template #empty>
       <div>暂无数据</div>
    </template>
  </Waterfall>

  <!-- 策略 2: 固定列数 (流式布局) -->
  <Waterfall :gap="20" :columnCount="3">
    <div v-for="item in items" class="card">...</div>
  </Waterfall>

  <!-- 策略 3: 虚拟列表模式 (万级数据极致性能) -->
  <Waterfall 
    virtual
    :items="massiveData"
    :height="800"
    :gap="20"
    :columnWidth="200"
  >
    <template #item="{ item, index }">
      <div class="card">
         <img :src="item.image" />
         <p>{{ item.title }} - {{ index }}</p>
      </div>
    </template>
  </Waterfall>
</template>

<script setup>
import { Waterfall } from 'universal-waterfall-layout/vue';
import { ref } from 'vue';

const isLoading = ref(false);
const items = [
  { image: '...', title: 'Item 1' },
  // ...
];
</script>

<style scoped>
.card {
  background: #f0f0f0;
  border-radius: 8px;
  overflow: hidden;
  /* 高度将由内容决定 */
}
</style>

Vue 属性 (Props)

| 属性 | 类型 | 默认值 | 描述 | |------|------|---------|-------------| | gap | Number | 10 | 元素之间的间距(像素)。 | | columnWidth | Number | - | 策略 1: 每列的固定宽度。容器将会居中显示。 | | columnCount | Number | - | 策略 2: 固定的列数。宽度是流式的(自适应)。 | | items | Array | [] | 可选:传入数据数组以便在变化时触发重新布局。 | | loading | Boolean | false | 如果为真,显示加载骨架屏。 | | lazyload | Boolean | false | 开启原生图片懒加载。 | | reachBottomDistance | Number | 50 | 触底事件触发阈值(像素)。 | | virtual | Boolean | false | 开启虚拟列表模式(高性能处理大数据量)。 | | height | String \| Number | - | 设置容器高度,开启内部滚动。 | | estimateItemHeight | Number | 300 | 虚拟列表预估高度。 |

Vue 事件 (Events)

| 事件名 | 描述 | |-------|-------------| | scroll-reach-bottom | 当滚动触底时触发。可用于无限滚动加载。 |

Vue 插槽 (Slots)

| 插槽 | 描述 | |------|-------------| | default | 主要内容项(非虚拟模式)。 | | item | 开启虚拟模式后的单项渲染插槽。接受 { item, index } 参数。 | | loading | 加载状态的自定义内容。 | | empty | 空状态的自定义内容。 |

React 使用方法

/react 子路径导入 Waterfall 组件。

import React from 'react';
import { Waterfall } from 'universal-waterfall-layout/react';

const App = () => {
  return (
    // 策略 1: 固定宽度 (居中)
    <Waterfall 
      gap={20} 
      columnWidth={250}
      loading={false}
      lazyload={true}
      loadingComponent={<div>加载中...</div>}
      emptyComponent={<div>暂无数据</div>}
    >
      {children}
    </Waterfall>

    // 策略 2: 固定列数 (流式)
    <Waterfall gap={20} columnCount={3}>
      {children}
    </Waterfall>

    // 策略 3: 虚拟列表模式
    <Waterfall 
      virtual
      items={massiveItems}
      height={800}
      gap={20}
      columnWidth={200}
      renderItem={(item, index) => (
        <div key={index} className="card">
          <img src={item.url} />
          <span>{item.title}</span>
        </div>
      )}
    />
  );
};

React 属性 (Props)

| 属性 | 类型 | 默认值 | 描述 | |------|------|---------|-------------| | gap | number | 10 | 元素之间的间距(像素)。 | | columnWidth | number | - | 每列的固定宽度。 | | columnCount | number | - | 固定的列数。 | | loading | boolean | false | 如果为真,显示加载骨架屏。 | | lazyload | boolean | false | 开启原生图片懒加载。 | | loadingComponent | ReactNode | - | 自定义加载状态组件。 | | emptyComponent | ReactNode | - | 自定义空状态组件。 | | onReachBottom | () => void | - | 滚动触底回调函数。 | | reachBottomDistance | number | 50 | 触发触底事件的距离阈值(像素)。 | | virtual | boolean | false | 是否开启虚拟列表模式。 | | items | any[] | [] | 虚拟模式下必填:完整的数据数组。 | | renderItem | (item, index) => ReactNode | - | 虚拟模式下必填:单项渲染函数。 | | height | string \| number | - | 容器高度,设置此项后开启内部滚动。 | | estimateItemHeight | number | 300 | 虚拟模式下的预估高度。 |

原生 JS / 核心库使用方法

如果你不想使用框架:

import { WaterFallCore } from 'universal-waterfall-layout';

const container = document.getElementById('my-container');
const waterfall = new WaterFallCore({
  container: container,
  gap: 15,
  columnWidth: 220,
  lazyload: true,
  onLayout: () => {
    console.log('布局已更新');
  }
});

// 销毁
waterfall.destroy();

API 选项

| 选项 | 类型 | 默认值 | 描述 | |--------|------|---------|-------------| | container | HTMLElement | 必填 | 容器元素。 | | gap | number | 0 | 间距大小(px)。 | | columnWidth | number | - | 选项 A: 固定列宽。如果设置了此项,columnCount 将被忽略。 | | columnCount | number | - | 选项 B: 固定列数。宽度动态计算。 | | itemSelector | string | 直接子元素 | 这里的 CSS 选择器用于选择子项。 | | lazyload | boolean | false | 开启原生图片懒加载。 | | onLayout | function | - | 布局计算完成后的回调。 | | onReachBottom | function | - | 滚动触底回调函数。 | | reachBottomDistance | number | 50 | 触底阈值(px)。 | | virtual | boolean | false | 是否开启虚拟滚动模式。 | | onRenderChange | (start, end) => void | - | 可见区域范围变化时的回调(仅限虚拟模式)。 | | viewport | HTMLElement \| Window | window | 指定滚动视口容器。 | | estimateItemHeight | number | 300 | 虚拟列表项的预估高度。 | | itemCount | number | 0 | 总数据项数量(虚拟模式必填)。 |

开发

  1. 安装依赖: npm install
  2. 构建库: npm run build