@emmgeede/gridselect

中文文档
1.2.0发布于 2026/11/08MITTypeScriptES Module零依赖构建来源已验证近 30 天下载 3789

Dependency-free select component: visible items for short lists, a searchable grid for long ones.

原始使用文档
文档目录10 节
  1. Contents
  2. Installation
  3. Usage
  4. Reacting to changes
  5. Several at once
  6. Documentation
  7. Features
  8. Browser support
  9. Development
  10. License

GridSelect logo: four rounded squares in shades of sky blue

GridSelect

npm version CI Accessibility Bundle size License: MIT

A dependency-free JavaScript component for picking from a list of choices. You write a plain radio group, checkbox group or <select>, wrap it, and GridSelect does the rest. Short lists stay visible as items. Longer lists switch to a compact field that opens a panel with a search input and a multi-column grid, fully keyboard accessible. Typing filters the items, or highlights matches in place, and digits pick an entry directly.

Your markup stays native, so forms submit, reset and validate as usual, and everything still works without JavaScript.

Try the demo

A currency field with its panel open. The search input contains 'dollar' and six matching currencies are shown as numbered items in a three-column grid, the first one outlined as the cursor.

Long list, filter mode (default). The field opened a panel with 40 currencies. Typing "dollar" hides everything else and renumbers the six matches 1 to 6. The outlined item is the cursor: Enter, a click or its digit picks it.

A short list of four shipping options shown as rounded items with digit badges 1 to 4, the first one selected.

Short list. Up to 10 entries stay visible as items. They are native radio buttons underneath; arrow keys move between them and the digits 1 to 4 pick one directly.

Highlight mode: all currencies stay in place, the two krone entries are shown in blue, the others dimmed, the cursor is on Norwegian krone, digit badges switch to S1, S2 for the second tier.

Long list, highlight mode (data-search="highlight"). The same list searched for "krone". Nothing is hidden on purpose: every entry keeps its place, so people who use the list daily can rely on positions. The matches (Danish and Norwegian krone) are marked in blue, the cursor jumps to the first match, all other entries are dimmed. Entries 11 to 20 are picked with Shift and a digit (S1 to S0).

Status: version 1.2.0, stable. Published on npm as @emmgeede/gridselect, because npm treats the plain name gridselect as too similar to an older package. Versions follow Semantic Versioning. See Features for what works today and CHANGELOG.md for what changed.

Contents

Installation

npm install @emmgeede/gridselect
import { gridselect } from "@emmgeede/gridselect";
import "@emmgeede/gridselect/gridselect.css"; // optional

Without a bundler, from a CDN (window.gridselect):

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@emmgeede/gridselect@1/src/gridselect.css">
<script src="https://cdn.jsdelivr.net/npm/@emmgeede/gridselect@1/dist/gridselect.min.js"></script>
<script>
  document.querySelectorAll("[data-gridselect]").forEach((el) => gridselect(el));
</script>

Prefer HTML only? Use the custom element, see <grid-select>:

<script src="https://cdn.jsdelivr.net/npm/@emmgeede/gridselect@1/dist/gridselect-element.min.js"></script>

Usage

<fieldset data-gridselect>
  <legend>Currency</legend>
  <label><input type="radio" name="cur" value="EUR" checked> Euro</label>
  <label><input type="radio" name="cur" value="CHF"> Swiss franc</label>
</fieldset>
import { gridselect } from "@emmgeede/gridselect";

const gs = gridselect(document.querySelector("[data-gridselect]"));
gs.value; // "EUR"
gs.value = "CHF"; // checks the CHF radio, fires no event

Reacting to changes

GridSelect keeps your inputs as the source of truth. Whenever the user picks something, by clicking an input, using the keyboard or choosing an item in the panel, GridSelect sets checked on the native input and the browser's own input and change events fire on it. Both bubble, so one listener on the wrapper covers the whole group:

const wrapper = document.querySelector("[data-gridselect]");
const gs = gridselect(wrapper);

wrapper.addEventListener("change", (event) => {
  console.log(event.target.value); // the input that changed, e.g. "CHF"
  // the whole selection: "CHF", or ["a", "c"] for checkboxes
  console.log(gs.value);
});

There is no custom event to learn: code that listens to change or input with addEventListener keeps working unchanged. React is the exception for picks inside the panel, because React's onChange on radios listens to clicks, not to change. In React, attach a native listener to the wrapper (via a ref) until the planned framework wrappers exist. Setting gs.value from code fires no event, just like setting checked yourself, and a form submit always sends the current selection.

Several at once

document.querySelectorAll("[data-gridselect]").forEach((el) => gridselect(el));

Use forEach((el) => gridselect(el)), not forEach(gridselect): the second form passes the index as a second argument, which will be read as options in later versions.

A <fieldset> with a <legend> is the recommended wrapper, it gives screen readers the group name. Any element works, data-gridselect is only a convention for selecting wrappers and for the stylesheet.

Documentation

The full documentation, with a live example on every page, is at gridselect.im/docs.

Features

FeatureStatus
Radio and checkbox groups, value, destroy(), TypeScript typesavailable
Grid panel above a configurable threshold (default 10), grid or list layoutavailable
Search modes filter (default) and highlightavailable
Digit shortcuts with configurable modifier tiersavailable
<select> as sourceavailable
Optional stylesheet with CSS variables, light and darkavailable
npm release and demo pageavailable
Multiple choice in the grid panel, <select multiple>available
Entries from a JS array, setItems()available
<grid-select> custom elementavailable
Fuzzy matchingavailable
Auto column width and flow layoutavailable
Group headings (<optgroup>, groups in items)available
Pinned and recent entriesavailable
Upper limit for multiple choice (max)available
Descriptions (a second line per entry)available
Panel opens where there is room, up to the window edgeavailable
Panel in the full window widthavailable
<grid-select> as a form control (validity, reset, FormData)available
Entries from a server (load)available
Themes: showcase, high contrast, compact, open for contributionsavailable
React and Vue wrappersavailable

Browser support

Current evergreen browsers (Chrome, Edge, Firefox, Safari).

Development

npm install
npm test             # unit tests (Vitest + jsdom), type check, package contents
npm run test:e2e     # browser tests (Playwright, Chromium) incl. axe-core checks
npm run build        # dist/gridselect.d.ts and dist/gridselect.min.js
npm run screenshots  # README images and animations in assets/, from the demo page (needs ImageMagick)
npm run playground   # http://localhost:5173/playground/ (tests) and /demo/
node scripts/pr-check.js  # the contribution rules CI checks on pull requests

Contributing: read AGENTS.md (rules for people and AI agents, with a contributing skill for Claude Code) and, for themes, CONTRIBUTING.md.

Releases: pushing a version tag (vX.Y.Z, matching package.json) runs the Publish workflow, which tests, builds and publishes to npm with provenance.

The playground loads src/gridselect.js directly and shows every variant: short and long radio groups, checkboxes, both search modes, the list layout, a form with required, disabled, submit and reset, and a log of the change events. Its styling is provisional until the stylesheet ships.

License

MIT

版本与发布记录

@emmgeede/gridselect 共发布 20 个版本,首次发布于 2026/11/01;过去 12 个月发布了 20 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.2.0latest2026/11/085 天前
1.1.02026/11/0310 天前
1.0.02026/11/0211 天前
0.22.02026/11/0211 天前
0.21.02026/11/0211 天前
0.20.02026/11/0211 天前

关于 @emmgeede/gridselect 的常见问题

@emmgeede/gridselect 是什么?

Dependency-free select component: visible items for short lists, a searchable grid for long ones.

如何安装 @emmgeede/gridselect?

在项目目录运行 npm install @emmgeede/gridselect,或使用 pnpm add / yarn add / bun add。

@emmgeede/gridselect 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@emmgeede/gridselect 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@emmgeede/gridselect 可以商用吗?

@emmgeede/gridselect 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@emmgeede/gridselect 的下载量有多少?

根据 npm 官方下载统计,@emmgeede/gridselect 在 2026/10/14 – 2026/11/12 这 30 天内被下载 3,789 次,日均约 126 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@emmgeede/gridselect 还在维护吗?

最新版本 1.2.0 发布于 2026/11/08(5 天前);至今共发布 20 个版本,其中过去 12 个月发布了 20 个;首次发布于 2026/11/01。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。