Replies: 3 comments 9 replies
|
seems like a good plan, GitHub CI is also back and working now so you can proceed |
|
Okay, I think we're nearly done. A to D are merged. With Q16, I queried if we'd be better having a fixed px addition to the header width rather than doubling the scrollbar width. Claude discovered there was already a fixed addition and decided it would be best to remove the doubled scrollbar width and a couple of other related inconsistencies - that PR is coming up very shortly. Also with Q15, the logic Claude was following is that the Frozen Rows and Columns rework (#1238) would definitely land and the work could be put off until then. However, I feel like at this point we're not 100% certain we will integrate that PR. The remaining issue, Q32 is a frozen grid issue only, so I thought I might leave that for you. It's not really clear to me what the best way forward is, or if we just leave it alone. |
|
OK, will have a look. BTW it was his code I used as a suggestion to Claude for the variable height PR. I'm going to be busy for a couple of weeks, work is catching up with me, but I'll keep doing minor things. You won't have my full attention though. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Here's a summary. I'm asking for PRs A and B to be created, then we'll do C and D. The finally look at the other minor issues.
Remaining Quirks — Reworked Evaluation & PR Plan
Follow-up to the triage posted in discussion #1247. The first wave (Q1, Q5, Q16-probe,
Q19, Q20, Q27, Q29, Q30, Q33 → PRs #1255–#1261) is merged; this reworks the
evaluation for everything that remains, so each can become a master PR. All line
numbers re-verified against master
2dc065cd; the pre-landing checks the triagecalled for have now been executed (results inline). Conventions carried from the
first wave: every reproducible fix ships with a self-hosting cypress spec
(harness served from the spec via
cy.intercept— nothing added toexamples/),validated fail-on-unfixed / pass-on-fixed, with deterministic assertion windows
and visit-inside-the-test so retries get a fresh page.
Summary — proposed PR list (in landing order)
frozenRow: 0as no freeze (input clamp)alwaysRenderColumncells to their own column panecreateFooterRowis enabled at runtimeleaveSpaceForNewRowsin frozen gridsPR-A — Q23/Q24:
frozenRow: 0activates an empty frozen band · ready, pre-checks doneMaster evidence (
slick.grid.ts:2353):setFrozenOptionsgates onthis._options.frozenRow! > -1, sofrozenRow: 0passes:hasFrozenRows = true,frozenRowsHeight = 0, split panes built, a 0-height frozen canvas, and withfrozenBottom: true,actualFrozenRow = dataLength − 0 = dataLength— the wholebody renders in the top canvas while bottom-mode offset math measures it (the exact
degenerate case the branch's cellrangeselector needed a positional fallback for).
Pre-check executed:
grep -rn "frozenRow: 0|frozenRow:0|frozenRow = 0"acrossexamples/,cypress/,src/→ zero uses. The clamp changes nothing anyoneexercises.
Fix:
if (this._options.frozenRow! > 0)— zero frozen rows means no freeze.One character. Cures both Q23 and Q24 and removes a whole degenerate family from
every future frozen-row reasoning.
Test plan: self-hosted spec, two harness grids (
frozenRow: 0andfrozenRow: 0, frozenBottom: true) assertinghasFrozenRowsis false-equivalentobservably: single-pane DOM (no
.grid-canvas-bottomrows split), and hit-testingresolves clicked rows correctly in the ex-degenerate bottom variant.
Blast radius: any grid explicitly passing
frozenRow: 0flips from "emptyfrozen band" to "no freeze" — verified unused in-repo; semantically the intended
meaning. Recommendation: fix-now.
PR-B — Q4: off-viewport
alwaysRenderColumncells land in the LEFT fragment · readyMaster evidence (
slick.grid.ts:5429): the off-viewport branch ofappendRowHtmlrenders intorowDiv(the left fragment) unconditionally:The in-viewport branch (5425) routes by band. So an
alwaysRenderColumncolumnthat is right-of-freeze AND horizontally scrolled out renders its cells into the
clipped left canvas — mispositioned/invisible, and (worse)
cellNodesByColumnIdxthen maps that column to a node in the wrong canvas for editors/plugins.
Fix:
(Same band routing the in-viewport branch already uses; left-frozen and
plain-grid cells keep landing in
rowDivexactly as today.)On the "is the config real" question: the checkbox-selector/row-move plugins
set
alwaysRenderColumnon THEIR columns; nothing forces those to be frozen-left.Any user putting an action column at the right edge of a frozen grid hits this.
The fix is also strictly narrowing (only changes the wrong-canvas case), so the
earlier hesitation buys little. Recommendation: fix-now.
Test plan: self-hosted spec —
frozenColumn: 0, 30 columns, last columnalwaysRenderColumn: true, viewport scrolled left → assert that column's cellnode is a child of the RIGHT canvas (
.grid-canvas-right), and thatgetCellNode(row, lastCol)box left-position exceeds the frozen-band width.Fails pre-fix (node parented in
.grid-canvas-left), passes post-fix.PR-C — Q3: frozen-row boundary drift across six comparison sites · UNBLOCKED
The blocker is resolved. The triage held Q3 pending a slickgrid-universal
exposure check. Executed via a fresh clone: slickgrid-universal does not wrap
this grid at runtime — it maintains its own fork (
packages/common/src/core/ slickGrid.ts), which even contains the sameisBottomSideoff-by-one (theirline 1247). An upstream fix here cannot break them; at most it's worth a
courtesy note so the fork can port it. The
.frozen-class grep there shows onlya test reference, no styling dependency.
Canonical semantics (the decision to approve): the render split is the
authority —
rows[i] >= actualFrozenRow→ bottom canvas (6524), i.e.:isBottomBandRow(r) ≡ hasFrozenRows && r >= actualFrozenRowisFrozenRowIdx(r) ≡ frozenBottom ? r >= actualFrozenRow : r < actualFrozenRowThe six sites on master
2dc065cd:appendRowHtmlfrozencssrow <= frozenRow(compares a COUNT; wrong rows classed in bottom mode, off-by-one in top)isFrozenRowIdx(row)cleanupRowsexemption<= actualFrozenRow(spares the first scrollable row)< actualFrozenRowviaisFrozenRowIdxcleanUpCellsexemption<= actualFrozenRow(same)>= actualFrozenRowscrollRowIntoViewguard-1boundaries (bottom mode won't scroll the LAST scrollable row)navigateToPos(8816)_getContainerElement>= actualFrozenRow + (frozenBottom ? 0 : 1)— classifies the first scrollable row as TOP side while its DOM is in the bottom canvas>= actualFrozenRow(
navigateToPos8816 is already canonical — the seventh site, used as the model.)Observables fixed:
getCanvasNode/getViewportNodereturning the wrong panefor exactly the boundary row (overlay/tooltip mispositioning);
.slick-row.frozenlanding on the wrong rows in bottom mode; the boundary row never evicted from
cache; keyboard/API scroll refusing the last scrollable row in bottom mode.
Shape: introduce the two private predicates, route the five non-canonical
sites through them, one commit. Characterization-first: land the spec in the
same PR but written against the CANONICAL semantics and validated to fail pre-fix
per site (the first wave's fail/pass discipline).
Test plan: self-hosted spec, one top-freeze grid + one bottom-freeze grid:
(a)
getCanvasNode(0, firstScrollableRow)returns the canvas that actuallycontains that row's
.slick-row[data-row]; (b) thefrozenclass set equalsexactly the configured frozen rows in BOTH modes; (c)
scrollRowIntoView(last scrollable row)scrolls in bottom mode; (d) boundary-row cache eviction after afar scroll. Recommendation: fix-now (no longer investigate-first).
PR-D — Q2:
setOptions({createFooterRow: true})after init crashes · needs the design callMaster evidence re-verified: footer DOM is built only in the init path
(
855);internal_setOptionsnever rebuilds it; flipping the flag later flowsinto
setColumns→createColumnFooterdereferences the undefined_footerRowL. (First-wave #1256 fixed the other footer bugs; this runtimetransition remains.)
The decision: (i) support it — build footer DOM lazily when the flag
flips true; or (ii) documented no-op — ignore the flip with a console warn.
Recommendation: (i) support. The grid already added lazy behaviors
elsewhere, the DOM is self-contained (scroller + spacer + columns container per
side), and
createColumnFooterimmediately populates cells — amaterializeFooterRow()called frominternal_setOptionswhencreateFooterRow && !_footerRowis ~40 lines mirroring the init block, pluswiring its scroll/context events (the bindings the init path attaches). Disable
(
falseat runtime) should hide, not destroy — symmetric withshowFooterRow.Test plan: self-hosted spec — construct without footer;
setOptions({ createFooterRow: true, showFooterRow: true }); assert footer DOM exists, footercells render per column,
onFooterRowCellRenderedfired once per column, andgetFooterRow()returns the element; thensetOptions({ showFooterRow: false })hides it. Fails pre-fix (TypeError), passes post-fix.
Blast radius: new code path only; the previously-crashing call now works —
strictly additive. Recommendation: fix-now once (i) is approved.
Investigation / decision items (no PR yet)
Q16-remainder — double scrollbar addition in
getHeadersWidthPost-#1260 state (
4687–4699): whenincludeScrollbar(=!autoHeight), thescrollbar width is added to the active band twice — once in the
includeScrollbarblock, once again in the band-finalization block (both thefrozen path
4697and the plain path4699). Effect: the header container isover-provisioned by one scrollbar width. Because
headersWidthR/Lalso serve asthe header scroll-range floor (the Q14/Q15 coupling), removing one add risks a
subtle header/body scroll desync in edge widths for zero user-visible gain — the
container is clipped anyway. Recommendation: keep-as-is; close the
investigation unless a concrete mis-render is ever traced to it. (If desired:
one golden-pin commit documenting the double-add as intentional over-provision.)
Q32 —
leaveSpaceForNewRowsignored in frozen grids6073: only the unfrozen branch adds the blank-space term (and only it usesdataLengthIncludingAddNew). Product call:scrollable body). Recommend supporting: add the same term to the frozen branch
when
!frozenBottom.unsupported, documented.
Recommendation: small PR for the top-freeze half if you want the affordance;
otherwise a doc note. Not a defect either way.
Q15 — cumulative
headersWidthR(re-affirmed keep)With the strategy now "fix everything on master, then rework the branch," the
question was whether Q15 should normalize on master. Re-affirmed no: the
over-provision is harmless (clipped), the value doubles as the scroll-range sync
floor, and the golden spec pins it. Normalization remains a branch-rework option
where
computeHeaderWidthsis being rewritten anyway — decide there, not here.Confirmed keepers (for the discussion record)
Q6 (footer R-before-L construction order), Q13-adjacent (
suppressColumnSetstaleness contract), Q14 (+1000 slack — load-bearing), Q17 (
headerR = 0write),Q25 (inert
viewportBottomRwrite), Q26 (reorder can't cross the freeze —deliberate limitation, worth one docs line).
Suggested landing order & why
A → B → C → D. A and B are independent and tiny (land in either order); C
touches the same row-boundary predicates that A simplifies (no
frozenRow: 0degenerate to reason about), so it goes after A; D is independent but largest,
and its spec benefits from C's canonical predicates being settled. After all
four: the #1238 rework proceeds against a master with zero known frozen-row
inconsistencies, and the branch's remaining quirk-preservation code (the
cellrangeselector degenerate fallback, the per-semantic predicate duplication,
the
fragmentForColumnoff-viewport asymmetry) all becomes deletable.All reactions