Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/pomodoro-timer/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ class GradientProgressBar extends Widget {

const attrs = styleToCellAttrs(this._style);

const label = this._showLabel ? ` ${Math.round(this._value * 100)}%` : '';
const label = this._showLabel ? ` ${Math.round(this._value * 100 + Number.EPSILON)}%` : '';

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
set -euo pipefail

printf '--- files ---\n'
git ls-files | rg 'examples/(pomodoro-timer/src/index\.tsx|todo-app/src/index\.ts)$|^examples/|^packages/|^src/' || true

printf '\n--- target snippets with line numbers ---\n'
sed -n '175,195p' examples/pomodoro-timer/src/index.tsx 2>/dev/null || true
printf '\n'
sed -n '95,115p' examples/todo-app/src/index.ts 2>/dev/null || true

printf '\n--- focused eps/round usage search ---\n'
rg -n "Number\.EPSILON|Math\.round\\(.*\\* 100|percentage|percent|pct" examples todo-app pomodoro-timer 2>/dev/null || true

printf '\n--- JavaScript rounding probe ---\n'
node - <<'JS'
const values = [0.145, 0.15, 0.245, 0.25];
for (const value of values) {
  const current = Math.round(value * 100 + Number.EPSILON);
  const correctedPre = Math.round((value + Number.EPSILON) * 100);
  const correctedScaled = Math.round(value * 100 + Number.EPSILON * 100);
  console.log(`${value} -> current=${current}, pre=${correctedPre}, scaled=${correctedScaled}`);
}
console.log('Number.EPSILON =', Number.EPSILON);
JS

Repository: Karanjot786/TermUI

Length of output: 247


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- files ---'
git ls-files | rg 'examples/(pomodoro-timer/src/index\.tsx|todo-app/src/index\.ts)$|^examples/|^packages/|^src/' || true

echo
echo '--- target snippets with line numbers ---'
sed -n '175,195p' examples/pomodoro-timer/src/index.tsx 2>/dev/null || true
echo
sed -n '95,115p' examples/todo-app/src/index.ts 2>/dev/null || true

echo
echo '--- focused eps/round usage search ---'
rg -n "Number\.EPSILON|Math\.round\\(.*\\* 100|percentage|percent|pct" examples todo-app pomodoro-timer 2>/dev/null || true

echo
echo '--- JavaScript rounding probe ---'
node - <<'JS'
const values = [0.145, 0.15, 0.245, 0.25];
for (const value of values) {
  const current = Math.round(value * 100 + Number.EPSILON);
  const correctedPre = Math.round((value + Number.EPSILON) * 100);
  const correctedScaled = Math.round(value * 100 + Number.EPSILON * 100);
  console.log(`${value} -> current=${current}, pre=${correctedPre}, scaled=${correctedScaled}`);
}
console.log('Number.EPSILON =', Number.EPSILON);
JS

Repository: Karanjot786/TermUI

Length of output: 48938


Scale the epsilon before percentage conversion in both renderers.

Adding Number.EPSILON after multiplying by 100 does not reliably fix half-percent boundaries. For example, 0.145 * 100 + Number.EPSILON still rounds to 14. Move the epsilon before * 100, or scale it by 100, and add a 0.145 regression test in both locations.

📍 Affects 2 files
  • examples/pomodoro-timer/src/index.tsx#L185-L185 (this comment)
  • examples/todo-app/src/index.ts#L107-L107
🤖 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 `@examples/pomodoro-timer/src/index.tsx` at line 185, Update the
percentage-label calculations in the renderers at
examples/pomodoro-timer/src/index.tsx:185-185 and
examples/todo-app/src/index.ts:107-107 so the epsilon is applied before
multiplying by 100 or is scaled by 100, ensuring 0.145 rounds to 15; add a
regression test covering 0.145 in both locations.

const barWidth = Math.max(0, width - label.length);
const filled = this._value <= 0 ? 0 : Math.round(barWidth * this._value);
const empty = barWidth - filled;
Expand Down
2 changes: 1 addition & 1 deletion examples/todo-app/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class CustomMultiProgress extends (MultiProgressClass as any) {
const value = Math.max(0, Math.min(1, item.value));
const filled = Math.round(barWidth * value);

const pct = Math.round(value * 100);
const pct = Math.round(value * 100 + Number.EPSILON);
const percentStr = ` ${pct}% `;
const showPct = barWidth >= percentStr.length;
const labelStart = showPct ? Math.floor((barWidth - percentStr.length) / 2) : -1;
Expand Down
2 changes: 1 addition & 1 deletion examples/widget-gallery/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class WidgetGalleryApp extends Widget {
}

// Tab switching: 1-6
const num = parseInt(event.key);
const num = parseInt(event.key, 10);
if (num >= 1 && num <= 6) {
this._switchTab(num - 1);
return true;
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/TreeSelect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ function _pathsEqual(a: number[], b: number[]): boolean {

function _valuesEqual(a: string[], b: string[]): boolean {
if (a.length !== b.length) return false;
const sortedA = [...a].sort();
const sortedA = [...a].sort((a, b) => a - b);
const sortedB = [...b].sort();
Comment on lines +185 to 186

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 | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail
npx --no-install tsc --noEmit

Repository: Karanjot786/TermUI

Length of output: 5708


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "Files:"
git ls-files packages/ui/src | rg 'TreeSelect|package\.json|tsconfig' || true

echo
echo "TreeSelect outline:"
if [ -f packages/ui/src/TreeSelect.ts ]; then
  ast-grep outline packages/ui/src/TreeSelect.ts --view compact || true
  wc -l packages/ui/src/TreeSelect.ts
  sed -n '1,240p' packages/ui/src/TreeSelect.ts
fi

echo
echo "Relevant compiler/config references:"
fd -a 'tsconfig.*|package.json' . | sed 's#^\./##' | rg '(^|/)(tsconfig.*|package\.json)$' | head -c 8000
for f in $(git ls-files | rg '(^|/)tsconfig.*\.json$|(^|/)package\.json$'); do
  if rg -n '"strict"|"tsconfigPaths"|"compilerOptions"|"compilerOptions":{"strict"' "$f" >/dev/null; then
    echo "--- $f ---"
    sed -n '1,160p' "$f"
  fi
done

Repository: Karanjot786/TermUI

Length of output: 35956


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "Files:"
git ls-files packages/ui/src | rg 'TreeSelect|package\.json|tsconfig' || true

echo
echo "TreeSelect outline:"
if [ -f packages/ui/src/TreeSelect.ts ]; then
  ast-grep outline packages/ui/src/TreeSelect.ts --view compact || true
  wc -l packages/ui/src/TreeSelect.ts
  sed -n '1,260p' packages/ui/src/TreeSelect.ts
fi

echo
echo "Relevant compiler/config references:"
for f in $(git ls-files | rg '(^|/)tsconfig[^/]*\.json$|(^|/)package\.json$'); do
  if rg -n '"strict"|"compilerOptions"|"extends"|"include"|"files"' "$f" >/dev/null; then
    echo "--- $f ---"
    sed -n '1,220p' "$f"
  fi
done

echo
echo "Package scripts:"
for f in package.json packages/*/package.json; do
  [ -f "$f" ] || continue
  if rg -n '"scripts"|"typecheck"|"tsc"' "$f" >/dev/null; then
    echo "--- $f ---"
    jq -r '.scripts // empty | to_entries[]? | "\(.key)=\(.value)"' "$f"
  fi
done

echo
echo "TypeScript availability/version:"
command -v tsc || true
if command -v npx >/dev/null; then
  npx --yes --package=typescript@latest tsc --version
fi

Repository: Karanjot786/TermUI

Length of output: 44939


🌐 Web query:

TypeScript arithmetic operator string operands strict mode subtract strings error

💡 Result:

In TypeScript, using arithmetic operators (such as -, *, /) with strings will result in a compilation error [1][2][3]. The specific error you will encounter is: "The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type" (or a similar message regarding the right-hand side) [1][2][4]. Unlike the addition operator (+), which TypeScript allows with strings because it performs string concatenation [5][6][7], other arithmetic operators are reserved for numeric types (including number, bigint, any, and numeric enums) [1][8][9]. This restriction is in place to prevent unintended implicit type coercion that can lead to runtime bugs [1][9]. To resolve this error, you must explicitly convert your string operands to numbers before performing the arithmetic operation [2][4][3]. Common methods include: * Using Number(value) or parseFloat(value)/parseInt(value) [10]. * Using the unary plus (+) operator, such as +stringVar1 - +stringVar2 [10]. If you are attempting to sort arrays of strings, you should use localeCompare instead of subtraction [10]. ### Summary of Differences * + Operator: Allowed with strings because it supports concatenation [5][6]. * -, *, / Operators: Disallowed with strings; attempting to use them will trigger a TypeScript compilation error [1][8][9].

Citations:


🌐 Web query:

site:github.com/microsoft/TypeScript String.prototype.sort comparator undefined undefined localeCompare sort behavior source

💡 Result:

There is no String.prototype.sort method in JavaScript [1][2]. The sort method is a property of Array.prototype (and TypedArray.prototype) [3][4][5]. Regarding the behavior of Array.prototype.sort: 1. Default Sorting: If no comparator function is provided, the sort method converts all array elements into strings and compares their sequences of UTF-16 code unit values [3][4][5]. This often leads to unexpected results when sorting numbers, as "10" will be sorted before "2" [3][6][7]. 2. Handling of undefined values: When sorting an array that contains undefined values, the ECMAScript specification dictates that all undefined elements are moved to the end of the array [8]. The compare function, if provided, is never called with undefined values [8]. 3. localeCompare: The String.prototype.localeCompare method is commonly used within a custom comparator function to handle language-sensitive string sorting [4]. For example: array.sort((a, b) => a.localeCompare(b)); This approach ensures that strings are sorted according to specific locale rules rather than raw UTF-16 code unit values [4].

Citations:


Use one typed comparator for both arrays.

_valuesEqual receives string[], so a - b is invalid under TypeScript strict mode. The second sort() also uses a different string sort order than localCompare, so duplicate value arrays can compare as unequal.

Define one comparator with a typed parameter, and pass it to both sort calls. Use Number(...) only if TreeSelect values are guaranteed numeric strings.

Proposed fix
-    const sortedA = [...a].sort((a, b) => a - b);
-    const sortedB = [...b].sort();
+    const compareValues = (left: string, right: string): number =>
+        Number(left) - Number(right);
+    const sortedA = [...a].sort(compareValues);
+    const sortedB = [...b].sort(compareValues);
🧰 Tools
🪛 GitHub Actions: CI / 0_build-and-test.txt

[error] 185-185: TypeScript DTS build failed: TS2362 and TS2363 indicate that the left- and right-hand operands of an arithmetic operation are not typed as any, number, bigint, or an enum. The '@termuijs/ui' 'tsup' build exited with code 1.

🪛 GitHub Actions: CI / build-and-test

[error] 185-185: TypeScript errors TS2362 and TS2363: arithmetic operands at columns 43 and 47 are not typed as any, number, bigint, or an enum. The tsup DTS build failed, causing 'bun run build' to exit with code 1.

🤖 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/TreeSelect.ts` around lines 185 - 186, Update _valuesEqual to
define one typed comparator for string values and pass it to both sortedA and
sortedB sort calls, ensuring strict TypeScript compatibility and identical
ordering for duplicate-array comparisons. Preserve string comparison semantics;
only convert with Number if TreeSelect values are explicitly guaranteed to be
numeric strings.

Source: Coding guidelines

for (let i = 0; i < sortedA.length; i++) {
if (sortedA[i] !== sortedB[i]) return false;
Expand Down
Loading