Skip to content

fix: address 5 upstream issues (batch rollback, throttle, CheckboxGroup, Tree, Color) - #3239

Open
tmdeveloper007 wants to merge 1 commit into
Karanjot786:mainfrom
tmdeveloper007:fix-upstream-issues
Open

fix: address 5 upstream issues (batch rollback, throttle, CheckboxGroup, Tree, Color)#3239
tmdeveloper007 wants to merge 1 commit into
Karanjot786:mainfrom
tmdeveloper007:fix-upstream-issues

Conversation

@tmdeveloper007

@tmdeveloper007 tmdeveloper007 commented Jul 28, 2026

Copy link
Copy Markdown

Summary

Addresses 5 pending upstream issues with targeted bug fixes.

Changes

File Issue Fix
packages/store/src/store.ts #3233 Always call flushBatch(threw) on error regardless of batch nesting depth
packages/core/src/utils/throttle.ts #3229 Added hasNewCalls flag; trailing fires only when new calls arrived during wait interval
packages/ui/src/CheckboxGroup.ts #3232 Subscribe handleKey to events emitter
packages/ui/src/Tree.ts #3231 Subscribe handleKey to events emitter + add handleKey method
packages/core/src/style/Color.ts #3230 Use g_c/b_c for green/blue channels in grayscale distance calculation

Tests

All 7 throttle tests pass; 49 CheckboxGroup tests pass; 1 batch test pass; build and typecheck pass.


Created by GSSOC Auto-PR cron automation

Summary by CodeRabbit

  • New Features

    • Improved keyboard navigation for tree controls, including cursor movement, selection confirmation, and expand/collapse actions.
    • Improved keyboard event handling for checkbox groups.
  • Bug Fixes

    • Corrected grayscale color matching for more accurate terminal color output.
    • Fixed throttled actions so trailing calls consistently use the latest input.
    • Improved rollback behavior when errors occur during nested batched updates.

…eckboxGroup, Tree, Color)

