Skip to content

Follow-up: fix reconfigure class migration edge cases#2

Open
VishnuSivadasVS wants to merge 2 commits into
latestfrom
codex/analyze-and-fix-reported-issues
Open

Follow-up: fix reconfigure class migration edge cases#2
VishnuSivadasVS wants to merge 2 commits into
latestfrom
codex/analyze-and-fix-reported-issues

Conversation

@VishnuSivadasVS

Copy link
Copy Markdown
Member

Motivation

  • Reconfiguration after changing classNames left stale classes/selectors in the DOM and could produce duplicate toggle buttons or mis-targeted control cells.
  • Multi-row <thead> support needed consistent application of visibility and removal of only injected control cells.
  • Inline review flagged accidental insertion of control cells into generated details rows and duplicate delegated listeners across remounts.

Description

  • Add swapClassTokens(...) and _migrateStructureClasses(prevOptions, nextOptions) to migrate existing DOM classes for control/toggle/details elements when structural classNames change.
  • Avoid inserting control <td> into details rows by skipping rows with the details class in _ensureControlColumn() and track injected header <th> per header row with _insertedHeaderControls (a WeakSet) so destroy() removes only injected header controls.
  • Ensure event delegation handlers are only attached once per controller by guarding _clickHandler and _keyHandler, apply visibility to all header rows via headerRows, and add a _reconfigure(nextOptions, structural) path that uses isStructuralOptionsChange(...) to detect structural changes.
  • Rebuilt distribution artifacts and updated README/docs to reflect multi-row <thead> support and the above fixes.

Testing

  • Ran npm run build which completed successfully and produced updated dist/* artifacts.
  • Launched a lightweight docs server with python3 -m http.server 4173 and captured a browser render with a Playwright script to validate the docs page loaded after the build, which succeeded.
  • Performed automated code searches/inspections to verify the new helpers and reconfigure path exist in src/CollapseTable.js and the built bundles include the same changes.

Codex Task

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e3f6519407

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/CollapseTable.js
Comment on lines +438 to 441
const firstIsControl = first && hasAllClasses(first, this.options.classNames.control);
if (!firstIsControl) {
const td = createEl("td", this.options.classNames.control);
row.insertBefore(td, row.firstChild);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve existing body control cells on teardown

This change only injects a control <td> when a row’s first cell is missing the control class, but destroy() still deletes the first cell from every data row whenever _insertedControl is true. In tables where some rows already had author-provided control cells (or _insertedControl became true due header-row injection), calling unset()/destroy() will remove original row data from unaffected rows instead of restoring the initial DOM.

Useful? React with 👍 / 👎.

Comment thread src/CollapseTable.js
Comment on lines +416 to +420
for (const tr of this.headerRows) {
const firstCell = tr.cells[0];
const firstIsControl = firstCell && hasAllClasses(firstCell, this.options.classNames.control);
if (!firstIsControl) {
const th = createEl("th", this.options.classNames.control);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Hide control headers for every THEAD row

Control header cells are now inserted for each header row, but visibility toggling still targets only this.headerRow.cells[0] in _updateTogglesVisibility(). With multi-row <thead> and wide layouts where anyHidden is false, only the first header-row control cell is hidden while other injected control headers remain visible, causing a stray leading header column and header/body misalignment.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a393312a41

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/CollapseTable.js
Comment on lines +999 to +1002
const buttons = Array.from(ctrlCell.querySelectorAll("button"));
if (buttons.length > 1) {
buttons.slice(1).forEach(btn => btn.remove());
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid deleting non-toggle buttons during class migration

During structural reconfiguration, _migrateStructureClasses removes every button in the control cell except the first one, because it uses querySelectorAll("button") and blindly deletes buttons.slice(1). This will permanently remove author-provided secondary buttons (for example row action buttons) whenever class-related options are updated, even though those buttons are not duplicate collapse toggles.

Useful? React with 👍 / 👎.

Comment thread src/CollapseTable.js
for (const tb of this.tbodies) {
for (const row of Array.from(tb.rows)) {
if (row.classList.contains(this.options.classNames.details)) continue;
if (!this._insertedBodyControls.has(row)) continue;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clean up injected controls for rows added after mount

Teardown now deletes the first body cell only when the row is present in _insertedBodyControls, but rows that get a control cell later via _mountRowsInBody are never added to that WeakSet. If rows are appended while the table is mounted, destroy() skips removing those injected control cells and leaves the DOM structure mutated after unset().

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant