Skip to content

Remove any from Array.isArray, fix violations#6760

Merged
ckifer merged 4 commits into
mainfrom
arrayisarray
Dec 12, 2025
Merged

Remove any from Array.isArray, fix violations#6760
ckifer merged 4 commits into
mainfrom
arrayisarray

Conversation

@PavelVanecek

@PavelVanecek PavelVanecek commented Dec 10, 2025

Copy link
Copy Markdown
Collaborator

Description

I discovered that vanilla typing for Array.isArray turns all read-only arrays into any[] (microsoft/TypeScript#17002) which is unfortunate and creates many holes in our typing so I added a custom type and fixed the newly discovered violations. It cascaded a little but it looks like it compiles just fine now.

Related Issue

#6645

Summary by CodeRabbit

  • Bug Fixes

    • Added null/undefined safety in tooltips and custom formatters; improved duplicate detection for mixed-type values.
  • Refactor

    • Strengthened type safety for animation styles, stacked-area data handling, and selector logic; internal axis/item resolution simplified.
  • Chores

    • Removed obsolete utility functions and cleaned up related tests and snapshots.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Dec 10, 2025

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@PavelVanecek has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 7 minutes and 44 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between c2c0754 and e6fcca1.

📒 Files selected for processing (1)
  • test/util/isArray.spec-d.ts (1 hunks)

Walkthrough

Refactors selector architecture to resolve axes from GraphicalItemId, adds a new graphicalItemSelectors module, changes area/stacked-data types to StackDataPoint tuples, renames/adds chart-data selector variants, tightens TypeScript types, and adjusts many selector consumers and tests accordingly.

Changes

Cohort / File(s) Summary
Snapshot Manifests
scripts/snapshots/es6Files.txt, scripts/snapshots/libFiles.txt, scripts/snapshots/typesFiles.txt
Added references for graphicalItemSelectors (ES6, lib, and types snapshots).
New Selectors Module
src/state/selectors/graphicalItemSelectors.ts
New selectors selectXAxisIdFromGraphicalItemId and selectYAxisIdFromGraphicalItemId to map a GraphicalItemId → axis IDs.
Area Selector Refactor
src/state/selectors/areaSelectors.ts, src/cartesian/Area.tsx
selectArea and related selectors now take (state, id, isPanorama); stacked data typed as ReadonlyArray<StackDataPoint> and AreaPointItem.value → [number, number]; introduced numerical-axis helpers and updated data selection to position-based data selector.
Bar & Other Selector Updates
src/state/selectors/barSelectors.ts, src/state/selectors/lineSelectors.ts, src/state/selectors/scatterSelectors.ts, src/state/selectors/axisSelectors.ts, src/state/selectors/combiners/combineTooltipPayload.ts
Replaced bar-specific axis-id helpers with GraphicalItemId-based selectors; updated imports to new data selector variants (Position3/Position4); removed fromMainValueToError from axisSelectors; enhanced tooltip payload construction for array items.
Data Selector Variants
src/state/selectors/dataSelectors.ts, test/cartesian/Bar.truncateByDomain.spec.ts
Renamed selectChartDataWithIndexesIfNotInPanoramaselectChartDataWithIndexesIfNotInPanoramaPosition4 and added ...Position3 variant with a simplified parameter list; updated consumers and tests to use the new names.
Type System & API Tightening
src/animation/AnimationManager.ts, src/component/DefaultTooltipContent.tsx, types.d.ts, test/helper/expectStackGroups.ts
Tightened ReactSmoothStyle to `string
Utility Changes
src/util/DataUtils.ts, src/util/scale/getNiceTickValues.ts, src/util/scale/util/utils.ts
hasDuplicate now keys cache with String(...); removed exported reverse util and replaced usages with in-place Array.prototype.reverse().
Component & UI Minor Fixes
storybook/stories/API/component/Legend.stories.tsx, www/src/components/.../MassBarChartCustomTicks.tsx
Added undefined guard in legend tooltip formatter and widened kgToYottagram to accept `number
Tests Updated
test/chart/AreaChart*.spec.tsx, test/state/selectors/areaSelectors.spec.tsx, test/cartesian/Bar.truncateByDomain.spec.tsx, test/helper/expectStackGroups.ts, test/util/*
Updated tests to new selector signatures (use area ids), added Area ids in tests, removed reverse and fromMainValueToError tests, and strengthened test helper typings.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45–75 minutes

  • Areas needing extra attention:
    • src/state/selectors/areaSelectors.ts — new axis-resolution flow, stacked-data mapping, and changed AreaPointItem types.
    • Cross-module usages of the new data selector variants (Position3/Position4) — ensure correct variant per consumer.
    • src/cartesian/Area.tsx — consumption of stacked tuples and computeArea signature change.
    • Tests that were updated to use id-driven selectors — validate coverage and expected data shapes.

Possibly related PRs

Suggested labels

typescript

Suggested reviewers

  • ckifer

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.38% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding a custom Array.isArray type and fixing the resulting violations it exposed.
Description check ✅ Passed The description adequately covers the problem, motivation, and links to the related issue, though some testing details are minimal.

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 and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/state/selectors/combiners/combineTooltipPayload.ts (1)

90-116: Refine the unknown type instead of suppressing errors.

The multiple @ts-expect-error suppressions (lines 94, 96, 106, 108, 112) violate the coding guideline that requires preferring unknown over any and refining the type. These suppressions functionally disable type checking, which is equivalent to using any.

As per coding guidelines, you should define a proper type for the array items and use type guards to validate the structure.

Consider this approach:

+interface TooltipPayloadItem {
+  name: unknown;
+  unit: unknown;
+  dataKey: DataKey<any>;
+  payload: unknown;
+}
+
+function isTooltipPayloadItem(item: unknown): item is TooltipPayloadItem {
+  return (
+    typeof item === 'object' &&
+    item !== null &&
+    'name' in item &&
+    'unit' in item &&
+    'dataKey' in item &&
+    'payload' in item
+  );
+}
+
 if (Array.isArray(tooltipPayload)) {
   tooltipPayload.forEach(item => {
+    if (!isTooltipPayloadItem(item)) {
+      return;
+    }
     const newSettings: TooltipEntrySettings = {
       ...settings,
-      // @ts-expect-error we're assuming that item has name and unit properties
       name: item.name,
-      // @ts-expect-error we're assuming that item has name and unit properties
       unit: item.unit,
       color: undefined,
       fill: undefined,
     };
     agg.push(
       getTooltipEntry({
         tooltipEntrySettings: newSettings,
-        // @ts-expect-error we're assuming that item has name and unit properties
         dataKey: item.dataKey,
-        // @ts-expect-error we're assuming that item has name and unit properties
         payload: item.payload,
         // @ts-expect-error getValueByDataKey does not validate the output type
         value: getValueByDataKey(item.payload, item.dataKey),
-        // @ts-expect-error we're assuming that item has name and unit properties
         name: item.name,
       }),
     );
   });
src/component/DefaultTooltipContent.tsx (1)

19-25: Type signature now correctly reflects runtime behavior where value and name can be undefined.

The Payload interface defines both name and value as optional properties, making it accurate for the Formatter type to include undefined in their signatures. This improves type safety for consumers implementing custom formatters.

Consider documenting this as a breaking change if updating from a previous version where these parameters were not typed as optional. Consumers with existing custom formatters must now handle undefined values explicitly.

🧹 Nitpick comments (6)
test/helper/expectStackGroups.ts (1)

59-117: Normalize error handling and matcher return shape in all three matchers

The new received typings for rechartsStackedDataMatcher, rechartsStackedSeriesMatcher, and rechartsStackedSeriesPointMatcher are a good improvement, but the catch blocks can be made type-safe and consistent with the declared matcher result type:

  • e in catch (e) is effectively untyped (often any), which conflicts with the repo’s preference for unknown.
  • In rechartsStackedSeriesMatcher and rechartsStackedSeriesPointMatcher the declared return type uses message: () => string, but the error branch returns message: e.message, which is a string (or any), not a function.

You can address both points with a small refactor:

-function rechartsStackedDataMatcher(received: ExpectedStackedData, expected: ExpectedStackedData) {
+function rechartsStackedDataMatcher(received: ExpectedStackedData, expected: ExpectedStackedData) {
   try {
     expectStackedData(received, expected);
     return {
       pass: true,
       message: () => 'Expected stack groups to not match',
     };
-  } catch (e) {
+  } catch (e: unknown) {
+    const message = e instanceof Error ? e.message : String(e);
     // Uncomment the `debugger` here to see the actual error message, or place a breakpoint in your IDE
     // debugger;
     return {
       pass: false,
-      message: e.message,
+      message: () => message,
     };
   }
 }
 
 function rechartsStackedSeriesMatcher(
-  received: ExpectedStackedDataSeries,
+  received: ExpectedStackedDataSeries,
   expected: ExpectedStackedDataSeries,
 ): { pass: boolean; message: () => string } {
   try {
     expectStackedSeries(received, expected);
     return {
       pass: true,
       message: () => 'Expected stack series to not match',
     };
-  } catch (e) {
+  } catch (e: unknown) {
+    const message = e instanceof Error ? e.message : String(e);
     // Uncomment the `debugger` here to see the actual error message, or place a breakpoint in your IDE
     // debugger;
     return {
       pass: false,
-      message: e.message,
+      message: () => message,
     };
   }
 }
 
 function rechartsStackedSeriesPointMatcher(
-  received: StackDataPoint,
+  received: StackDataPoint,
   expected: StackDataPoint,
 ): { pass: boolean; message: () => string } {
   try {
     if (!Array.isArray(received)) {
       throw new Error(`stackedSeriesPoint error: expected ${received} to be an array`);
     }
     expect(seriesPointToTuple(received)).toEqual(expected);
     return {
       pass: true,
       message: () => 'Expected stack series point to not match',
     };
-  } catch (e) {
+  } catch (e: unknown) {
+    const message = e instanceof Error ? e.message : String(e);
     // Uncomment the `debugger` here to see the actual error message, or place a breakpoint in your IDE
     // debugger;
     return {
       pass: false,
-      message: e.message,
+      message: () => message,
     };
   }
 }

This keeps the matchers’ public typings accurate, avoids leaking any through the catch variable, and still surfaces the original error message. As per coding guidelines, this also aligns with the “no any” rule and explicit, accurate return typing in TS.

src/util/DataUtils.ts (1)

92-98: Consider caching the string conversion to avoid duplicate calls.

String(ary[i]) is called twice per iteration. While this is a minor concern, you could store the result in a variable for a slight efficiency gain.

   for (let i = 0; i < len; i++) {
-    if (!cache[String(ary[i])]) {
-      cache[String(ary[i])] = true;
+    const key = String(ary[i]);
+    if (!cache[key]) {
+      cache[key] = true;
     } else {
       return true;
     }
   }
test/state/selectors/areaSelectors.spec.tsx (1)

12-13: Tests aligned with id‑based selectArea API

Updating all usages to selectArea(state, 'area-0', false) matches the new selector signature and stays consistent with the <Area id="area-0" /> in the test chart setup. The existing expectations and call‑count assertions continue to validate selector stability correctly.

If you touch this file again, consider hoisting 'area-0' into a shared constant to avoid accidental mismatches between chart JSX and selector calls.

Also applies to: 25-25, 137-137

src/state/selectors/graphicalItemSelectors.ts (1)

1-11: New graphical‑item axis selectors are correct; possible micro‑DRY

Both selectXAxisIdFromGraphicalItemId and selectYAxisIdFromGraphicalItemId correctly scan state.graphicalItems.cartesianItems by id and fall back to defaultAxisId when no match or axis id is present, which is a sensible default for cartesian charts.

If these are often called together for the same id, consider factoring out a small helper like selectCartesianItemById so you only traverse cartesianItems once per id and then read both xAxisId and yAxisId from that result.

test/cartesian/Bar.truncateByDomain.spec.tsx (1)

164-172: Test name doesn't match the selector name.

The test name still references the old selector name selectChartDataWithIndexesIfNotInPanorama, but it now tests selectChartDataWithIndexesIfNotInPanoramaPosition4. Consider updating the test name for consistency.

-    test('selectChartDataWithIndexesIfNotInPanorama', () => {
+    test('selectChartDataWithIndexesIfNotInPanoramaPosition4', () => {
src/state/selectors/areaSelectors.ts (1)

70-78: Unused isPanorama parameter in selector signature.

The isPanorama parameter at position 3 is unused in this selector but is required for positional alignment with createSelector composition. Consider adding a brief comment explaining this pattern for maintainability.

 const selectSynchronisedAreaSettings: (
   state: RechartsRootState,
   id: GraphicalItemId,
   isPanorama: boolean,
 ) => AreaSettings | undefined = createSelector(
-  [selectUnfilteredCartesianItems, pickAreaId],
+  // isPanorama is unused here but required for selector position alignment in createSelector
+  [selectUnfilteredCartesianItems, pickAreaId],
   (graphicalItems, id: GraphicalItemId) =>
     graphicalItems.filter(item => item.type === 'area').find(item => item.id === id),
 );
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ee0b17b and 1de4be9.

📒 Files selected for processing (28)
  • scripts/snapshots/es6Files.txt (1 hunks)
  • scripts/snapshots/libFiles.txt (1 hunks)
  • scripts/snapshots/typesFiles.txt (1 hunks)
  • src/animation/AnimationManager.ts (1 hunks)
  • src/cartesian/Area.tsx (4 hunks)
  • src/component/DefaultTooltipContent.tsx (2 hunks)
  • src/state/selectors/areaSelectors.ts (6 hunks)
  • src/state/selectors/axisSelectors.ts (3 hunks)
  • src/state/selectors/barSelectors.ts (9 hunks)
  • src/state/selectors/combiners/combineTooltipPayload.ts (2 hunks)
  • src/state/selectors/dataSelectors.ts (2 hunks)
  • src/state/selectors/graphicalItemSelectors.ts (1 hunks)
  • src/state/selectors/lineSelectors.ts (2 hunks)
  • src/state/selectors/scatterSelectors.ts (2 hunks)
  • src/util/DataUtils.ts (1 hunks)
  • src/util/scale/getNiceTickValues.ts (4 hunks)
  • src/util/scale/util/utils.ts (0 hunks)
  • storybook/stories/API/component/Legend.stories.tsx (1 hunks)
  • test/cartesian/Bar.truncateByDomain.spec.tsx (2 hunks)
  • test/chart/AreaChart.spec.tsx (6 hunks)
  • test/chart/AreaChart.stacked.spec.tsx (10 hunks)
  • test/helper/expectStackGroups.ts (4 hunks)
  • test/state/selectors/areaSelectors.spec.tsx (3 hunks)
  • test/util/errorValue.spec.ts (1 hunks)
  • test/util/isArray.spec-d.ts (1 hunks)
  • test/util/scale/utils.spec.ts (1 hunks)
  • types.d.ts (1 hunks)
  • www/src/components/GuideView/DomainAndTicks/MassBarChartCustomTicks.tsx (1 hunks)
💤 Files with no reviewable changes (1)
  • src/util/scale/util/utils.ts
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.{ts,tsx}: Never use any type (implicit or explicit) in TypeScript code
Prefer unknown over any and refine the type in TypeScript
Type function parameters and return values explicitly in TypeScript, do not rely on implicit any or inference; exceptions are React components and trivial functions
Do not use as type assertions in TypeScript; the only exception is as const

Files:

  • src/animation/AnimationManager.ts
  • src/state/selectors/graphicalItemSelectors.ts
  • src/state/selectors/combiners/combineTooltipPayload.ts
  • test/util/isArray.spec-d.ts
  • storybook/stories/API/component/Legend.stories.tsx
  • types.d.ts
  • test/chart/AreaChart.stacked.spec.tsx
  • www/src/components/GuideView/DomainAndTicks/MassBarChartCustomTicks.tsx
  • src/util/DataUtils.ts
  • src/util/scale/getNiceTickValues.ts
  • test/state/selectors/areaSelectors.spec.tsx
  • test/cartesian/Bar.truncateByDomain.spec.tsx
  • test/util/scale/utils.spec.ts
  • src/state/selectors/scatterSelectors.ts
  • src/state/selectors/axisSelectors.ts
  • test/helper/expectStackGroups.ts
  • src/component/DefaultTooltipContent.tsx
  • test/chart/AreaChart.spec.tsx
  • src/cartesian/Area.tsx
  • src/state/selectors/lineSelectors.ts
  • test/util/errorValue.spec.ts
  • src/state/selectors/barSelectors.ts
  • src/state/selectors/dataSelectors.ts
  • src/state/selectors/areaSelectors.ts
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Ensure code lints by running npm run lint and follows Airbnb's Style Guide

Files:

  • src/animation/AnimationManager.ts
  • src/state/selectors/graphicalItemSelectors.ts
  • src/state/selectors/combiners/combineTooltipPayload.ts
  • test/util/isArray.spec-d.ts
  • storybook/stories/API/component/Legend.stories.tsx
  • types.d.ts
  • test/chart/AreaChart.stacked.spec.tsx
  • www/src/components/GuideView/DomainAndTicks/MassBarChartCustomTicks.tsx
  • src/util/DataUtils.ts
  • src/util/scale/getNiceTickValues.ts
  • test/state/selectors/areaSelectors.spec.tsx
  • test/cartesian/Bar.truncateByDomain.spec.tsx
  • test/util/scale/utils.spec.ts
  • src/state/selectors/scatterSelectors.ts
  • src/state/selectors/axisSelectors.ts
  • test/helper/expectStackGroups.ts
  • src/component/DefaultTooltipContent.tsx
  • test/chart/AreaChart.spec.tsx
  • src/cartesian/Area.tsx
  • src/state/selectors/lineSelectors.ts
  • test/util/errorValue.spec.ts
  • src/state/selectors/barSelectors.ts
  • src/state/selectors/dataSelectors.ts
  • src/state/selectors/areaSelectors.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Do not hardcode any strings or formatting choices in library code; users should provide localized strings as desired

Files:

  • src/animation/AnimationManager.ts
  • src/state/selectors/graphicalItemSelectors.ts
  • src/state/selectors/combiners/combineTooltipPayload.ts
  • src/util/DataUtils.ts
  • src/util/scale/getNiceTickValues.ts
  • src/state/selectors/scatterSelectors.ts
  • src/state/selectors/axisSelectors.ts
  • src/component/DefaultTooltipContent.tsx
  • src/cartesian/Area.tsx
  • src/state/selectors/lineSelectors.ts
  • src/state/selectors/barSelectors.ts
  • src/state/selectors/dataSelectors.ts
  • src/state/selectors/areaSelectors.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (DEVELOPING.md)

All imports from recharts must use the public API entry point; imports from internal paths like recharts/types/* or recharts/src/* are not allowed

Files:

  • src/animation/AnimationManager.ts
  • src/state/selectors/graphicalItemSelectors.ts
  • src/state/selectors/combiners/combineTooltipPayload.ts
  • test/util/isArray.spec-d.ts
  • storybook/stories/API/component/Legend.stories.tsx
  • types.d.ts
  • test/chart/AreaChart.stacked.spec.tsx
  • www/src/components/GuideView/DomainAndTicks/MassBarChartCustomTicks.tsx
  • src/util/DataUtils.ts
  • src/util/scale/getNiceTickValues.ts
  • test/state/selectors/areaSelectors.spec.tsx
  • test/cartesian/Bar.truncateByDomain.spec.tsx
  • test/util/scale/utils.spec.ts
  • src/state/selectors/scatterSelectors.ts
  • src/state/selectors/axisSelectors.ts
  • test/helper/expectStackGroups.ts
  • src/component/DefaultTooltipContent.tsx
  • test/chart/AreaChart.spec.tsx
  • src/cartesian/Area.tsx
  • src/state/selectors/lineSelectors.ts
  • test/util/errorValue.spec.ts
  • src/state/selectors/barSelectors.ts
  • src/state/selectors/dataSelectors.ts
  • src/state/selectors/areaSelectors.ts
storybook/stories/**/*.stories.tsx

📄 CodeRabbit inference engine (CONTRIBUTING.md)

storybook/stories/**/*.stories.tsx: Use Storybook for smoke tests and add play functions with assertions for actual tests
Update Storybook stories when APIs have been changed to ensure they work as expected

Files:

  • storybook/stories/API/component/Legend.stories.tsx
**/storybook/**/*.stories.{ts,tsx}

📄 CodeRabbit inference engine (DEVELOPING.md)

When adding new Storybook stories, prioritize high fidelity examples intended for publication on the website and in Storybook UI; use unit tests or VR tests for low fidelity tests

Files:

  • storybook/stories/API/component/Legend.stories.tsx
test/**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Aim for 100% unit test code coverage when writing new code

Files:

  • test/chart/AreaChart.stacked.spec.tsx
  • test/state/selectors/areaSelectors.spec.tsx
  • test/cartesian/Bar.truncateByDomain.spec.tsx
  • test/util/scale/utils.spec.ts
  • test/chart/AreaChart.spec.tsx
  • test/util/errorValue.spec.ts
test/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (test/README.md)

test/**/*.{test,spec}.{ts,tsx}: Aim for 100% unit test code coverage when writing new code
Prefer to use the createSelectorTestCase helper function when writing or modifying tests
Use the expectLastCalledWith helper function instead of expect(spy).toHaveBeenLastCalledWith(...) for better typing and autocompletion
Verify the number of selector calls using the spy object from createSelectorTestCase to spot unnecessary re-renders and improve performance
Mock getBoundingClientRect in tests using the helper function provided in test/helper/MockGetBoundingClientRect.ts
Use vi.useFakeTimers() in all tests due to Redux autoBatchEnhancer dependency on timers and requestAnimationFrame
Call vi.runOnlyPendingTimers() to advance timers after renders when not using createSelectorTestCase helper, and avoid vi.runAllTimers() to prevent infinite loops
Use userEvent.setup({ advanceTimers: vi.runOnlyPendingTimers }) or the userEventSetup helper function from test/helper/userEventSetup.ts when creating userEvent instances
When testing tooltips on hover, use vi.runOnlyPendingTimers() after each userEvent.hover() call or use the showTooltip helper function from tooltipTestHelpers.ts to account for requestAnimationFrame delays

Files:

  • test/chart/AreaChart.stacked.spec.tsx
  • test/state/selectors/areaSelectors.spec.tsx
  • test/cartesian/Bar.truncateByDomain.spec.tsx
  • test/util/scale/utils.spec.ts
  • test/chart/AreaChart.spec.tsx
  • test/util/errorValue.spec.ts
**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

When running unit tests, prefer to run a single test file using npm run test -- path/to/TestFile.spec.tsx rather than running all tests with npm test

Files:

  • test/chart/AreaChart.stacked.spec.tsx
  • test/state/selectors/areaSelectors.spec.tsx
  • test/cartesian/Bar.truncateByDomain.spec.tsx
  • test/util/scale/utils.spec.ts
  • test/chart/AreaChart.spec.tsx
  • test/util/errorValue.spec.ts
🧠 Learnings (16)
📓 Common learnings
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6750
File: src/state/selectors/axisSelectors.ts:593-602
Timestamp: 2025-12-08T08:23:26.219Z
Learning: In the recharts codebase, `DataKey<any>` is an intentional exception to the "no any" rule while proper typing is being developed. This should not be flagged in reviews.
📚 Learning: 2025-11-23T13:30:10.395Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6669
File: www/src/docs/exampleComponents/ScatterChart/ScatterChartWithLabels.tsx:2-2
Timestamp: 2025-11-23T13:30:10.395Z
Learning: The `TooltipIndex` type from recharts is defined in `src/state/tooltipSlice.ts` but is not currently exported from the public API entry points. It should not be imported from `recharts/types/state/tooltipSlice` as this is an internal implementation path. An ESLint rule is needed to prevent regressions.

Applied to files:

  • src/state/selectors/graphicalItemSelectors.ts
  • src/state/selectors/combiners/combineTooltipPayload.ts
  • storybook/stories/API/component/Legend.stories.tsx
  • scripts/snapshots/typesFiles.txt
  • src/state/selectors/axisSelectors.ts
  • src/component/DefaultTooltipContent.tsx
  • src/state/selectors/dataSelectors.ts
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to **/*.{ts,tsx} : Prefer `unknown` over `any` and refine the type in TypeScript

Applied to files:

  • test/util/isArray.spec-d.ts
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Use the `expectLastCalledWith` helper function instead of `expect(spy).toHaveBeenLastCalledWith(...)` for better typing and autocompletion

Applied to files:

  • test/util/isArray.spec-d.ts
  • test/chart/AreaChart.stacked.spec.tsx
  • test/util/scale/utils.spec.ts
  • test/helper/expectStackGroups.ts
  • test/chart/AreaChart.spec.tsx
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Verify the number of selector calls using the spy object from `createSelectorTestCase` to spot unnecessary re-renders and improve performance

Applied to files:

  • test/util/isArray.spec-d.ts
  • test/chart/AreaChart.stacked.spec.tsx
  • test/state/selectors/areaSelectors.spec.tsx
  • test/cartesian/Bar.truncateByDomain.spec.tsx
  • scripts/snapshots/typesFiles.txt
  • test/util/scale/utils.spec.ts
  • src/state/selectors/scatterSelectors.ts
  • scripts/snapshots/es6Files.txt
  • test/helper/expectStackGroups.ts
  • scripts/snapshots/libFiles.txt
  • test/chart/AreaChart.spec.tsx
  • src/state/selectors/lineSelectors.ts
  • test/util/errorValue.spec.ts
  • src/state/selectors/barSelectors.ts
📚 Learning: 2025-11-25T01:23:14.977Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T01:23:14.977Z
Learning: Applies to src/**/*.{ts,tsx} : Do not hardcode any strings or formatting choices in library code; users should provide localized strings as desired

Applied to files:

  • storybook/stories/API/component/Legend.stories.tsx
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to storybook/stories/**/*.stories.tsx : Update Storybook stories when APIs have been changed to ensure they work as expected

Applied to files:

  • storybook/stories/API/component/Legend.stories.tsx
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Prefer to use the `createSelectorTestCase` helper function when writing or modifying tests

Applied to files:

  • test/chart/AreaChart.stacked.spec.tsx
  • test/state/selectors/areaSelectors.spec.tsx
  • test/cartesian/Bar.truncateByDomain.spec.tsx
  • scripts/snapshots/typesFiles.txt
  • scripts/snapshots/es6Files.txt
  • scripts/snapshots/libFiles.txt
  • test/chart/AreaChart.spec.tsx
  • test/util/errorValue.spec.ts
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Call `vi.runOnlyPendingTimers()` to advance timers after renders when not using `createSelectorTestCase` helper, and avoid `vi.runAllTimers()` to prevent infinite loops

Applied to files:

  • test/chart/AreaChart.stacked.spec.tsx
  • test/state/selectors/areaSelectors.spec.tsx
  • scripts/snapshots/es6Files.txt
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Mock `getBoundingClientRect` in tests using the helper function provided in `test/helper/MockGetBoundingClientRect.ts`

Applied to files:

  • test/state/selectors/areaSelectors.spec.tsx
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to test/component/**/*.spec.tsx : Use React Testing Library for testing component interactions and behavior upon rendering

Applied to files:

  • test/state/selectors/areaSelectors.spec.tsx
📚 Learning: 2025-12-06T03:36:59.377Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: DEVELOPING.md:0-0
Timestamp: 2025-12-06T03:36:59.377Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : All imports from `recharts` must use the public API entry point; imports from internal paths like `recharts/types/*` or `recharts/src/*` are not allowed

Applied to files:

  • test/cartesian/Bar.truncateByDomain.spec.tsx
  • src/state/selectors/axisSelectors.ts
  • src/state/selectors/barSelectors.ts
  • src/state/selectors/areaSelectors.ts
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Use `vi.useFakeTimers()` in all tests due to Redux autoBatchEnhancer dependency on timers and `requestAnimationFrame`

Applied to files:

  • test/util/scale/utils.spec.ts
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Extract pure helper functions for data processing and write unit tests for them

Applied to files:

  • test/util/scale/utils.spec.ts
📚 Learning: 2025-12-08T08:23:26.219Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6750
File: src/state/selectors/axisSelectors.ts:593-602
Timestamp: 2025-12-08T08:23:26.219Z
Learning: In the recharts codebase, `DataKey<any>` is an intentional exception to the "no any" rule while proper typing is being developed. This should not be flagged in reviews.

Applied to files:

  • test/helper/expectStackGroups.ts
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to **/*.{ts,tsx} : Type function parameters and return values explicitly in TypeScript, do not rely on implicit any or inference; exceptions are React components and trivial functions

Applied to files:

  • test/helper/expectStackGroups.ts
🧬 Code graph analysis (14)
src/state/selectors/graphicalItemSelectors.ts (3)
src/state/store.ts (1)
  • RechartsRootState (23-38)
src/state/graphicalItemsSlice.ts (1)
  • GraphicalItemId (19-19)
src/state/cartesianAxisSlice.ts (2)
  • AxisId (8-8)
  • defaultAxisId (9-9)
src/state/selectors/combiners/combineTooltipPayload.ts (1)
src/util/ChartUtils.ts (1)
  • getValueByDataKey (42-56)
test/chart/AreaChart.stacked.spec.tsx (1)
src/state/selectors/areaSelectors.ts (2)
  • selectGraphicalItemStackedData (109-131)
  • selectArea (133-202)
test/state/selectors/areaSelectors.spec.tsx (2)
test/helper/selectorTestHelpers.tsx (2)
  • shouldReturnUndefinedOutOfContext (9-20)
  • shouldReturnFromInitialState (22-35)
src/state/selectors/areaSelectors.ts (1)
  • selectArea (133-202)
test/cartesian/Bar.truncateByDomain.spec.tsx (1)
src/state/selectors/dataSelectors.ts (1)
  • selectChartDataWithIndexesIfNotInPanoramaPosition4 (37-47)
src/state/selectors/scatterSelectors.ts (4)
src/state/cartesianAxisSlice.ts (1)
  • AxisId (8-8)
src/state/graphicalItemsSlice.ts (1)
  • GraphicalItemId (19-19)
src/state/chartDataSlice.ts (1)
  • ChartDataState (23-40)
src/state/selectors/dataSelectors.ts (1)
  • selectChartDataWithIndexesIfNotInPanoramaPosition4 (37-47)
src/state/selectors/axisSelectors.ts (1)
src/state/selectors/dataSelectors.ts (1)
  • selectChartDataWithIndexesIfNotInPanoramaPosition4 (37-47)
test/helper/expectStackGroups.ts (1)
src/util/stacks/stackTypes.ts (1)
  • StackDataPoint (51-51)
src/component/DefaultTooltipContent.tsx (3)
src/util/DataUtils.ts (1)
  • isNumOrStr (27-27)
src/util/types.ts (1)
  • TooltipType (81-81)
src/component/DefaultLegendContent.tsx (1)
  • Formatter (24-24)
src/cartesian/Area.tsx (3)
src/state/selectors/areaSelectors.ts (1)
  • selectArea (133-202)
src/util/stacks/stackTypes.ts (1)
  • StackDataPoint (51-51)
src/util/ChartUtils.ts (2)
  • getValueByDataKey (42-56)
  • getCateCoordinateOfLine (488-527)
src/state/selectors/lineSelectors.ts (1)
src/state/selectors/dataSelectors.ts (1)
  • selectChartDataWithIndexesIfNotInPanoramaPosition4 (37-47)
src/state/selectors/barSelectors.ts (4)
src/context/chartLayoutContext.tsx (1)
  • selectChartLayout (133-133)
src/state/selectors/axisSelectors.ts (1)
  • selectUnfilteredCartesianItems (311-313)
src/state/selectors/graphicalItemSelectors.ts (2)
  • selectXAxisIdFromGraphicalItemId (5-7)
  • selectYAxisIdFromGraphicalItemId (9-11)
src/state/selectors/dataSelectors.ts (1)
  • selectChartDataWithIndexesIfNotInPanoramaPosition3 (49-58)
src/state/selectors/dataSelectors.ts (2)
src/state/store.ts (1)
  • RechartsRootState (23-38)
src/state/chartDataSlice.ts (1)
  • ChartDataState (23-40)
src/state/selectors/areaSelectors.ts (9)
src/util/types.ts (1)
  • NullableCoordinate (93-96)
src/state/graphicalItemsSlice.ts (1)
  • GraphicalItemId (19-19)
src/state/selectors/graphicalItemSelectors.ts (2)
  • selectXAxisIdFromGraphicalItemId (5-7)
  • selectYAxisIdFromGraphicalItemId (9-11)
src/state/types/AreaSettings.ts (1)
  • AreaSettings (7-14)
src/context/chartLayoutContext.tsx (1)
  • selectChartLayout (133-133)
src/state/cartesianAxisSlice.ts (1)
  • AxisId (8-8)
src/util/stacks/stackTypes.ts (3)
  • StackDataPoint (51-51)
  • StackSeriesIdentifier (57-57)
  • StackSeries (43-43)
src/util/stacks/getStackSeriesIdentifier.ts (1)
  • getStackSeriesIdentifier (14-18)
src/state/selectors/dataSelectors.ts (1)
  • selectChartDataWithIndexesIfNotInPanoramaPosition3 (49-58)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build, Test, Pack
🔇 Additional comments (51)
test/util/scale/utils.spec.ts (1)

2-2: Updated import is consistent with utility API changes

Removing reverse from the imports cleanly reflects its removal from the underlying utilities; the remaining tests still exercise the other helpers correctly.

test/helper/expectStackGroups.ts (2)

14-16: Stronger typing for seriesPointToTuple looks good

Using StackDataPoint for both parameter and return aligns this helper with the stack types and keeps the flow through actualSeriesToExpectedSeries type-safe. No further changes needed.


45-57: Typed matcher helpers now match the stacked data aliases

Updating expectStackedData and expectStackedSeries to use ExpectedStackedData / ExpectedStackedDataSeries keeps the helpers consistent with the exported types and avoids leaking unknown/any into tests, while preserving the runtime Array.isArray safety checks. This looks correct.

test/util/errorValue.spec.ts (1)

1-63: LGTM!

The test file is well-structured with good coverage for getErrorDomainByDataKey. The use of describe.each for parameterized tests and @ts-expect-error for invalid input testing is appropriate.

scripts/snapshots/typesFiles.txt (1)

152-152: LGTM!

The new type declaration file entry is correctly positioned alphabetically in the snapshot list, consistent with the new graphicalItemSelectors.ts source file added in this PR.

src/animation/AnimationManager.ts (1)

4-4: LGTM!

Replacing object with Record<string, unknown> is a solid type improvement. It's more precise for style objects while using unknown instead of any per the coding guidelines.

www/src/components/GuideView/DomainAndTicks/MassBarChartCustomTicks.tsx (1)

84-91: LGTM!

Good defensive change to handle potentially undefined values. The null check using loose equality (== null) correctly catches both null and undefined, and returning an empty string is appropriate for formatter functions.

types.d.ts (1)

33-48: Good workaround for TypeScript's Array.isArray typing limitation.

The override correctly addresses the TypeScript issue where Array.isArray on ReadonlyArray produces any[]. The use of any in the parameter type is acceptable here since it must match TypeScript's built-in signature to override it properly. The return type ReadonlyArray<unknown> is the key improvement.

The documentation clearly explains the trade-offs and provides guidance on mutation, which is helpful for maintainers.

src/component/DefaultTooltipContent.tsx (2)

12-14: LGTM!

The defaultFormatter now correctly handles undefined values. The Array.isArray check benefits from the new typed declaration added in this PR.


84-89: LGTM!

The explicit typing of entry as Payload<TValue, TName> and finalFormatter as Formatter<TValue, TName> improves type safety and removes implicit any inference.

storybook/stories/API/component/Legend.stories.tsx (1)

90-92: Tooltip formatter null‑safety looks good

Using value?.toLocaleString() aligns with the YAxis tick formatter and safely handles null/undefined tooltip values without changing the overall behavior.

scripts/snapshots/es6Files.txt (1)

152-152: Snapshot list updated consistently

Adding "es6/state/selectors/graphicalItemSelectors.js" after funnelSelectors keeps the selector snapshot list ordered and in sync with the new selector module.

scripts/snapshots/libFiles.txt (1)

152-152: Lib snapshot entry matches ES6 snapshot

The new "lib/state/selectors/graphicalItemSelectors.js" entry is correctly placed alongside other selector modules and stays consistent with the es6 snapshot list.

src/state/selectors/lineSelectors.ts (1)

5-5: Line selector now wired to Position4 data selector correctly

Switching to selectChartDataWithIndexesIfNotInPanoramaPosition4 and using it as the final dependency in selectLinePoints keeps the selector signature intact while relying only on isPanorama for data selection. This matches the helper’s intended (state, _, _, isPanorama) contract with no behavioral change.

Also applies to: 82-83

src/util/scale/getNiceTickValues.ts (1)

7-7: Local in‑place reverse() is safe and simplifies the utility

Dropping the custom reverse helper and using values.reverse() is fine here: values is always a freshly created local array and is only used for the return value, so the in‑place mutation has no observable side effects outside these functions while trimming an unnecessary import.

Also applies to: 186-187, 198-199, 236-237

src/state/selectors/scatterSelectors.ts (1)

6-6: Scatter data selector correctly switched to Position4 helper

scatterChartDataSelector now delegates to selectChartDataWithIndexesIfNotInPanoramaPosition4 and explicitly marks axis parameters as unused, which matches the helper’s (state, _, _, isPanorama) contract. This keeps the external selectScatterPoints signature the same while making the dependency on isPanorama explicit and type‑safe.

Also applies to: 78-87

src/state/selectors/axisSelectors.ts (4)

40-40: Import update aligns with renamed selector.

The import correctly references the new selectChartDataWithIndexesIfNotInPanoramaPosition4 variant, which matches the 4-parameter signature required by selectors like selectDisplayedData and selectDisplayedStackedData.


47-47: Consolidated DataUtils imports.

Formatting cleanup that consolidates the imports into a single line. No functional change.


432-434: Correct usage of Position4 selector variant.

The selectChartDataWithIndexesIfNotInPanoramaPosition4 selector is properly used here. The selector signature (state, _unused1, _unused2, isPanorama) aligns with createSelector's parameter passing where axisType and axisId occupy positions 2 and 3, and isPanorama is at position 4.


587-589: Consistent selector usage for stacked data.

Same pattern applied correctly to selectDisplayedStackedData, ensuring consistent data retrieval behavior across axis selectors.

test/cartesian/Bar.truncateByDomain.spec.tsx (1)

10-10: Import updated to new selector variant.

Correctly imports the renamed selectChartDataWithIndexesIfNotInPanoramaPosition4 selector.

test/chart/AreaChart.stacked.spec.tsx (8)

173-178: Migrated to id-based selector API.

Test correctly uses selectGraphicalItemStackedData(state, areaSettings1.id, false) with the new GraphicalItemId-based signature. This aligns with the broader refactor to resolve axes from item IDs rather than explicit axis parameters.


182-187: Consistent id-based selector usage for second area.

Same pattern applied correctly for areaSettings2.id.


191-241: selectArea now uses GraphicalItemId.

The test correctly invokes selectArea(state, areaSettings1.id, false) matching the updated selector signature (state, id, isPanorama). Expected data structure remains unchanged.


244-297: Second area selection verified.

Test for selectArea(state, areaSettings2.id, false) validates stacked baseline and point calculations. The y-value of the first area correctly becomes the baseline for the second area.


423-429: Second describe block updated consistently.

The "without explicit XAxis dataKey" scenario follows the same id-based selector pattern, maintaining test coverage for this edge case.

Also applies to: 432-438, 441-492, 495-548


689-704: Multiple data arrays scenario covered.

Tests for "multiple data arrays but each has their own dataKey" correctly use id-based selectors with area-specific data arrays.

Also applies to: 707-730, 733-758


905-920: Same dataKey scenario tested.

The "multiple data arrays with the same dataKey" scenario validates stacking behavior when areas share a dataKey, using id-based selectors.

Also applies to: 923-960, 963-1001


1151-1166: Without explicit XAxis dataKey and same dataKey scenario.

Final describe block covers the edge case combination, completing test coverage for the id-based selector migration.

Also applies to: 1169-1206, 1209-1247

test/chart/AreaChart.spec.tsx (8)

176-176: Updated to id-based area selection.

The test now correctly uses selectArea(state, 'area-1', false) to retrieve area data by GraphicalItemId.


196-196: Area component now has explicit id.

Added id="area-1" to enable id-based selector lookup. This is required for the new selector API.


249-332: Updated test expectations for stacked percentage chart.

The expected output now reflects the ComputedArea structure with baseLine, isRange, and points properties. Values and coordinates are correctly specified for the expand stack offset.


360-360: Consistent id-based selector for number x-axis test.

Test correctly uses selectArea(state, 'area-1', false).


368-368: Area id attribute added for number x-axis scenario.


416-489: Comprehensive expectation for number x-axis stacked area.

Test validates baseline and point data when x-axis is type number with domain ['dataMin', 'dataMax']. The stacked values correctly start from 0.


493-501: Number stackId test updated.

Test case for numeric stackId now uses id-based selection with id="area-0" and selectArea(state, 'area-0', false).


512-596: Complete expectation for number stackId scenario.

Validates the full ComputedArea structure including all 7 data points from pageData.

src/state/selectors/barSelectors.ts (9)

19-19: Import updated to Position3 selector variant.

The selectChartDataWithIndexesIfNotInPanoramaPosition3 variant matches the 3-parameter signature (state, id, isPanorama) used by bar selectors.


28-28: New imports for GraphicalItemId-based axis resolution.

Imports selectXAxisIdFromGraphicalItemId and selectYAxisIdFromGraphicalItemId from the new graphicalItemSelectors module to resolve axis IDs from GraphicalItemId.


56-74: selectAllVisibleBars refactored to use GraphicalItemId-based axis selectors.

The selector now derives xAxisId and yAxisId from the GraphicalItemId via the new helper selectors, then filters bars by the appropriate axis based on layout. This decouples the selector from explicit axis ID parameters.


84-85: selectBarStackGroups uses new axis resolution.

Axis IDs are now resolved from the GraphicalItemId before calling selectStackGroups.


97-98: selectBarCartesianAxisSize aligned with new pattern.

Consistent use of selectXAxisIdFromGraphicalItemId/selectYAxisIdFromGraphicalItemId.


126-127: selectBarBandSize updated.

Same refactoring pattern applied.


152-153: selectAxisBandSize updated.

Consistent pattern.


202-231: Helper selectors consistently refactored.

selectXAxisWithScale, selectYAxisWithScale, selectXAxisTicks, and selectYAxisTicks all use the new GraphicalItemId-based axis resolution. This consolidates the axis lookup logic.


279-279: selectBarRectangles uses Position3 data selector.

The selectChartDataWithIndexesIfNotInPanoramaPosition3 variant is correctly used here, matching the selector's 3-parameter signature (state, id, isPanorama).

src/state/selectors/dataSelectors.ts (1)

37-58: LGTM - Selector variants for positional argument handling.

The Position3 and Position4 naming convention correctly reflects the position of the isPanorama parameter in reselect's createSelector composition. Using unknown for unused parameters aligns with the coding guidelines.

src/cartesian/Area.tsx (2)

843-843: LGTM - Simplified selector API using GraphicalItemId.

The selector call correctly uses the new GraphicalItemId-based API, which internally resolves axis IDs from the item's registered state. This aligns with the refactored selectArea signature in areaSelectors.ts.


966-981: LGTM - Proper type handling with Array.isArray narrowing.

The valueAsArray variable correctly handles both stacked data (already a tuple) and non-stacked data (converted to [baseValue, rawValue]). The @ts-expect-error comments are appropriate since getValueByDataKey returns unknown and runtime type checking is required.

src/state/selectors/areaSelectors.ts (2)

109-131: LGTM - Correct stacked data extraction from d3 series.

The selector correctly maps d3's SeriesPoint to StackDataPoint tuples by extracting the lower [0] and upper [1] stack bounds. The composition with selectNumericalAxisStackGroups properly resolves the correct axis stack groups based on layout.


133-148: LGTM - Well-structured selector composition.

The selectArea selector correctly composes all required inputs using the GraphicalItemId-based resolution pattern. The usage of selectChartDataWithIndexesIfNotInPanoramaPosition3 aligns with the 3-parameter signature (state, id, isPanorama).

Comment thread src/state/selectors/areaSelectors.ts Outdated
Comment thread test/util/isArray.spec-d.ts Outdated
@codecov

codecov Bot commented Dec 10, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.85039% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.67%. Comparing base (ee0b17b) to head (e6fcca1).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
...ideView/DomainAndTicks/MassBarChartCustomTicks.tsx 0.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6760      +/-   ##
==========================================
- Coverage   93.70%   93.67%   -0.04%     
==========================================
  Files         515      516       +1     
  Lines       43011    43021      +10     
  Branches     5018     5011       -7     
==========================================
- Hits        40302    40298       -4     
- Misses       2703     2717      +14     
  Partials        6        6              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

PavelVanecek and others added 3 commits December 10, 2025 23:01
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/state/selectors/areaSelectors.ts (1)

97-107: selectNumericalAxisStackGroups correctly composes the stackGroups lookup.

The helper forwards state, the resolved numerical axis type/id, and isPanorama into selectStackGroups, so stack groups are fetched relative to the axis actually used for numeric values. Logic looks sound; any further micro-optimizations (e.g., caching the axis type between usages) would be purely cosmetic.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1de4be9 and c2c0754.

📒 Files selected for processing (2)
  • src/state/selectors/areaSelectors.ts (6 hunks)
  • test/util/isArray.spec-d.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.{ts,tsx}: Never use any type (implicit or explicit) in TypeScript code
Prefer unknown over any and refine the type in TypeScript
Type function parameters and return values explicitly in TypeScript, do not rely on implicit any or inference; exceptions are React components and trivial functions
Do not use as type assertions in TypeScript; the only exception is as const

Files:

  • src/state/selectors/areaSelectors.ts
  • test/util/isArray.spec-d.ts
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Ensure code lints by running npm run lint and follows Airbnb's Style Guide

Files:

  • src/state/selectors/areaSelectors.ts
  • test/util/isArray.spec-d.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Do not hardcode any strings or formatting choices in library code; users should provide localized strings as desired

Files:

  • src/state/selectors/areaSelectors.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (DEVELOPING.md)

All imports from recharts must use the public API entry point; imports from internal paths like recharts/types/* or recharts/src/* are not allowed

Files:

  • src/state/selectors/areaSelectors.ts
  • test/util/isArray.spec-d.ts
🧠 Learnings (13)
📓 Common learnings
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6750
File: src/state/selectors/axisSelectors.ts:593-602
Timestamp: 2025-12-08T08:23:26.219Z
Learning: In the recharts codebase, `DataKey<any>` is an intentional exception to the "no any" rule while proper typing is being developed. This should not be flagged in reviews.
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Verify the number of selector calls using the spy object from `createSelectorTestCase` to spot unnecessary re-renders and improve performance
📚 Learning: 2025-11-23T13:30:10.395Z
Learnt from: PavelVanecek
Repo: recharts/recharts PR: 6669
File: www/src/docs/exampleComponents/ScatterChart/ScatterChartWithLabels.tsx:2-2
Timestamp: 2025-11-23T13:30:10.395Z
Learning: The `TooltipIndex` type from recharts is defined in `src/state/tooltipSlice.ts` but is not currently exported from the public API entry points. It should not be imported from `recharts/types/state/tooltipSlice` as this is an internal implementation path. An ESLint rule is needed to prevent regressions.

Applied to files:

  • src/state/selectors/areaSelectors.ts
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to **/*.{ts,tsx} : Prefer `unknown` over `any` and refine the type in TypeScript

Applied to files:

  • test/util/isArray.spec-d.ts
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Use the `expectLastCalledWith` helper function instead of `expect(spy).toHaveBeenLastCalledWith(...)` for better typing and autocompletion

Applied to files:

  • test/util/isArray.spec-d.ts
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Verify the number of selector calls using the spy object from `createSelectorTestCase` to spot unnecessary re-renders and improve performance

Applied to files:

  • test/util/isArray.spec-d.ts
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Prefer to use the `createSelectorTestCase` helper function when writing or modifying tests

Applied to files:

  • test/util/isArray.spec-d.ts
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Use `vi.useFakeTimers()` in all tests due to Redux autoBatchEnhancer dependency on timers and `requestAnimationFrame`

Applied to files:

  • test/util/isArray.spec-d.ts
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Use `userEvent.setup({ advanceTimers: vi.runOnlyPendingTimers })` or the `userEventSetup` helper function from `test/helper/userEventSetup.ts` when creating userEvent instances

Applied to files:

  • test/util/isArray.spec-d.ts
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Call `vi.runOnlyPendingTimers()` to advance timers after renders when not using `createSelectorTestCase` helper, and avoid `vi.runAllTimers()` to prevent infinite loops

Applied to files:

  • test/util/isArray.spec-d.ts
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : When testing tooltips on hover, use `vi.runOnlyPendingTimers()` after each `userEvent.hover()` call or use the `showTooltip` helper function from `tooltipTestHelpers.ts` to account for requestAnimationFrame delays

Applied to files:

  • test/util/isArray.spec-d.ts
📚 Learning: 2025-11-25T01:23:08.250Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: test/README.md:0-0
Timestamp: 2025-11-25T01:23:08.250Z
Learning: Applies to test/**/*.{test,spec}.{ts,tsx} : Aim for 100% unit test code coverage when writing new code

Applied to files:

  • test/util/isArray.spec-d.ts
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to test/**/*.spec.{ts,tsx} : Aim for 100% unit test code coverage when writing new code

Applied to files:

  • test/util/isArray.spec-d.ts
📚 Learning: 2025-11-25T01:22:59.729Z
Learnt from: CR
Repo: recharts/recharts PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-11-25T01:22:59.729Z
Learning: Applies to test/component/**/*.spec.tsx : Use React Testing Library for testing component interactions and behavior upon rendering

Applied to files:

  • test/util/isArray.spec-d.ts
🧬 Code graph analysis (1)
src/state/selectors/areaSelectors.ts (9)
src/util/types.ts (1)
  • NullableCoordinate (93-96)
src/state/graphicalItemsSlice.ts (1)
  • GraphicalItemId (19-19)
src/state/selectors/axisSelectors.ts (1)
  • selectStackGroups (635-643)
src/state/selectors/graphicalItemSelectors.ts (2)
  • selectXAxisIdFromGraphicalItemId (5-7)
  • selectYAxisIdFromGraphicalItemId (9-11)
src/util/ChartUtils.ts (1)
  • isCategoricalAxis (103-107)
src/state/cartesianAxisSlice.ts (1)
  • AxisId (8-8)
src/util/stacks/stackTypes.ts (4)
  • StackGroup (32-35)
  • StackDataPoint (51-51)
  • StackSeriesIdentifier (57-57)
  • StackSeries (43-43)
src/util/stacks/getStackSeriesIdentifier.ts (1)
  • getStackSeriesIdentifier (14-18)
src/state/selectors/dataSelectors.ts (1)
  • selectChartDataWithIndexesIfNotInPanoramaPosition3 (49-58)
🪛 GitHub Actions: Build and test
test/util/isArray.spec-d.ts

[error] 1-1: ESLint: import/newline-after-import - Expected 1 empty line after import statement. (in /__w/recharts/recharts/test/util/isArray.spec-d.ts) Run 'npm run lint' to fix.

🪛 GitHub Check: Build, Test, Pack
test/util/isArray.spec-d.ts

[failure] 1-1:
Expected 1 empty line after import statement not followed by another import

🔇 Additional comments (8)
test/util/isArray.spec-d.ts (1)

2-42: Type refinement tests for Array.isArray look solid.

The three cases (unknown, union with number[], union with ReadonlyArray<number>) exercise the custom Array.isArray typing well, use unknown instead of any, and avoid as assertions, all in line with the repo’s TypeScript guidelines. I don’t see further issues here once the lint error is fixed.

src/state/selectors/areaSelectors.ts (7)

2-22: Imports for new stack/axis helpers are consistent with project guidelines.

The additional imports for stack types, chart-data selector, and graphical-item axis helpers are all used below and come from local modules or vendor code only; there are no new imports from internal recharts/* paths. No changes needed.


24-35: AreaPointItem and ComputedArea typings now match tuple-based stacked values.

Changing value to [number, number] and baseLine to number | ReadonlyArray<AreaPointItem> aligns these types with StackDataPoint = [number, number] and with read-only area point collections, which should work cleanly with the updated stacking pipeline and avoids any[]-style looseness.


37-47: GraphicalItemId-based X/Y axis helpers are wired to the correct selectors.

selectXAxisWithScale/selectXAxisTicks now use the X-axis id selector and the Y counterparts use the Y-axis id selector, so both scales and ticks are resolved from GraphicalItemId consistently. This also addresses the earlier issue where X-axis ticks were sourced via the Y-axis selector.


59-78: pickAreaId/selectSynchronisedAreaSettings signatures stay compatible with 3‑arg selectors.

pickAreaId clearly ignores state and returns the GraphicalItemId, and selectSynchronisedAreaSettings adds an isPanorama parameter in its public signature while still only depending on state and id internally. This keeps it usable alongside other (state, id, isPanorama) selectors without changing behavior.


80-95: Numerical-axis resolution correctly complements isCategoricalAxis.

selectNumericalAxisType chooses 'yAxis' when the X axis is categorical and 'xAxis' otherwise, which matches the horizontal/vertical layout rules, and selectNumericalAxisIdFromGraphicalItemId delegates to the matching X/Y axis-id selector based on that type. This gives a coherent numerical-axis id for stacking per graphical item.


109-131: selectGraphicalItemStackedData safely narrows to the correct series and returns typed tuples.

The selector guards against missing areaSettings, stackGroups, stackId, and stackSeriesIdentifier, then locates the relevant StackSeries for the area and maps each point to a [item[0], item[1]] tuple typed as StackDataPoint. This is compatible with the new StackDataPoint definition and keeps the output strongly typed while ignoring any extra fields on the underlying series points.


133-161: selectArea wiring with stackedData and panorama-aware chart data is consistent.

The selector now accepts (state, graphicalItemId, isPanorama), threads isPanorama into selectChartDataWithIndexesIfNotInPanoramaPosition3, and consumes stackedData: ReadonlyArray<StackDataPoint> | undefined from selectGraphicalItemStackedData. Existing guards on layout, axes, ticks, and bandSize are preserved, so computeArea only runs when all prerequisites are satisfied.

Comment thread test/util/isArray.spec-d.ts
@github-actions

Copy link
Copy Markdown
Contributor

Staging Deployment Details

These deployments will remain available for 30 days.

To update snapshots: Comment /update-snapshots on this PR to automatically update the baseline screenshots.

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

Staging Deployment Details

These deployments will remain available for 30 days.

To update snapshots: Comment /update-snapshots on this PR to automatically update the baseline screenshots.

@ckifer
ckifer merged commit 443b136 into main Dec 12, 2025
37 of 39 checks passed
@PavelVanecek
PavelVanecek deleted the arrayisarray branch December 12, 2025 05:06
@coderabbitai coderabbitai Bot mentioned this pull request Jan 10, 2026
8 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants