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

marquee-selection

v0.0.13

Published

A TypeScript library for creating a marquee selection effect

Downloads

31

Readme

groupjs · DOM 矩形圈选与编组

一个轻量的浏览器侧 DOM 圈选库:支持鼠标拖拽矩形圈选、精度模式(相交/包含/中心点 + 面积阈值/IoU)、多次圈选合并、编组与覆盖层、组框四边/四角拖动实时重算、双击快速成组、组间合并、悬浮高亮,以及结果快照与事件回调。内置组级嵌套关系快照,便于构建“组嵌套查看”之类的 UI。

特性

  • 容器内拖拽矩形圈选(fixed 覆盖层,不受容器 overflow 影响)
  • 精度策略:intersects/contains/center + minOverlapRatio + overlapMetric(element/IoU)
  • 冲突处理:none/leaf/best(避免误选大容器)
  • 多次圈选:replace/add/subtract/toggle/auto(Shift/Alt/Ctrl/⌘)
  • 编组模式:每次拖拽生成一组;组覆盖层可见/隐藏、删除
  • 组覆盖层:四边+四角拖动,拖动过程中实时重算命中
  • 组合并:新建组与其它组相交时,工具条“合并”并选择目标组合并
  • 双击快速成组:以双击元素外框作为选择框直接生成一组
  • 悬浮高亮:hoverHighlight+hoverClass
  • 选择约束:allowIntersectionSelection / allowContainmentSelection / allowUnionSelection 控制是否允许“与已有选择部分交叉”“包含/被包含(父子)”与“新增并集”;当不允许时,拖拽/双击/覆盖层尺寸调整都会以红框提示并取消本次操作
  • 完整快照:单选/编组含 flat 并集、hidden、groupRects、groupNesting(组级嵌套)
  • 事件:onChange、onSelectionEnd;控制器:onSelectionEnd(订阅)与 waitForSelectionEnd(一次性)

安装

可直接拷贝 src/index.ts 使用,或自行打包。

位置注入与 position.js 用法

本项目支持为 HTML 元素自动注入源码位置信息(如行号、列号、起止 offset),便于调试、可视化、AST 映射等高级用例。

1. 生成位置信息注入脚本

运行以下命令,会自动解析 index.html,为每个 DOM 元素生成唯一选择器及其源码位置信息,并输出注入脚本 src/position-injector.js

npm run position

开发/打包:

npm i
npm run dev       # 本地预览 demo(Vite)
npm run build     # 产出 dist(es/umd/types)

快速上手(浏览器)

import enableMarqueeSelection from "/src/index.ts";

const ctrl = enableMarqueeSelection({
  container: document.getElementById("container")!,
  selectable: "*",
  selectionMode: "intersects",
  minOverlapRatio: 0.2,
  overlapMetric: "element",
  conflictStrategy: "best",
  multi: true,
  combineMode: "auto",
  groupMode: true,
  groupOverlayClass: undefined,
  hoverHighlight: true,
  hoverClass: "hovered",
  quickGroupOnDblClick: true,
  // 结果回调(一次完整拖拽/操作结束)
  onSelectionEnd: (snapshot) => {
    console.log("snapshot", snapshot);
  },
});

API

enableMarqueeSelection(options) => controller

options(主要项):

  • container: HTMLElement 必填,圈选容器
  • selectable?: string 默认 'img',可被圈选的选择器
  • selectionMode?: 'intersects' | 'contains' | 'center' 默认 'intersects'
  • minOverlapRatio?: number 相交模式下的最小重叠阈值(0~1)
  • overlapMetric?: 'element' | 'iou' 重叠指标
  • selectedClass?: string 默认 'selected'
  • onChange?: (payload) => void 实时变更(单选/编组)
  • preventAncestorSelection?: boolean 默认 true,避免误选父容器
  • conflictStrategy?: 'none' | 'leaf' | 'best' 父子冲突处理
  • multi?: boolean 多次圈选
  • combineMode?: 'replace' | 'add' | 'subtract' | 'toggle' | 'auto'
  • groupMode?: boolean 开启编组
  • groupOverlayClass?: string 组覆盖层类名(可自定义样式)
  • hoverHighlight?: boolean 悬浮高亮
  • hoverClass?: string 悬浮高亮类
  • onSelectionEnd?: (snapshot) => void 一次交互结束
  • quickGroupOnDblClick?: boolean 双击快速成组
  • quickGroupSelector?: string 双击匹配祖先选择器后再成组
  • allowIntersectionSelection?: boolean 默认 true。若为 false,则只禁止“部分交叉”关系:即新集合与已有集合间存在交集且双方都还有各自独有的元素。
  • allowContainmentSelection?: boolean 默认 true。仅当 allowIntersectionSelection=false 时生效;true 表示仍允许“包含/被包含”关系(A 是 B 的子集或父集),false 表示包含也禁止,仅保留完全不相交或完全相等两种情况。
  • allowUnionSelection?: boolean 默认 true。若为 false,则当已存在选择/组时,禁止新增元素(并集)。
    • toolbarButtons?: { label; title?; className?; onClick?(ctx) }[] 追加自定义工具栏按钮(ctx.label/ctx.title 为可写属性,可在同步或异步回调中赋值以实时更新按钮展示)

controller:

  • destroy(): void 卸载
  • getGroups(): Element[][] 获取所有组
  • clearGroups(): void 清空所有组
  • removeGroup(index: number): boolean 删除指定组
  • setGroupVisibility(index: number, hidden: boolean): boolean 设置组可见
  • toggleGroupVisibility(index: number): boolean 切换可见
  • getSelectionResult(): MarqueeSelectionSnapshot 获取当前快照
  • setToolbarButtonProps(groupIndex: number, buttonIndex: number, props: { label?: string; title?: string }): boolean 直接修改指定组的自定义工具栏按钮文案(label/title 任意可选)
  • onSelectionEnd(handler): () => void 订阅下一次结束
  • waitForSelectionEnd(): Promise 等待下一次结束
  • getGroupNesting(): { parents: (number|null)[]; children: number[][]; roots: number[] } | null 获取组级嵌套(groupMode 下有效)

快照结构 MarqueeSelectionSnapshot

  • 单选:{ type: 'single'; selected: Element[] }
  • 编组:
    {
    	type: 'groups'
    	groups: Element[][]     // 每组元素集
    	flat: Element[]         // 全部并集
    	hidden: boolean[]       // 各组隐藏状态
    	groupRects: ({ left:number; top:number; width:number; height:number } | null)[] // 各组外接框
    	groupNesting: {
    		parents: (number|null)[]
    		children: number[][]
    		roots: number[]
    	}
    }

groupNesting 说明:依据组外接矩形完全包含关系,给每个组选取“面积最小的包含者”作为其最近父组,从而形成多层嵌套树(roots 为无父组)。这使得你能在 UI 中构建“组嵌套查看”。

高级能力

  • 组覆盖层拖动:

    • 覆盖层四边/四角(nw/ne/sw/se)句柄拖动,实时更新圈选命中与 DOM 选中态;
    • 鼠标松开后固定结果,并触发 onSelectionEnd。
    • 当禁用交叉/包含/并集时(allowIntersectionSelection / allowContainmentSelection / allowUnionSelection),若本次调整会产生被禁止的部分交叉、包含或新增元素,将以红色边框与浅红底提示,并在松开时取消本次调整。
  • 组合并:

    • 当新建组与其他组外接框相交时,工具条显示“合并”;
    • 点击弹出合并面板,勾选要合并的组后确认;
    • 被合并组删除,当前组元素替换为并集,自动刷新覆盖层与快照。
  • 双击快速成组:

    • 开启 quickGroupOnDblClick 后,双击元素(或其 closest(quickGroupSelector) 祖先)会以该元素外框作为选择框迅速生成一组。
    • 亦会遵守 allowIntersectionSelection / allowContainmentSelection / allowUnionSelection;违规则提示并取消。
  • 自定义工具栏按钮:

    • 通过 options.toolbarButtons 追加按钮到每个组的工具栏;
    • onClick(ctx) 回调提供:
      • ctx.index 当前组索引
      • ctx.group 当前组元素数组
      • ctx.controller 控制器实例
      • ctx.getSnapshot() 获取最新快照
      • ctx.refresh() 触发重绘覆盖层并广播 onSelectionEnd
      • ctx.label / ctx.title 支持在回调中赋值(含异步场景),立即刷新按钮文本与 title;ctx.buttonEl 可用于附加自定义 DOM
    • 若需在回调外(例如异步完成后、或来自其它交互)修改按钮文案,可调用 controller.setToolbarButtonProps(groupIndex, buttonIndex, { label?: string, title?: string }),该方法会持久更新对应组的按钮状态并刷新 UI。
    • 示例:
    enableMarqueeSelection({
      // ...existing options...
      toolbarButtons: [
        {
          label: "导出",
          title: "导出该组元素信息",
          onClick: ({ index, group, getSnapshot }) => {
            const ids = group.map((el) => (el as HTMLElement).id).join(",");
            console.log("组", index + 1, "元素ID:", ids);
          },
        },
        {
          label: "反选本组",
          onClick: ({ index, controller, getSnapshot, refresh }) => {
            const snap = getSnapshot();
            if (snap.type !== "groups") return;
            // 简单示例:把该组设置为隐藏/显示切换
            controller.toggleGroupVisibility(index);
            refresh();
          },
        },
      ],
    });
  • 悬浮高亮:

    • hoverHighlight + hoverClass,非拖拽时鼠标悬浮可提示可圈选元素。

Demo

  • 项目内置 index.html 演示:右上角浮层面板展示结果;
  • 面板支持“平铺查看 / 组嵌套查看”切换;嵌套查看直接使用库返回的 snapshot.groupNesting

开发

npm run dev       # 起 Vite 开发服务
npm run build     # 产出 dist(es/umd/types)

License

MIT