- fix(store): always call flushBatch(threw) on error regardless of batch depth (Karanjot786#3233)
- fix(core): throttle trailing call fires only when new calls arrived during wait (Karanjot786#3229)
  - Added hasNewCalls flag to track if subsequent calls came in after leading call
  - Trailing fires when hasNewCalls || !leading
- fix(ui): CheckboxGroup: subscribe handleKey to events emitter (Karanjot786#3232)
- fix(ui): Tree: subscribe handleKey to events emitter + add handleKey method (Karanjot786#3231)
- fix(core): Color.ts: use g_c/b_c for green/blue channels in grayscale distance (Karanjot786#3230)

Refs: upstream Karanjot786#3230, Karanjot786#3229, Karanjot786#3232, Karanjot786#3231, Karanjot786#3233
@github-actions github-actions Bot added type:bug +10 pts. Bug fix. area:core @termuijs/core area:ui @termuijs/ui labels Jul 28, 2026
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR corrects grayscale ANSI color matching, tracks trailing throttle calls explicitly, changes nested batch rollback handling, and adds keyboard event wiring and key actions for CheckboxGroup and Tree widgets.

Changes

Core utility corrections

Layer / File(s) Summary
Color and throttle behavior
packages/core/src/style/Color.ts, packages/core/src/utils/throttle.ts
Grayscale color distance calculations use the correct channel values, and throttling tracks additional calls during an active timer.

Batch rollback behavior

Layer / File(s) Summary
Nested batch error handling
packages/store/src/store.ts
Batch errors now invoke rollback flushing regardless of remaining batch depth.

Widget keyboard handling

Layer / File(s) Summary
Widget keyboard controls
packages/ui/src/CheckboxGroup.ts, packages/ui/src/Tree.ts
CheckboxGroup subscribes to key events, while Tree handles navigation, confirmation, and expansion key actions.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related issues

Possibly related PRs

Suggested labels: gssoc:approved, quality:clean, level:intermediate, area:widgets, area:store, type:testing

Suggested reviewers: karanjot786

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description summarizes changes and tests, but it omits required template sections like Closes # and Which package(s)?. Add the linked issue number, affected package(s), type of change, and complete the required checklist/notes sections.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise, specific, and matches the five bug-fix areas in the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/store/src/store.ts (1)

76-76: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Add regression coverage for caught nested batch errors.

At Line 76, flushBatch(true) now runs while an outer batch may still be active. Because _batchStores is shared across nesting levels, this can roll back outer updates when an inner error is caught. Existing tests cover outer rejection, but not this changed path; add a test that defines the expected state and subscriber behavior for a caught inner error.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/store/src/store.ts` at line 76, Add regression coverage around
flushBatch in the store batching tests for a caught error inside a nested batch.
Define an outer batch that applies updates, trigger and catch an inner batch
error, then verify the expected final store state and subscriber notifications,
ensuring outer updates are preserved and the inner failure does not incorrectly
roll them back.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/src/utils/throttle.ts`:
- Around line 30-40: Reset the hasNewCalls flag inside throttled.cancel()
alongside the timer and argument cleanup, so cancellation fully clears the
throttle state. Add a regression test covering a second call followed by cancel
and then a new leading call, ensuring no stale trailing invocation occurs.

In `@packages/ui/src/Tree.ts`:
- Around line 23-32: The handleKey method should accept the core KeyEvent type
instead of an inline object, and its switch should use the canonical 'space' key
value rather than ' '. Update the import and handler case while preserving the
existing enter/space behavior.

---

Nitpick comments:
In `@packages/store/src/store.ts`:
- Line 76: Add regression coverage around flushBatch in the store batching tests
for a caught error inside a nested batch. Define an outer batch that applies
updates, trigger and catch an inner batch error, then verify the expected final
store state and subscriber notifications, ensuring outer updates are preserved
and the inner failure does not incorrectly roll them back.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ce7ba88d-d0e2-4e3c-893b-58e28373bcdd

📥 Commits

Reviewing files that changed from the base of the PR and between 48f63a1 and afb0af0.

📒 Files selected for processing (5)
  • packages/core/src/style/Color.ts
  • packages/core/src/utils/throttle.ts
  • packages/store/src/store.ts
  • packages/ui/src/CheckboxGroup.ts
  • packages/ui/src/Tree.ts

Comment on lines +30 to +40
let hasNewCalls = false;

const throttled = function (...args: Parameters<T>) {
lastArgs = args;
if (timer) hasNewCalls = true;
if (!timer) {
if (leading) func(...args);
timer = setTimeout(() => {
timer = undefined;
if (lastArgs !== args || !leading) func(...lastArgs!);
if (hasNewCalls || !leading) func(...lastArgs!);
hasNewCalls = false;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reset hasNewCalls when cancelling.

throttled.cancel() clears the timer and arguments at Lines 46-50 but leaves this new flag set. After a cancelled window that received a second call, the next independent leading call can incorrectly trigger a trailing invocation. Reset hasNewCalls = false in cancel() and cover this sequence with a regression test.

Proposed fix
 throttled.cancel = () => {
     clearTimeout(timer);
     timer = undefined;
     lastArgs = undefined;
+    hasNewCalls = false;
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let hasNewCalls = false;
const throttled = function (...args: Parameters<T>) {
lastArgs = args;
if (timer) hasNewCalls = true;
if (!timer) {
if (leading) func(...args);
timer = setTimeout(() => {
timer = undefined;
if (lastArgs !== args || !leading) func(...lastArgs!);
if (hasNewCalls || !leading) func(...lastArgs!);
hasNewCalls = false;
throttled.cancel = () => {
clearTimeout(timer);
timer = undefined;
lastArgs = undefined;
hasNewCalls = false;
};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/utils/throttle.ts` around lines 30 - 40, Reset the
hasNewCalls flag inside throttled.cancel() alongside the timer and argument
cleanup, so cancellation fully clears the throttle state. Add a regression test
covering a second call followed by cancel and then a new leading call, ensuring
no stale trailing invocation occurs.

Comment thread packages/ui/src/Tree.ts
Comment on lines +23 to +32
private handleKey(event: { key: string }): void {
switch (event.key) {
case 'up':
this.selectPrev();
break;
case 'down':
this.selectNext();
break;
case 'enter':
case ' ':

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n -C2 "KeyEvent|case 'space'|emit\\('key'" packages/core/src packages/ui/src

Repository: Karanjot786/TermUI

Length of output: 50375


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- packages/ui/src/Tree.ts outline ---'
ast-grep outline packages/ui/src/Tree.ts || true

printf '%s\n' '--- packages/ui/src/Tree.ts lines 1-220 ---'
cat -n packages/ui/src/Tree.ts

printf '%s\n' '--- relevant imports in ui package files ---'
for f in packages/ui/src/Tree.ts packages/ui/src/Tree.test.ts; do
  if [ -f "$f" ]; then
    echo "### $f"
    sed -n '1,80p' "$f"
  else
    echo "missing: $f"
  fi
done

printf '%s\n' '--- KeyEvent key maps for space / printable chars ---'
cat -n packages/core/src/input/KeyMap.ts | sed -n '1,130p'

Repository: Karanjot786/TermUI

Length of output: 14550


Use KeyEvent and the canonical 'space' key.

Tree is already subscribing to the core 'key' event, whose contract is KeyEvent, and the input parser emits Space as 'space', not ' '. Keep the component contract aligned and normalize the handler case.

Proposed fix
-    private handleKey(event: { key: string }): void {
+    private handleKey(event: KeyEvent): void {
...
-            case ' ':
+            case 'space':
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private handleKey(event: { key: string }): void {
switch (event.key) {
case 'up':
this.selectPrev();
break;
case 'down':
this.selectNext();
break;
case 'enter':
case ' ':
private handleKey(event: KeyEvent): void {
switch (event.key) {
case 'up':
this.selectPrev();
break;
case 'down':
this.selectNext();
break;
case 'enter':
case 'space':
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/Tree.ts` around lines 23 - 32, The handleKey method should
accept the core KeyEvent type instead of an inline object, and its switch should
use the canonical 'space' key value rather than ' '. Update the import and
handler case while preserving the existing enter/space behavior.

Source: Coding guidelines

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

Labels

area:core @termuijs/core area:ui @termuijs/ui type:bug +10 pts. Bug fix.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant