Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
40e0363
feat(grid)!: replace frozen panes with pinning and sticky docking
ghiscoding Sep 8, 2026
ef7197f
chore: remove legacy frozen code from slickgrid and services
ghiscoding Sep 8, 2026
93e791c
chore: increase unit tests coverage
ghiscoding Sep 8, 2026
9e681fc
chore: remove all legacy frozen stuff from codebase
ghiscoding Sep 8, 2026
aca989c
Merge branch 'master' into feat/pinning-and-sticky
ghiscoding Sep 8, 2026
f7d1b9b
chore: reimplement pinning in header menu, fix column resize, remove …
ghiscoding Sep 8, 2026
d790054
chore: fix all framework demos & horizontal/vertical scrollers
ghiscoding Sep 9, 2026
869c653
chore(tests): fix Vitest warning about vmThread
ghiscoding Sep 9, 2026
10fc72e
chore: fix failing React Cypress test
ghiscoding Sep 9, 2026
96b1d94
chore: increase unit test coverage
ghiscoding Sep 9, 2026
893bcc9
docs: update agents.md file to correctly separate RTK/VEXP
ghiscoding Sep 9, 2026
8ce44cb
chore: fix toggle pin row top/bottom
ghiscoding Sep 9, 2026
690c04e
chore: add `pinnable` flag to disable column pinning
ghiscoding Sep 9, 2026
96e2116
chore: replicate new sticky example to all frameworks
ghiscoding Sep 9, 2026
26cc6ed
chore: improve scrolling perf for pinning and sticky
ghiscoding Sep 9, 2026
6e8efcb
chore: fix issue with mousewheel going left outside viewport
ghiscoding Sep 9, 2026
a37c647
chore(css): remove unnecessary column header float
ghiscoding Sep 9, 2026
adb8b86
chore: make Pinning work with Grouping and fix all UI bugs
ghiscoding Sep 10, 2026
288bafb
chore: add Pin Through Here left/right to Header Menu
ghiscoding Sep 10, 2026
2d8f6a3
chore: rename Pin Columns Left/Right and add test coverage
ghiscoding Sep 10, 2026
4bd4b15
chore: pane rename and old names cleanup
ghiscoding Sep 11, 2026
f02914f
Merge branch 'master' into feat/pinning-and-sticky
ghiscoding Sep 11, 2026
77e28d6
chore: add top/bottom/left/right pinning in same example
ghiscoding Sep 11, 2026
a10ee37
chore: dropzone should always be full grid width
ghiscoding Sep 11, 2026
ffd925f
chore: pinning should also work with colspan
ghiscoding Sep 11, 2026
3cc7251
chore: increase test coverage and fix missed cypress tests
ghiscoding Sep 11, 2026
a7e68c4
chore: colspan should spread outside pinning boundary
ghiscoding Sep 12, 2026
aeed7da
chore: column name behind column being resized should show over
ghiscoding Sep 12, 2026
d72b395
chore: rendered-order export/picker fixes
ghiscoding Sep 12, 2026
0fd661d
chore: improve pinning/colspan tests
ghiscoding Sep 12, 2026
c44c576
chore: add missing attributes for a11y
ghiscoding Sep 12, 2026
c67f95a
chore: revisit horizontal scrolling with sticky columns
ghiscoding Sep 12, 2026
3776e8b
chore: simplify SlickGrid error messages & update tests
ghiscoding Sep 12, 2026
6011d51
chore: update error messages in cypress tests
ghiscoding Sep 12, 2026
032ae34
chore: add mocking to avoid jsdom warnings
ghiscoding Sep 12, 2026
f39d3e8
chore: add mocking to avoid jsdom warnings
ghiscoding Sep 12, 2026
a425c24
chore: move Header Menu Sort commands to top of list & change icons
ghiscoding Sep 12, 2026
4861a0c
chore: adjust examples & cypress tests to resolve failures
ghiscoding Sep 12, 2026
bdb10c1
chore: improve sticky horizontal scroll perf
ghiscoding Sep 13, 2026
6f23075
chore: remove Docking Controller public API from barrel
ghiscoding Sep 13, 2026
c3930da
chore: more cleanup and leftover pinning/sticky progress tasks
ghiscoding Sep 14, 2026
c4830b5
chore: add showPinningCommands in header menu options
ghiscoding Sep 15, 2026
5af9009
chore: final code cleanup and Firefox fixes
ghiscoding Sep 15, 2026
358a603
Merge remote-tracking branch 'origin/master' into feat/pinning-and-st…
ghiscoding Sep 15, 2026
369629b
chore(tests): add missing slickgrid line coverage
ghiscoding Sep 15, 2026
639af10
chore: try to add `minCenterRowCount` but not entirely implemented
ghiscoding Sep 15, 2026
f2c806f
chore: improve Firefox perf for grid pinning
ghiscoding Sep 15, 2026
7787ac8
Merge remote-tracking branch 'origin/feat/pinning-and-sticky' into fe…
ghiscoding Sep 15, 2026
05682cf
chore: complete the `minCenterRowCount` fix
ghiscoding Sep 15, 2026
592bbec
chore: resolve vitest error for missing entries
ghiscoding Sep 15, 2026
96ed4e3
chore: add missing a11y attributes
ghiscoding Sep 16, 2026
11fd743
docs: update v11 migration guide
ghiscoding Sep 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1,119 changes: 1,119 additions & 0 deletions .agents/plans/pinning-sticky-progress.md

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions .agents/skills/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Repository AI Skills

Portable project skills live under `.agents/skills/<skill-name>/SKILL.md` and can be discovered
by Cursor and other Agent Skills-compatible tools.

Available portable skills

- [`pinning-sticky/SKILL.md`](pinning-sticky/SKILL.md) — configuration and maintenance guidance
for permanent pinning and sticky docking.
- [`create-slickgrid-package/SKILL.md`](create-slickgrid-package/SKILL.md) — guidance for creating
optional SlickGrid packages and external resources.
- [`read-docs-and-interfaces/SKILL.md`](read-docs-and-interfaces/SKILL.md) — repository documentation
and TypeScript interface discovery.
- [`webmcp/SKILL.md`](webmcp/SKILL.md) — WebMCP API, demo, and test guidance.

New cross-agent skills should use the portable structure above.

Project implementation plans live under `.agents/plans/`:

- [`formatted-data-cache-implementation.md`](../plans/formatted-data-cache-implementation.md)
- [`pinning-sticky-progress.md`](../plans/pinning-sticky-progress.md)
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
---
name: create-slickgrid-package
description: Create a new optional SlickGrid Universal package or external resource in the monorepo.
---

## Create a new SlickGrid‑Universal package

New packages in the slickgrid‑universal monorepo are typically created when adding a new optional **External Resource** (i.e. a plugin or component that integrates with the grid but is not part of the core). This skill documents the recommended steps and minimal references for doing so. Use `SlickEmptyWarningComponent` ([packages/empty-warning-component](packages/empty-warning-component)) as a simple reference implementation.
Expand Down
59 changes: 59 additions & 0 deletions .agents/skills/pinning-sticky/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
name: pinning-sticky
description: Configure, document, review, or change SlickGrid permanent pinning and scroll-activated sticky docking.
---

# Pinning and Sticky Docking

Use this skill when configuring, documenting, reviewing, or changing SlickGrid permanent pinning
or scroll-activated sticky docking.

## Canonical configuration

- Use the nested `GridOption.pinning` shape for permanent pins:
`columns.left/right` and `rows.top/bottom`.
- Column references may be numeric boundaries or explicit IDs/indexes. Explicit arrays may be
non-contiguous, for example `columns.left: ['account', 'status']`.
- Row references may be indexes or `datasetIdPropertyName` values. An in-range numeric row
reference is interpreted as an index first. Non-contiguous rows are valid, for example
`rows.top: [0, 2, 4]`.
- `Column.pinned` is the per-column permanent-pin form. `Column.pinnable` only controls whether
built-in pinning commands are exposed.
- Do not infer pinning from drag operations across center/pinned bands. Reordering stays within a
band; pinning and unpinning are explicit through configuration, APIs, or menus.

## Sticky behavior

- Use `Column.sticky` and `GridOption.stickyRows` for scroll-activated docking. Sticky state is
scroll-dependent and is not serialized in Grid State/Presets; permanent pinning is serialized.
- Multiple active top sticky rows stack in natural dataset order. They do not push each other out.
- Sticky row capacity uses the current viewport, not a fixed row count. The default row budget is
60% of viewport height after permanent pinned rows are accounted for, and measured row heights
determine how many candidates fit. `docking.maxRowViewportHeightPercent` and
`docking.overflowStrategy` control this behavior.
- Permanent pinned rows remain part of the normal dataset height. When non-contiguous rows are
pinned, unpinned rows are laid out contiguously so skipped indexes do not create blank gaps.

## Maintenance verification

When changing this feature:

1. Check the shared interfaces and the root documentation first:
`packages/common/src/interfaces/`, `docs/grid-functionalities/pinning.md`, and
`docs/grid-functionalities/sticky.md`.
2. Keep the equivalent pinning/sticky documentation aligned in Angular, Aurelia, React, and Vue.
3. Add or update focused common tests for resolver/layout behavior, then preserve the existing
Vanilla and framework Cypress coverage for pinning, sticky docking, resizing, editing,
selection, grouping, spans, RTL, and variable row heights.
4. Treat `DockingController` as an internal implementation module; do not make it part of the
public API without an explicit API decision.
5. Keep fast vertical-scroll blanking as a separate virtual-rendering task; do not conflate it
with sticky-row activation or docking-layout refresh.

## Source documentation

- [Implementation progress](../../plans/pinning-sticky-progress.md)
- [Pinning](../../../docs/grid-functionalities/pinning.md)
- [Sticky docking](../../../docs/grid-functionalities/sticky.md)
- [Grid State and Presets](../../../docs/grid-functionalities/grid-state-preset.md)
- [v11 migration guide](../../../docs/migrations/migration-to-11.x.md)
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
---
name: read-docs-and-interfaces
description: Find the right SlickGrid documentation, interfaces, demos, and tests for a requested feature or API.
---

# Skill: Read Docs & Interfaces

Purpose
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
---
name: webmcp
description: Discover, configure, or review SlickGrid WebMCP tools, documentation, interfaces, demos, and tests.
---

# Skill: WebMCP / AI Toolkit

Purpose
Expand Down
12 changes: 0 additions & 12 deletions .github/skills/SKILLS.md

This file was deleted.

13 changes: 13 additions & 0 deletions .rtk/filters.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Project-local RTK filters — commit this file with your repo.
# Filters here override user-global and built-in filters.
# Docs: https://github.com/rtk-ai/rtk#custom-filters
schema_version = 1

# Example: suppress build noise from a custom tool
# [filters.my-tool]
# description = "Compact my-tool output"
# match_command = "^my-tool\\s+build"
# strip_ansi = true
# strip_lines_matching = ["^\\s*$", "^Downloading", "^Installing"]
# max_lines = 30
# on_empty = "my-tool: ok"
11 changes: 8 additions & 3 deletions demos/aurelia/src/assets/i18n/en/aurelia-slickgrid.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"CLEAR_ALL_FILTERS": "Clear all Filters",
"CLEAR_ALL_GROUPING": "Clear all Grouping",
"CLEAR_ALL_SORTING": "Clear all Sorting",
"CLEAR_PINNING": "Unfreeze Columns/Rows",
"CLEAR_PINNING": "Unpin Columns/Rows",
"CLONE": "Clone",
"COLLAPSE_ALL_GROUPS": "Collapse all Groups",
"COLUMNS": "Columns",
Expand All @@ -28,7 +28,11 @@
"FILTER_SHORTCUTS": "Filter Shortcuts",
"FROM_TO_OF_TOTAL_ITEMS": "{{from}}-{{to}} of {{totalItems}} items",
"FORCE_FIT_COLUMNS": "Force fit columns",
"FREEZE_COLUMNS": "Freeze Columns",
"PIN_COLUMN": "Column Pinning",
"PIN_COLUMNS_LEFT": "Pin Columns Left",
"PIN_COLUMNS_RIGHT": "Pin Columns Right",
"PIN_LEFT": "Pin Left",
"PIN_RIGHT": "Pin Right",
"INVALID_FLOAT": "The number must be valid and have a maximum of {{maxDecimal}} decimals.",
"GREATER_THAN": "Greater than",
"GREATER_THAN_OR_EQUAL_TO": "Greater than or equal to",
Expand Down Expand Up @@ -63,7 +67,8 @@
"SYNCHRONOUS_RESIZE": "Synchronous resize",
"TOGGLE_FILTER_ROW": "Toggle Filter Row",
"TOGGLE_PRE_HEADER_ROW": "Toggle Pre-Header Row",
"UNFREEZE_COLUMNS": "Unfreeze Columns",
"UNPIN_COLUMN": "Unpin Column",
"UNPIN_COLUMNS": "Unpin All Columns",
"X_OF_Y_SELECTED": "# of % selected",
"X_OF_Y_MASS_SELECTED": "{{x}} of {{y}} selected",
"BILLING": {
Expand Down
11 changes: 8 additions & 3 deletions demos/aurelia/src/assets/i18n/fr/aurelia-slickgrid.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"CLEAR_ALL_FILTERS": "Supprimer tous les filtres",
"CLEAR_ALL_GROUPING": "Supprimer tous les groupes",
"CLEAR_ALL_SORTING": "Supprimer tous les tris",
"CLEAR_PINNING": "Dégeler les colonnes/rangées",
"CLEAR_PINNING": "Désépingler les colonnes/rangées",
"CLONE": "Cloner",
"COLLAPSE_ALL_GROUPS": "Réduire tous les groupes",
"COLUMNS": "Colonnes",
Expand All @@ -28,7 +28,11 @@
"FILTER_SHORTCUTS": "Raccourcis de filtre",
"FROM_TO_OF_TOTAL_ITEMS": "{{from}}-{{to}} de {{totalItems}} éléments",
"FORCE_FIT_COLUMNS": "Ajustement forcé des colonnes",
"FREEZE_COLUMNS": "Geler les colonnes",
"PIN_COLUMN": "Épinglage de colonne",
"PIN_COLUMNS_LEFT": "Épingler les colonnes à gauche",
"PIN_COLUMNS_RIGHT": "Épingler les colonnes à droite",
"PIN_LEFT": "Épingler à gauche",
"PIN_RIGHT": "Épingler à droite",
"GREATER_THAN": "Plus grand que",
"GREATER_THAN_OR_EQUAL_TO": "Plus grand ou égal à",
"GROUP_BY": "Grouper par",
Expand Down Expand Up @@ -63,7 +67,8 @@
"SYNCHRONOUS_RESIZE": "Redimension synchrone",
"TOGGLE_FILTER_ROW": "Basculer la ligne des filtres",
"TOGGLE_PRE_HEADER_ROW": "Basculer la ligne de pré-en-tête",
"UNFREEZE_COLUMNS": "Dégeler les colonnes",
"UNPIN_COLUMN": "Désépingler la colonne",
"UNPIN_COLUMNS": "Désépingler toutes les colonnes",
"X_OF_Y_SELECTED": "# de % sélectionnés",
"X_OF_Y_MASS_SELECTED": "{{x}} de {{y}} sélectionnés",
"BILLING": {
Expand Down
10 changes: 8 additions & 2 deletions demos/aurelia/src/examples/locales/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ export const localeFrench = {
TEXT_EXPORT_TO_TEXT_FORMAT: 'Exporter en format texte',
TEXT_FILTER_SHORTCUTS: 'Raccourcis de filtre',
TEXT_FORCE_FIT_COLUMNS: 'Ajustement forcé des colonnes',
TEXT_PIN_COLUMN: 'Épinglage de colonne',
TEXT_PIN_COLUMNS_LEFT: 'Épingler les colonnes à gauche',
TEXT_PIN_COLUMNS_RIGHT: 'Épingler les colonnes à droite',
TEXT_PIN_LEFT: 'Épingler à gauche',
TEXT_PIN_RIGHT: 'Épingler à droite',
TEXT_GROUP_BY: 'Grouper par',
TEXT_HIDE_COLUMN: 'Cacher la colonne',
TEXT_LAST_UPDATE: 'Dernière mise à jour',
Expand All @@ -32,10 +37,11 @@ export const localeFrench = {
TEXT_SORT_ASCENDING: 'Trier par ordre croissant',
TEXT_SORT_DESCENDING: 'Trier par ordre décroissant',
TEXT_STARTS_WITH: 'Commence par',
TEXT_UNFREEZE_COLUMNS: 'Dégeler les colonnes',
TEXT_UNPIN_COLUMN: 'Désépingler la colonne',
TEXT_UNPIN_COLUMNS: 'Désépingler toutes les colonnes',
TEXT_X_OF_Y_SELECTED: '# de % sélectionné',
TEXT_X_OF_Y_MASS_SELECTED: '{{x}} de {{y}} sélectionnés',
TEXT_CLEAR_PINNING: 'Dégeler les colonnes/rangées',
TEXT_CLEAR_PINNING: 'Désépingler les colonnes/rangées',
TEXT_EQUAL_TO: 'Égal à',
TEXT_GREATER_THAN: 'Plus grand que',
TEXT_GREATER_THAN_OR_EQUAL_TO: 'Plus grand ou égal à',
Expand Down
2 changes: 0 additions & 2 deletions demos/aurelia/src/examples/slickgrid/example07.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,6 @@ export class Example07 {
...this.gridOptions1,
enableHeaderMenu: true,
enableFiltering: true,
// frozenColumn: 2,
// frozenRow: 2,
headerButton: {
onCommand: (_e: any, args) => this.handleOnCommand(_e, args, 2),
},
Expand Down
10 changes: 5 additions & 5 deletions demos/aurelia/src/examples/slickgrid/example14.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@ <h3>

<hr />

<h3>Grid 2 <small>(with Header Grouping &amp; Frozen/Pinned Columns)</small></h3>
<h3>Grid 2 <small>(with Header Grouping &amp; Pinned Columns)</small></h3>

<div class="col-sm 12">
<button class="btn btn-outline-secondary btn-sm btn-icon" click.trigger="setFrozenColumns2(-1)" data-test="remove-frozen-column-button">
<i class="mdi mdi-close"></i> Remove Frozen Columns
<button class="btn btn-outline-secondary btn-sm btn-icon" click.trigger="setPinnedColumns2(-1)" data-test="remove-pinned-column-button">
<i class="mdi mdi-close"></i> Remove Pinned Columns
</button>
<button class="btn btn-outline-secondary btn-sm btn-icon" click.trigger="setFrozenColumns2(2)" data-test="set-3frozen-columns">
<i class="mdi mdi-pin-outline"></i> Set 3 Frozen Columns
<button class="btn btn-outline-secondary btn-sm btn-icon" click.trigger="setPinnedColumns2(2)" data-test="set-3pinned-columns">
<i class="mdi mdi-pin-outline"></i> Set 3 Pinned Columns
</button>
</div>

Expand Down
11 changes: 0 additions & 11 deletions demos/aurelia/src/examples/slickgrid/example14.scss

This file was deleted.

18 changes: 11 additions & 7 deletions demos/aurelia/src/examples/slickgrid/example14.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ExcelExportService } from '@slickgrid-universal/excel-export';
import { PdfExportService } from '@slickgrid-universal/pdf-export';
import { type AureliaGridInstance, type Column, type GridOption, type ItemMetadata } from 'aurelia-slickgrid';
import './example14.scss'; // provide custom CSS/SASS styling

export class Example14 {
aureliaGrid1!: AureliaGridInstance;
Expand Down Expand Up @@ -56,6 +55,7 @@ export class Example14 {
preHeaderPanelHeight: 28,
gridHeight: 275,
gridWidth: 800,
rowHeight: 33,
enablePdfExport: true,
enableExcelExport: true,
excelExportOptions: {
Expand All @@ -68,6 +68,9 @@ export class Example14 {
getRowMetadata: (item: any, row: number) => this.renderDifferentColspan(item, row),
},
},
headerMenu: {
showPinningCommands: true,
},
gridMenu: {
iconButtonContainer: 'preheader', // we can display the grid menu icon in either the preheader or in the column header (default)
},
Expand Down Expand Up @@ -104,15 +107,16 @@ export class Example14 {
explicitInitialization: true,
gridHeight: 275,
gridWidth: 800,
frozenColumn: 2,
rowHeight: 33,
pinning: { columns: { left: 2 } },
enablePdfExport: true,
enableExcelExport: true,
excelExportOptions: {
exportWithFormatter: false,
},
externalResources: [new ExcelExportService(), new PdfExportService()],
gridMenu: { hideClearFrozenColumnsCommand: false },
headerMenu: { hideFreezeColumnsCommand: false },
gridMenu: { hideClearPinningCommand: false },
headerMenu: { showPinningCommands: true },
};
}

Expand All @@ -124,7 +128,7 @@ export class Example14 {
id: i,
num: i,
title: 'Task ' + i,
duration: '5 days',
duration: '5 days with some long text to test column span',
percentComplete: Math.round(Math.random() * 100),
start: '01/01/2009',
finish: '01/05/2009',
Expand All @@ -134,8 +138,8 @@ export class Example14 {
return mockDataset;
}

setFrozenColumns2(frozenCols: number) {
this.gridObj2.setOptions({ frozenColumn: frozenCols });
setPinnedColumns2(pinnedCols: number) {
this.gridObj2.setOptions({ pinning: { columns: { left: pinnedCols } } });
this.gridOptions2 = this.gridObj2.getOptions();
}

Expand Down
4 changes: 2 additions & 2 deletions demos/aurelia/src/examples/slickgrid/example15.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,10 @@ export class Example15 {
},
gridMenu: {
hideForceFitButton: true,
hideClearFrozenColumnsCommand: false,
hideClearPinningCommand: false,
},
headerMenu: {
hideFreezeColumnsCommand: false,
showPinningCommands: true,
},
enablePagination: true,
pagination: {
Expand Down
4 changes: 2 additions & 2 deletions demos/aurelia/src/examples/slickgrid/example18.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ <h2>
<div class="row">
<div class="col-sm-12">
<button class="btn btn-outline-secondary btn-xs btn-icon" data-test="add-5k-rows-btn" click.trigger="loadData(5000)">5K rows</button>
<button class="btn btn-outline-secondary btn-xs btn-icon" data-test="add-50k-rows-btn" click.trigger="loadData(50000)">
50K rows
<button class="btn btn-outline-secondary btn-xs btn-icon" data-test="add-500k-rows-btn" click.trigger="loadData(500000)">
500K rows
</button>
<button class="btn btn-outline-secondary btn-xs btn-icon" data-test="clear-grouping-btn" click.trigger="clearGroupsAndSelects()">
<i class="mdi mdi-close"></i> Clear grouping
Expand Down
Loading
Loading