本文へ移動
cccskills
無料GitHub で公開

handsontable-dev

Use for ANY work touching the `handsontable/` core package: fixing bugs, adding features, modifying TypeScript types, removing as-casts, writing or debugging plugins, editors, renderers, validators, cell types, hooks, shortcuts, selection, helpers, index translations, or i18n. Also use for how-to questions about core internals (plugin lifecycle, coordinate systems, hook registration, TypeScript conventions). Triggers on file paths under `handsontable/src/` (excluding `3rdparty/walkontable/` which has its own skill), or when the user describes a symptom in the core grid without naming a file. This is the primary entry point for all core Handsontable development, when in doubt, load it.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md12.7 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Handsontable Core Development

Dispatch table

Load handsontable-code-review (architecture dimension) first for every change, then the task-specific specialist. It is the design lens (SOLID, Law of Demeter, plugin decoupling, breaking changes); the task skill is the implementation guide.

TaskSkill
Create / modify a pluginhandsontable-plugin-dev
Create / modify an editorhandsontable-editor-dev
Create / modify a rendererhandsontable-renderer-dev
Create / modify a validatorhandsontable-validator-dev
Create / modify a cell typehandsontable-celltype-dev
Write a new E2E testhandsontable-playwright-e2e (Playwright, tests/e2e/)
Maintain a legacy E2E test (*.spec.js, frozen)handsontable-e2e-testing
Write / modify unit tests (*.unit.js or *.unit.ts)handsontable-unit-testing
Make a test actually prove behaviortest-writing-discipline
Build a demo / test pagehandsontable-demo-page
Work on CSS / themeshandsontable-css-dev
Walkontable rendering enginewalkontable-dev / walkontable-testing
A rendering-engine geometry change needs a spec (viewport, overlays, sizing, scroll sync)engine tier: edit an existing walkontable Jasmine spec, or add new coverage in tests/e2e/walkontable/*.spec.ts (walkontable-dev, Testing)
Lint violationshandsontable/AGENTS.md (Lint) + handsontable/.ai/CONVENTIONS.md
Coordinate translation (physical/visual/renderable)coordinate-systems
i18n / translationsi18n-translations
Visual regression testsvisual-testing
Docs pageswriting-docs-pages

Design rules from handsontable-code-review

Full checklist: its references/architecture.md.

  • Plugin decoupling. Talk via hooks; reach another plugin only through hot.getPlugin('Name'). No circular plugin dependencies.
  • Conflict ownership. The plugin that introduces an incompatibility owns the blocking logic. For hard conflicts, call registerConflict() from src/plugins/base/conflictRegistry.ts at module load time.
  • Law of Demeter. Go through TableView or Core for Walkontable data, not this.hot.view.wt.wtTable chains.
  • Liskov. Honor the full BasePlugin contract (lifecycle methods + static properties).
  • Cascading config. New options fit cell → column → global where applicable; document table-level-only options (like data) in JSDoc.
  • Breaking changes. Keep the legacy CSS class in the DOM when renaming. Keep old API names working (no warning for legacy, one-time warning for deprecated). Keep every default setting value. Put removed hooks/options on the removed list so misuse throws.
  • Convention over configuration. Red flags: new options with the same value at every call site (make it the default), new directories outside the existing taxonomy, explicit wiring where auto-discovery works.
  • Gold standard: src/plugins/pagination/pagination.ts (plugin structure, settings validation, conflict registration, focus management).

File layout

src/plugins/{pluginName}/        index.ts, {pluginName}.ts, types.ts?, __tests__/,
                                 AGENTS.md + CLAUDE.md->AGENTS.md (required)
src/editors/{editorName}/        index.ts, {editorName}.ts
src/renderers/{rendererName}/    index.ts, {rendererName}.ts
src/validators/{validatorName}/  index.ts, {validatorName}.ts
src/cellTypes/{typeName}/        index.ts, {typeName}.ts

Unit tests are *.unit.js or *.unit.ts. New E2E is Playwright (tests/e2e/*.spec.ts); the Jasmine *.spec.js suite is frozen (edit existing specs, migrate broken ones to Playwright). .d.ts files are generated by npm run build:types into handsontable/tmp/.


TypeScript gotchas

1. Generalize the signature, add zero as casts

New code adds no as casts (as SomeType, <SomeType>value). Treat the urge to write one as a wrong type upstream. Exhaust these in order: (1) make the function/method signature generic; (2) make the shared entity generic; (3) narrow with a type guard; (4) use unknown only at a true I/O boundary. A cast is acceptable only when none apply (external/normalization boundary, known TS generic-inference gap) and carries a comment saying why. as unknown as T (double cast) is banned. Use unknown instead of any at boundaries, then narrow. After removing casts, rerun npm run test:types; some are load-bearing.

// ✗ function getFirst(items: unknown[]): SomeRow { return items[0] as SomeRow; }
// ✓ function getFirst<T>(items: T[]): T { return items[0]; }

Fix the type at its source. When the same cast repeats across consumers, make the shared structure generic with a permissive default so existing callers compile unchanged:

class TreeNode<T extends object = Record<string, unknown>> {
  data: T;
  walkDown(cb: (node: TreeNode<T>) => unknown) { /* ... */ }
}

Example: src/utils/dataStructures/tree.ts TreeNode<T>, consumed by nestedHeaders as TreeNode<HeaderNodeData>.

1a. DOM narrowing

Use isHTMLElement from src/helpers/dom/element.ts (for a Node | Element | null value) instead of x as HTMLElement, x instanceof HTMLElement, or a nodeType === Node.ELEMENT_NODE guard.

2. .d.ts files

Declarations are generated from source into handsontable/tmp/ only: hand-write no .d.ts anywhere (there is no separate types/ mirror) and edit nothing under tmp/. If a type is missing from the public API, fix the JSDoc/export in the .ts source and rerun npm run build:types.

3. import type for types

import type { HotInstance } from '../../core/types';

4. Import shared types from core/

TypeLocation
GridSettings, Events, HookKeysrc/core/settings.ts
HotInstancesrc/core/types.ts
Plugin-local typesthe plugin's own types.ts

Import these types; never paste a partial copy of GridSettings/HotInstance into the file you are editing (a local copy drifts from the real signature). When the existing type is too wide, narrow it with a generic parameter or type guard at the boundary. Consumers import the same types from the package (import type { GridSettings } from 'handsontable'); see docs/content/guides/tools-and-building/typescript-types/typescript-types.md.

Adding a new hook:

  1. Add the callback signature to GridSettings in src/core/settings.ts.
  2. Register the hook name in src/core/hooks/constants.ts / src/core/hooks/index.ts.
  3. Call Hooks.getSingleton().register('myHook') at module level in the plugin file.

5. Private fields use #, callbacks are arrow-function class fields

class MyPlugin extends BasePlugin {
  #map: HidingMap | null = null;
  #onAfterRender = (): void => { /* `this` is bound */ };
}

@private JSDoc tags and .bind(this) are forbidden.

6. Cognitive complexity ≤ 15 per function

Extract a helper to fix a violation.


Cross-cutting rules (enforced by ESLint)

RuleWhat to do
No throw new Error()throwWithCause('...', cause) from src/helpers/errors.ts
No window / document / console globalsthis.hot.rootWindow, this.hot.rootDocument, helpers from src/helpers/console.ts
No raw setTimeout / setIntervalthis.hot._registerTimeout(fn, delay) (auto-clears on hot.destroy())
No barrel importsImport from the specific submodule path (plugins/index, editors/index, renderers/index, validators/index, cellTypes/index, i18n/index are off limits). Only src/registry.ts may use barrels.
No direct cross-plugin importsHooks or this.hot.getPlugin('Name')
it() in *.spec.js must be asyncasync with await when calling HOT rendering APIs
No native toLocaleLowerCase(locale)localeLowerCase(value, locale) from helpers/string (enforced by no-restricted-syntax)

JSDoc

jsdoc/require-jsdoc is error for src/**/*.ts and scripts/**/*.mjs: every class, method, function declaration, and class field needs a block. Test and type files (*.unit.ts, *.spec.ts, *.types.ts, *.d.ts) are exempt.

  • Multiline format (root AGENTS.md), with a blank line before /** and after */.
  • {Type} in every @param and @returns, public or private. docs:api (jsdoc-to-markdown) reads compiled handsontable/tmp/ and prints these types in the API reference. Keep them in sync with the TS signature ({number|object} for number | { from: number; to: number }). The TS [80004] warning is suppressed for .ts source.
  • The {Type} must parse as JSDoc (catharsis), not TypeScript. A tuple breaks docs:api with Invalid type expression. Write @type {Array<number> | null} and keep the tuple on the TS annotation (#pastePlan: [number, number, number, number] | null). No PR check catches this: the docs path filter in .github/workflows/checks.yml covers docs/** and handsontable/package.json, not handsontable/src/**, so the break surfaces as a failing Docs Staging Deployment on the next unrelated push touching docs/**. After a JSDoc type change, build the package and run npm --prefix docs run docs:api.
  • Private # fields: a description block, no @private.
  • Descriptions state something new (what the member does or represents, with population/invalidation rules where relevant), not a restatement of its name. American English, active voice, short sentences.

DOM and data gotchas

  • Merged cells: read meta, not DOM. Read colspan/rowspan from hot.getCellMeta(row, col), not td.colSpan / td.rowSpan. MergeCells sets cellProperties.colspan via afterGetCellMeta; the DOM attribute may be missing outside the viewport and ignores custom afterGetCellMeta overrides.
  • Coordinates. Translate physical/visual/renderable with hot.rowIndexMapper / hot.columnIndexMapper (coordinate-systems skill).
  • i18n. Add constants to src/i18n/constants.ts and translations to every file in src/i18n/languages/.

Registration wiring

ComponentWire into
Pluginsrc/plugins/index.ts
Editorsrc/editors/index.ts + src/editors/factory.ts
Renderersrc/renderers/index.ts + src/renderers/factory.ts
Validatorsrc/validators/index.ts
Cell typesrc/cellTypes/index.ts
Any new option / hooksrc/dataMap/metaManager/metaSchema.ts + src/core/settings.ts

Build: type declarations

npm run build:types        # step 1: tsc emits tmp/**/*.d.ts
npm run downlevel:types    # step 2: rewrites post-TS-5.1 lib types to TS 5.1 equivalents

npm run build runs both. Run after any change to the public type surface (new export, changed parameter type, new GridSettings option). Wrappers consume handsontable/tmp/.

The dev compiler is TS 6, which infers ArrayIterator, IteratorObject (TS 5.6+) and WeakKey (TS 5.2+), absent from TS 5.1. scripts/downlevel-dts.mjs swaps them for IterableIterator<T> / object. CI job verify-emitted-types runs tsc@5.1.6 --noEmit against tmp/ and reports the leaked identifier as TS2304: Cannot find name '...'. Fix by either annotating the source with the TS 5.1 type (: IterableIterator<T>, WeakMap<object, V>) or adding a row to REPLACEMENTS in scripts/downlevel-dts.mjs.


Mandatory checklist for every change

  • Source file is .ts
  • No as / any casts introduced
  • No .d.ts files hand-edited
  • Unit tests (*.unit.js or *.unit.ts), pure logic, no mocks
  • E2E tests: Playwright in tests/e2e/ (new); legacy *.spec.js suite is frozen
  • npm run build (or build:types + downlevel:types) run if public types changed
  • Wired into all relevant index / factory files
  • Added to metaSchema.ts if a new option was introduced
  • JSDoc on every class, method, function declaration, and class field (multiline; {Type} in every @param/@returns, in sync with the TS signature; no @private on # fields)
  • No breaking change (or it is explicitly called out)
  • Changelog entry added (bin/changelog entry)

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Use when developing or modifying the @handsontable/angular-wrapper package - Angular components with decorators, NgZone performance optimization, and ng-packagr build system

日本語の概要は準備中です。原文の説明を表示しています。

handsontable/handsontable2.2万2026年10月12日 更新

Use when testing a local or public URL on a real device via BrowserStack, opening a live browser session on Android, iOS, or desktop browsers, or when the user mentions BrowserStack, real device testing, mobile testing, cross-browser testing, touch testing, or wants to verify behavior on a specific phone, tablet, or browser version. Also trigger when the user says "test this on Android/iPhone/Safari/Chrome mobile", asks to open a live session, or mentions demo-mobile.html, even if they don't mention BrowserStack by name.

日本語の概要は準備中です。原文の説明を表示しています。

handsontable/handsontable2.2万2026年10月12日 更新

Use when a source code change needs a changelog entry, or before committing and pushing any bug fix, feature, or behavior change to source code - detecting when entries are required, categorizing changes correctly (added/changed/fixed/deprecated/removed/security), writing user-facing titles, and creating the JSON entry in .changelogs/

日本語の概要は準備中です。原文の説明を表示しています。

handsontable/handsontable2.2万2026年10月12日 更新

Query the pre-built code-review-graph knowledge graph (Tree-sitter, whole monorepo) instead of walking call chains with Grep+Read – 2-6x cheaper, and it catches dynamic dispatch that grep misses. Use for ANY task that spans multiple files, even when the user never mentions a graph or asks for it - fixing or tracing a bug ("fix this bug", "why does X happen", "trace this"), exploring unfamiliar code ("how does X work", "who calls X", "what imports Y", "where is X used or handled"), planning or doing a refactor ("rename X", "is it safe to change or remove X", "what would break", "blast radius", "find dead code"), or reviewing changes ("review this PR", "review this branch or diff"). When you are about to Grep for a symbol's callers, callees, or importers, use this skill.

日本語の概要は準備中です。原文の説明を表示しています。

handsontable/handsontable2.2万2026年10月12日 更新

Use when working with row or column indexes in Handsontable - translating between physical, visual, and renderable coordinates, using IndexMapper, or debugging index-related bugs where rows or columns appear in wrong positions

日本語の概要は準備中です。原文の説明を表示しています。

handsontable/handsontable2.2万2026年10月12日 更新

Use when creating code examples for documentation pages - JavaScript, TypeScript, React, Angular, and Vue variants with proper imports, registration, and license key

日本語の概要は準備中です。原文の説明を表示しています。

handsontable/handsontable2.2万2026年10月12日 更新

handsontable のスキルをすべて見る

このスキルの問題を報告する