Skip to content
Merged
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
5 changes: 5 additions & 0 deletions .changeset/strong-stamps-occur.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@stackoverflow/stacks-utils": patch
---

formatCount support for negative values
4 changes: 4 additions & 0 deletions packages/stacks-utils/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ formatCount(9999); // "9,999"
formatCount(10000); // "10k"
formatCount(12345); // "12.3k"
formatCount(1234567); // "1.2m"

// Negative numbers
formatCount(-1234); // "-1,234"
formatCount(-12345); // "-12.3k"
```

You can also import from the class:
Expand Down
15 changes: 15 additions & 0 deletions packages/stacks-utils/src/NumberFormatter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,21 @@ describe("NumberFormatter.formatCount", () => {
});
});

describe("negative numbers", () => {
it("should format negative numbers in standard format", () => {
expect(NumberFormatter.formatCount(-42)).toBe("-42");
expect(NumberFormatter.formatCount(-999)).toBe("-999");
expect(NumberFormatter.formatCount(-1234)).toBe("-1,234");
expect(NumberFormatter.formatCount(-9999)).toBe("-9,999");
});

it("should format negative numbers in compact format", () => {
expect(NumberFormatter.formatCount(-10000)).toBe("-10k");
expect(NumberFormatter.formatCount(-12345)).toBe("-12.3k");
expect(NumberFormatter.formatCount(-1234567)).toBe("-1.2m");
});
});

describe("convenience function export", () => {
it("should work with the exported formatCount function", () => {
expect(formatCount(1234)).toBe("1,234");
Expand Down
11 changes: 7 additions & 4 deletions packages/stacks-utils/src/NumberFormatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,21 @@ export class NumberFormatter {
* @param count - The number to format
* @param compactThreshold - (Optional) The number at which to switch from standard to compact format
* @returns A formatted string:
* - Less than 10,000: standard format with commas (e.g., "1,234", "999")
* - 10,000 or more: compact format with lowercase suffixes (e.g., "10k", "1.2m")
* - Less than 10,000: standard format with commas (e.g., "1,234", "999", "-1,234")
* - 10,000 or more: compact format with lowercase suffixes (e.g., "10k", "1.2m", "-10k")
*/
public static formatCount(
count: number,
compactThreshold: number = 10000
): string {
const absoluteValue = Math.abs(count);
const sign = count < 0 ? "-" : "";

for (const formatter of NumberFormatter.getFormatters(
compactThreshold
)) {
if (formatter.condition(count)) {
return formatter.format(count);
if (formatter.condition(absoluteValue)) {
return sign + formatter.format(absoluteValue);
}
}
return count.toString(); // should never reach here
Expand Down