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

@composy/grid-core

v0.0.2

Published

High-performance, framework-agnostic grid layout engine

Readme

@composy/grid-core

高性能、框架无关的网格布局引擎,支持拖拽、调整大小、碰撞检测、undo/redo、键盘导航和响应式断点。

安装

pnpm add @composy/grid-core

快速开始

import { createGrid } from '@composy/grid-core'

const grid = createGrid('#container', {
  column: 12,
  cellHeight: 80,
  gap: 10
})

grid.addWidget({ x: 0, y: 0, w: 4, h: 2, content: '<div>Widget 1</div>' })
grid.addWidget({ x: 4, y: 0, w: 4, h: 2, content: '<div>Widget 2</div>' })

核心 API

createGrid / Grid 类

| 方法 | 说明 | | --------------------------- | --------------- | | addWidget(data) | 添加网格项 | | addWidgets(items) | 批量添加 | | removeWidget(id) | 移除指定项 | | removeAll() | 移除全部 | | getWidget(id) | 获取指定项 | | getWidgets() | 获取所有项 | | updateWidget(id, updates) | 更新项属性 | | moveWidget(id, x, y) | 移动项位置 | | resizeWidget(id, w, h) | 调整项大小 | | load(items) | 加载布局 | | save() | 保存当前布局 | | compact() | 自动压缩 | | enable() / disable() | 启用/禁用 | | undo() / redo() | 撤销/重做 | | canUndo() / canRedo() | 是否可撤销/重做 | | select(id) / deselect() | 选中/取消选中 | | batchUpdate(fn) | 批量更新 |

事件

dragstart · drag · dragend · resizestart · resize · resizeend · change · added · removed · undo · redo · select · deselect · breakpoint · init · destroy · enable · disable · ready · compact

类名规范

所有运行时 class 使用 ldesign-grid 前缀,遵循 BEM 规范:

  • 块级:ldesign-grid、ldesign-grid__container
  • 元素:ldesign-grid__item、ldesign-grid__item-content、ldesign-grid__item-inner、ldesign-grid__placeholder
  • 修饰符:ldesign-grid--disabled、ldesign-grid--dragging、ldesign-grid--resizing、ldesign-grid--static、ldesign-grid--dark、ldesign-grid--dragover、ldesign-grid--drop-in

CSS 变量

所有样式通过 --ldesign-grid-* CSS 变量控制,颜色默认引用 packages/color 的 --ld-* 变量,尺寸默认引用 packages/size 的 --ld-* 变量。

:root {
  --ldesign-grid-background-color: var(--ld-bg-page);
  --ldesign-grid-surface-color: var(--ld-bg-surface);
  --ldesign-grid-text-color: var(--ld-text-primary);
  --ldesign-grid-border-color: var(--ld-border);
  --ldesign-grid-placeholder-background-color: ...;
  --ldesign-grid-item-border-radius: var(--ld-radius-md);
  --ldesign-grid-gap: var(--ld-spacing-sm);
  /* ... */
}

可通过 options.theme 传入自定义主题变量覆盖默认值。

功能特性

  • 拖拽 & 调整大小:鼠标 + 触摸支持,8 方向调整手柄
  • 碰撞检测:push / swap / none 模式
  • 自动压缩:紧凑布局算法
  • undo/redo:完整历史栈,可配置最大深度
  • 键盘导航:Arrow/Tab/Delete/Escape 键操控
  • 响应式断点:按 viewport 宽度自动切换列数/间距
  • 外部拖入:支持从外部元素拖入网格
  • 主题化:CSS 变量 + color/size token 桥接

构建产物

| 目录 | 格式 | 入口 | | ------- | --------------------- | ------------------------------------ | | dist/ | UMD | dist/index.js、dist/index.min.js | | es/ | ESM (preserveModules) | es/index.js | | esm/ | ESM (preserveModules) | esm/index.js | | lib/ | CJS | lib/index.cjs |

开发

pnpm run type-check   # 类型检查
pnpm run build        # 构建
pnpm run test:run     # 运行测试

增强能力与使用约定

深度更新配置

setOptions 接受 DeepPartial<GridOptions>,嵌套配置会合并而不是整体替换;数组会复制,数值配置会在进入布局引擎前归一化。getOptions 返回独立快照,调用方可以安全地修改返回值而不会改变运行中的网格。

grid.setOptions({
  scroll: { enabled: true, sensitivity: 24 },
  animate: { enabled: true, duration: 180 },
  theme: { itemBorderRadius: 'var(--ld-radius-md)' }
})

const snapshot = grid.getOptions()
snapshot.scroll = { enabled: false }

原子化加载与批量更新

load(items) 会先校验重复 ID、规范化尺寸和位置,再一次性替换布局;输入不合法时不会留下半加载状态。batchUpdate 支持嵌套调用,批量期间延迟布局计算,并在最外层结束时统一刷新。

grid.batchUpdate(() => {
  grid.updateWidget('sales', { w: 6, h: 3 })
  grid.updateWidget('trend', { x: 6, y: 0, w: 6, h: 3 })
})

外部拖入

可以把网格外部的卡片、模板列表或文件入口注册为拖入源。setupExternalDrag 返回清理函数,重复配置前应先调用它;网格销毁时会自动解绑源元素和文档级监听器。

grid.setupExternalDrag({
  source: '.widget-palette [data-widget]',
  defaultSize: { w: 3, h: 2 },
  createItem: el => ({
    id: `widget-${el.dataset.widget}`,
    content: el.dataset.label ?? 'New widget'
  }),
  helper: 'clone',
  removeOnDrop: false
})

stop()

Web Component、SSR 与多文档环境

Web Component 注册过程会检查自定义元素是否已经存在,异步初始化在元素断开后会被忽略。Core 的 DOM 工具、样式表和监听器均以容器所属的 ownerDocument 为边界,适合 iframe、测试文档和 SSR 后再挂载的场景。

事件与可观察性

除原有的 change、拖拽、缩放、撤销和响应式断点事件外,批量操作会保留单项 added、removed 等领域事件,并在批量结束时发出最终布局变更。持久化层建议在最外层 change 事件中调用 save(),不要在每个像素级 drag 事件中写入远端存储。