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

xcn-waterfall

v0.9.12

Published

A simple react virtual waterfall component

Readme

XCN Virtual Waterfall

React TypeScript

一个简单的定宽不定高虚拟列表瀑布流组件,使用react + ts编写,适用于react项目

example

Feature

  • [x] 支持虚拟列表
  • [x] 自定义列数
  • [x] 响应式
  • [x] 支持自定义底部元素
  • [x] 支持指定挂载滚动监听的容器
  • [x] 支持使用钩子动态更改单个项目渲染
  • [x] 支持使用钩子触发重新布局
  • [ ] (待开发)根据宽度动态调整开关,适合停止滚动,宽度归0的场景

Usage

1. Install

npm install xcn-waterfall

2. Import

import {useXCNWaterfallItem, XCNWaterfall} from "xcn-waterfall";

3. Use

父组件使用示例

// src/example/responsiveCols.tsx

function ResponsiveCols() {
  // 这里随机生成一些盒子
  const [data, setData] = useState(
    generateRandomObjects().map(item => {
      const id = generateRandomId()

      return {
        id: id,
        height: item.height,
        width: item.width,
        content: () => (
          <Comp
            name={id}
            style={{
              position: 'absolute', left: 0, top: 0, right: 0, bottom: 0,
              background: item.color
            }}
          >
          </Comp>
        )
      } as WaterfallItems // 这个类型定义了每个item的必要参数,包括id,height,width,content
    })
  )
  
  // 这里是处理 onRequestBottomMore 事件,当请求3次后,返回空[]表示没有更多数据了
  const count = useRef(0)
  const handleRequestMore = async () => {
    count.current++
    let newData: WaterfallItems[] = []

    if (count.current < 3) {
      newData = generateRandomObjects().map(item => {
        const id = generateRandomId()
        return {
          id: id,
          height: item.height,
          width: item.width,
          content: () => (
            <Comp
              name={id}
              style={{
                position: 'absolute', left: 0, top: 0, right: 0, bottom: 0,
                background: item.color
              }}
            />
          )
        }
      })
    } else {
      newData = [];
    }

    // 延时 1000 ms
    await new Promise(resolve => setTimeout(resolve, 1000))

    return newData as WaterfallItems[]
  }

  return (
    <>
      <XCNWaterfall
        data={data}
        // 响应式列数,指定在不同屏幕下的列数
        columnsGroup={{
          xs: 1,
          sm: 2,
          md: 3,
          lg: 4,
        }}
        // 容器滚动监听的ref,可选,默认自动生成100%高度的容器包裹自身滚动
        // scrollContainerRef={scrollRef}
        onRequestBottomMore={handleRequestMore}
        // 底部元素渲染函数,可选
        bottomCompRenderFn={(reqCount: number, isLoading: boolean, isFinished: boolean) => (
          <h4 style={{
            color: 'yellow',
            textAlign: 'center'
          }}>waterfall bottom | reqCount {reqCount} | isLoading {`${isLoading}`} | isFinished {`${isFinished}`}</h4>
        )}
        // 容器样式,可选
        style={{
          width: '80vw',
          height: '80vh'
        }}
      />
    </>
  )
}

子组件使用示例

// src/example/comp.tsx
// 自定义的卡片
export function Comp(props: any) {

  // 通过 useXCNWaterfallItem 获取到当前卡片的 item 数据,并修改并重新渲染该卡片
  const {
    item, updateItem,
    initState, computedPosition, computedItemsInView, setItemsToRender
  } = useXCNWaterfallItem(props.name)

  /**
   * update new width and height for box
   * */
  const updateNewBox = () => {
    updateItem({
      height: Math.floor(Math.random() * (1024 - 512 + 1)) + 512,
      width: Math.floor(Math.random() * (1024 - 512 + 1)) + 512,
    })
    initState()
    computedPosition()
    setItemsToRender(computedItemsInView())
  }

  return (
    <div {...props}>
      {props.name}
      <p>
        use item {item?.count || "none"}
      </p>
      <button onClick={() => {
        if (!item?.count) {
          updateItem({
            count: 1
          })
        } else {
          updateItem({
            count: item.count + 1
          })
        }
      }}>
        +
      </button>
      <button onClick={updateNewBox}>
        set new box
      </button>
    </div>
  )
}

Tips

  • 使用useXCNWaterfallItem钩子动态更改单个项目渲染,比如单个卡片内的计数器
  • 优先使用columnsGroup属性设置列数,如果没有该属性,则使用columns属性,响应式是基于容器宽度而不是window宽度

Full Example

可查看src/example目录

Props

接口参数

License

MIT