Skip to content

refactor: Replace SortableJS 2/4: replace SortableJS with native HTML5 drag & drop for column header reorder - #1242

Open
6pac-ai wants to merge 2 commits into
masterfrom
refactor/drop-sortablejs
Open

refactor: Replace SortableJS 2/4: replace SortableJS with native HTML5 drag & drop for column header reorder#1242
6pac-ai wants to merge 2 commits into
masterfrom
refactor/drop-sortablejs

Conversation

@6pac-ai

@6pac-ai 6pac-ai commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Context

Part 2 of the SortableJS removal (port of slickgrid-universal's refactor(core)!: drop SortableJS dependency #2634). Stacked on #1240 — the characterization specs landed there pass unchanged against this new engine; that was the acceptance gate for this PR.

After this PR the grid itself no longer uses SortableJS for header column reordering. The SlickDraggableGrouping plugin still does (next PR), so the dependency and the example <script> tags stay for now.

What's in here

  • src/slick.interactions.ts — new setupColumnReorderDrag(): native HTML5 drag & drop with live DOM reordering during dragover, browser-edge auto-scroll, a Firefox/Linux mouse-based fallback (native HTML5 drag is broken there), a touch fallback with a manual drag ghost (touch screens never fire HTML5 drag events), and dropzone hooks that the draggable-grouping port will use. Registered on the Slick namespace so iife/browser builds keep working with no new <script> tag (every example already loads slick.interactions.js).
  • src/slick.grid.ts — sortablejs type imports and the two Sortable instances removed; setupColumnReorder() rewired onto the new engine with a column-map reconciliation in onDragEnd: hidden and reorderable: false columns keep their original indices. This fixes a latent bug — the old toArray() read-back silently dropped hidden columns from the grid on any reorder (hidden columns render no header, so the DOM read-back omitted them).
  • src/models/interactions.interface.ts (+ColumnReorderDragOption), src/global.d.ts (Slick namespace typing), src/styles/slick.grid.scss (fallback drag-ghost rule).
  • Cypress: the hidden-column characterization test from test(cypress): Replace SortableJS 1/4: characterize column header reorder ahead of SortableJS removal #1240 is un-skipped (it documents the fix above and now passes — it cannot pass on SortableJS), and a redundant spec-level @4tw/cypress-drag-drop import in example-grid-menu.cy.ts is removed (it re-registered the plugin's drag command over the shared HTML5 DnD overwrite from test(cypress): Replace SortableJS 1/4: characterize column header reorder ahead of SortableJS removal #1240).

Deliberate deviations from the upstream engine

Both preserve the previous SortableJS behavior that the #1240 characterization specs pin:

  1. Frozen boundary stays uncrossable — reorders are constrained to the dragged column's own header container. Upstream's engine allows dragging a header across the left/right (frozen) boundary; SortableJS's two unconnected lists never did.
  2. The drag finalizes on drop as well as dragend — SortableJS finalized on drop. Without this, drag sources that dispatch drop without a following dragend leave the header DOM visually reordered while setColumns()/onColumnsReordered never run.

Not in here

  • dist/** is intentionally not rebuilt in this PR (release commits regenerate it).
  • SortableJS stays in package.json and in the example pages until the DraggableGrouping port and the final removal sweep.

Verification

  • Full 47-spec Cypress suite against the rebuilt bundles: 600/601 passing, 0 failures (1 intentional pending) — including all test(cypress): Replace SortableJS 1/4: characterize column header reorder ahead of SortableJS removal #1240 characterization specs unchanged: plain/frozen reorder, unorderable columns (blocked from moving, still resizable), onColumnsReordered payloads, scroll preservation, edge auto-scroll, cross-boundary lock, grouping pill drags and header→dropzone drop (still SortableJS-driven in the plugin).
  • npm run lint and npm run build:types (strict TS) clean.
  • dist/browser/slick.grid.js contains no SortableJS references after the change; the only remaining Sortable.create call sites in the bundles come from slick.draggablegrouping.ts.

Next up: port SlickDraggableGrouping off SortableJS (setupDropzonePillDrag), then remove the dependency and sweep the ~100 example pages.

🤖 Generated with Claude Code

6pac-ai and others added 2 commits July 17, 2026 11:44
… removal

- overwrite the @4tw/cypress-drag-drop drag command with a native HTML5
  DnD event sequence (pointerdown/mousedown -> dragstart -> dragenter/
  dragover -> drop -> dragend) sharing one DataTransfer, so the same
  command drives SortableJS today and a native drag engine later
- add characterization specs for plain header reorder (unorderable
  columns, onColumnsReordered payload, resizing unorderable columns),
  frozen-grid reorder (cross-boundary lock, scroll preservation,
  auto-scroll) and header-to-dropzone grouping drops
- part 1 of the SortableJS removal (port of slickgrid-universal #2634)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… header reorder

Port of slickgrid-universal's column reorder engine (ghiscoding/slickgrid-universal#2634)
adapted to this repo. The grid no longer needs SortableJS for header column reordering;
the SlickDraggableGrouping plugin still uses it (to be ported next), so the dependency
itself stays for now.

- add `setupColumnReorderDrag()` to slick.interactions.ts: native HTML5 drag with live
  DOM reordering during dragover, browser-edge auto-scroll, Firefox/Linux mouse fallback,
  touch fallback with a manual drag ghost, and dropzone hooks for draggable grouping
- rewire slick.grid.ts: drop the sortablejs type imports and Sortable instances, add a
  column-map reconciliation in onDragEnd so `hidden` and `reorderable: false` columns
  keep their original indices (the old toArray() read-back silently dropped hidden
  columns on any reorder)
- two deliberate deviations from the upstream engine, both preserving the previous
  SortableJS behavior pinned by the characterization specs:
  - reorders are constrained to the dragged column's own header container, so columns
    can never cross the frozen-column boundary
  - the drag finalizes on `drop` as well as `dragend` (SortableJS finalized on drop;
    without this, drag sources that skip dragend leave the DOM reordered without
    setColumns/onColumnsReordered ever running)
- enable the hidden-column characterization test (fixed by the column-map reconciliation)
- remove a redundant spec-level @4tw/cypress-drag-drop import in example-grid-menu.cy.ts
  that re-registered the plugin's drag command over the shared HTML5 DnD overwrite

Full Cypress suite: 600/601 passing (1 intentional pending), lint and TS declaration
build clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@6pac 6pac changed the title refactor: replace SortableJS with native HTML5 drag & drop for column header reorder refactor: Replace SortableJS 2/4: replace SortableJS with native HTML5 drag & drop for column header reorder Jul 17, 2026
Base automatically changed from test/column-reorder-e2e to master July 17, 2026 14:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants