Skip to content

Commit ed15215

Browse files
authored
React 19 Support (#1968)
* feat: add React 19 support with automatic JSX transform * chore: update yarn.lock * feat!: add React 19 support with automatic JSX transform * chore(demo): upgrade @react-spring/web to v10 * chore: configure ESLint for TypeScript type/value separation * chore: add package exports field to all packages for better module resolution * feat: add explicit type exports and migrate to package root imports * test(xychart): fix React 19 warnings by avoiding key prop spread * demo: upgrade to React 19 and Next.js 15, simplify config * demo: replace deep imports with package root imports and improve types * chore: update yarn.lock for React 19 and Next.js 15 upgrade * fix(xychart): fix React 19 key prop spread warning in Tooltip * prettier: fix formatting * demo: configure transpilePackages for production builds * chore: convert to type-only React imports with automatic JSX transform * refactor: replace React.* with direct named imports * build: drop IE11 support and target modern browsers - Removed IE 11 from targets - Added specific modern browser versions (Chrome 108+, Firefox 133+, Safari 15.6+, etc.) - Changed loose: false for stricter transpilation - Added useBuiltIns and useSpread optimizations to React preset
1 parent 20e3154 commit ed15215

File tree

396 files changed

+1883
-1233
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

396 files changed

+1883
-1233
lines changed

.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ module.exports = {
5353
'react/jsx-sort-props': 'off',
5454
'react/no-array-index-key': 'off',
5555
'react/no-children-prop': 'off',
56+
'react/react-in-jsx-scope': 'off', // Not needed with automatic JSX transform (React 16.14+)
5657
'react/require-default-props': 'off',
5758
'react/sort-comp': 'off',
5859
'react/sort-prop-types': 'off',

babel.config.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,25 @@
11
const esm = process.env.ESM;
22

33
const envOptions = {
4-
loose: true,
4+
loose: false,
55
modules: esm ? false : 'commonjs',
66
shippedProposals: true,
77
targets: {
8-
ie: 11,
8+
browsers: [
9+
'chrome >= 108',
10+
'edge >= 108',
11+
'firefox >= 133',
12+
'safari >= 15.6',
13+
'ios_saf >= 15.6',
14+
'samsung >= 27',
15+
],
916
},
1017
bugfixes: false,
1118
};
1219

1320
const presets = [
1421
['@babel/preset-env', envOptions],
15-
'@babel/preset-react',
22+
['@babel/preset-react', { runtime: 'automatic', useBuiltIns: true, useSpread: true }],
1623
'@babel/preset-typescript',
1724
];
1825

config-eslint/typescript.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ module.exports = {
3131
'no-unused-vars': 'off',
3232

3333
// IMPORT (Conflicts with TS patterns)
34+
'no-duplicate-imports': 'off', // Disabled in favor of import/no-duplicates
35+
'import/export': 'off', // TypeScript allows same name for type and value exports
3436
'import/extensions': [
3537
'error',
3638
'never',
@@ -40,6 +42,7 @@ module.exports = {
4042
],
4143
'import/named': 'off',
4244
'import/no-cycle': 'off',
45+
'import/no-duplicates': 'error', // Handles TS type/value namespace separation
4346
'import/no-named-as-default': 'off',
4447
'import/no-extraneous-dependencies': [
4548
'error',
@@ -80,6 +83,7 @@ module.exports = {
8083
'error',
8184
{ assertionStyle: 'as', objectLiteralTypeAssertions: 'allow-as-parameter' },
8285
],
86+
'@typescript-eslint/consistent-type-exports': ['error', { fixMixedExportsWithInlineTypeSpecifier: true }],
8387
'@typescript-eslint/consistent-type-imports': ['error', { prefer: 'type-imports' }],
8488
'@typescript-eslint/explicit-function-return-type': 'off', // Allow inferrence
8589
'@typescript-eslint/func-call-spacing': ['error', 'never'],

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@
7676
"@testing-library/user-event": "^13.5.0",
7777
"@types/jsdom": "27.0.0",
7878
"@types/node": "^22.10.2",
79-
"@types/react": "18.3.26",
80-
"@types/react-dom": "18.3.7",
79+
"@types/react": "^19.0.0",
80+
"@types/react-dom": "^19.0.0",
8181
"@typescript-eslint/eslint-plugin": "^8.18.1",
8282
"@typescript-eslint/parser": "^8.18.1",
8383
"@vitest/coverage-v8": "4",
@@ -100,8 +100,8 @@
100100
"jsdom": "27.0.0",
101101
"lerna": "^7.0.2",
102102
"prettier": "^2.8.1",
103-
"react": "^16.0.0-0 || ^17.0.0-0 || ^18.0.0-0 || ^19.0.0-0",
104-
"react-dom": "^16.0.0-0 || ^17.0.0-0 || ^18.0.0-0 || ^19.0.0-0",
103+
"react": "^16.14.0 || ^17.0.0-0 || ^18.0.0-0 || ^19.0.0-0",
104+
"react-dom": "^16.14.0 || ^17.0.0-0 || ^18.0.0-0 || ^19.0.0-0",
105105
"timezone-mock": "^1.1.0",
106106
"ts-node": "^10.9.1",
107107
"typescript": "^5.7.0",
@@ -114,10 +114,10 @@
114114
]
115115
},
116116
"resolutions": {
117-
"react": "18.3.1",
118-
"react-dom": "18.3.1",
119-
"@types/react": "18.3.26",
120-
"@types/react-dom": "18.3.7",
117+
"react": "^19.0.0",
118+
"react-dom": "^19.0.0",
119+
"@types/react": "^19.0.0",
120+
"@types/react-dom": "^19.0.0",
121121
"wrap-ansi": "7.0.0",
122122
"string-width": "4.2.3",
123123
"strip-ansi": "6.0.1",

packages/visx-annotation/package.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@
66
"main": "lib/index.js",
77
"module": "esm/index.js",
88
"types": "lib/index.d.ts",
9+
"exports": {
10+
".": {
11+
"types": "./lib/index.d.ts",
12+
"import": "./esm/index.js",
13+
"require": "./lib/index.js"
14+
}
15+
},
916
"files": [
1017
"lib",
1118
"esm"
@@ -28,7 +35,7 @@
2835
},
2936
"homepage": "https://github.com/airbnb/visx#readme",
3037
"peerDependencies": {
31-
"react": "^16.0.0-0 || ^17.0.0-0 || ^18.0.0-0 || ^19.0.0-0"
38+
"react": "^16.14.0 || ^17.0.0-0 || ^18.0.0-0 || ^19.0.0-0"
3239
},
3340
"dependencies": {
3441
"@types/react": "*",

packages/visx-annotation/src/components/Annotation.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import React, { useMemo } from 'react';
1+
import { useMemo, type ReactNode } from 'react';
22
import AnnotationContext from '../context/AnnotationContext';
33
import type { AnnotationContextType } from '../types';
44

55
export type AnnotationProps = Pick<AnnotationContextType, 'x' | 'y' | 'dx' | 'dy'> & {
66
/** Annotation children (Subject, Label, Connector) */
7-
children: React.ReactNode;
7+
children: ReactNode;
88
};
99

1010
export default function Annotation({ x, y, dx, dy, children }: AnnotationProps) {

packages/visx-annotation/src/components/CircleSubject.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useContext } from 'react';
1+
import { useContext, type SVGProps } from 'react';
22
import cx from 'classnames';
33
import type { AnnotationContextType } from '../types';
44
import AnnotationContext from '../context/AnnotationContext';
@@ -19,7 +19,7 @@ export default function CircleSubject({
1919
stroke = '#222',
2020
radius = 16,
2121
...restProps
22-
}: CircleSubjectProps & Omit<React.SVGProps<SVGCircleElement>, keyof CircleSubjectProps>) {
22+
}: CircleSubjectProps & Omit<SVGProps<SVGCircleElement>, keyof CircleSubjectProps>) {
2323
// if props are provided, they take precedence over context
2424
const annotationContext = useContext(AnnotationContext);
2525

packages/visx-annotation/src/components/Connector.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useContext } from 'react';
1+
import { useContext, type SVGProps } from 'react';
22
import cx from 'classnames';
33
import type { AnnotationContextType } from '../types';
44
import AnnotationContext from '../context/AnnotationContext';
@@ -14,7 +14,7 @@ export type ConnectorProps = Pick<AnnotationContextType, 'x' | 'y' | 'dx' | 'dy'
1414
/** Color of the connector line. */
1515
stroke?: string;
1616
/** Optional additional props. */
17-
pathProps?: React.SVGProps<SVGPathElement>;
17+
pathProps?: SVGProps<SVGPathElement>;
1818
};
1919

2020
export default function Connector({

packages/visx-annotation/src/components/EditableAnnotation.tsx

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/* eslint-disable react/jsx-handler-names */
2-
import React, { useCallback, useRef } from 'react';
3-
import type { UseDrag, HandlerArgs as DragHandlerArgs } from '@visx/drag/lib/useDrag';
4-
import useDrag from '@visx/drag/lib/useDrag';
2+
import { useCallback, useRef } from 'react';
3+
import type { SVGProps, ReactNode, MouseEvent, TouchEvent } from 'react';
4+
import type { UseDrag, HandlerArgs as DragHandlerArgs } from '@visx/drag';
5+
import { useDrag } from '@visx/drag';
56
import type { AnnotationContextType } from '../types';
67
import Annotation from './Annotation';
78

@@ -11,15 +12,15 @@ export type EditableAnnotationProps = Pick<AnnotationContextType, 'x' | 'y' | 'd
1112
/** Height of the possible drag canvas (e.g., SVG container). */
1213
height: number;
1314
/** Annotation children (Subject, Label, Connector) */
14-
children: React.ReactNode;
15+
children: ReactNode;
1516
/** Whether the Label position (dx, dy) is editable. */
1617
canEditLabel?: boolean;
1718
/** Whether the Subject position (x, y) is editable. */
1819
canEditSubject?: boolean;
1920
/** Optional circle props to set on the subject drag handle. */
20-
subjectDragHandleProps?: React.SVGProps<SVGCircleElement>;
21+
subjectDragHandleProps?: SVGProps<SVGCircleElement>;
2122
/** Optional circle props to set on the label drag handle. */
22-
labelDragHandleProps?: React.SVGProps<SVGCircleElement>;
23+
labelDragHandleProps?: SVGProps<SVGCircleElement>;
2324
/** Callback invoked on drag start. */
2425
onDragStart?: ({ x, y, dx, dy, event }: HandlerArgs) => void;
2526
/** Callback invoked on drag move. */
@@ -33,7 +34,7 @@ export type HandlerArgs = {
3334
y: number;
3435
dx: number;
3536
dy: number;
36-
event: React.MouseEvent | React.TouchEvent;
37+
event: MouseEvent | TouchEvent;
3738
};
3839

3940
const defaultDragHandleProps = {
@@ -62,8 +63,8 @@ export default function EditableAnnotation({
6263
}: EditableAnnotationProps) {
6364
// chicken before the egg, we need these to reference drag state
6465
// in drag callbacks which are defined before useDrag() state is available
65-
const subjectDragRef = useRef<UseDrag>();
66-
const labelDragRef = useRef<UseDrag>();
66+
const subjectDragRef = useRef<UseDrag | undefined>(undefined);
67+
const labelDragRef = useRef<UseDrag | undefined>(undefined);
6768

6869
const handleDragStart = useCallback(
6970
({ event }: DragHandlerArgs) => {

packages/visx-annotation/src/components/HtmlLabel.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import React, { useContext, useMemo } from 'react';
1+
import { useContext, useMemo } from 'react';
2+
import type { ReactNode, CSSProperties } from 'react';
23
import cx from 'classnames';
34
import useMeasure from 'react-use-measure';
45
import { Group } from '@visx/group';
@@ -20,9 +21,9 @@ export type HtmlLabelProps = Pick<
2021
| 'y'
2122
> & {
2223
/** Pass in a custom element as the label to style as you like. Renders inside a <foreignObject>, be aware that most non-browser SVG renderers will not render HTML <foreignObject>s. See: https://github.com/airbnb/visx/issues/1173#issuecomment-1014380545. */
23-
children?: React.ReactNode;
24+
children?: ReactNode;
2425
/** Optional styles to apply to the HTML container. */
25-
containerStyle?: React.CSSProperties;
26+
containerStyle?: CSSProperties;
2627
};
2728
export default function HtmlLabel({
2829
anchorLineStroke = '#222',

0 commit comments

Comments
 (0)