Skip to content

Commit 879465a

Browse files
committed
fix(styled): react 19 support (fixes callstack#1431)
1 parent e52a567 commit 879465a

File tree

4 files changed

+9531
-7393
lines changed

4 files changed

+9531
-7393
lines changed

.changeset/funny-meals-brake.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@linaria/react': patch
3+
---
4+
5+
Support for React 19

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383
},
8484
"engines": {
8585
"node": ">=16.0.0",
86-
"pnpm": "^8.0.0"
86+
"pnpm": "^9.0.0"
8787
},
88-
"packageManager": "pnpm@8.15.7+sha256.50783dd0fa303852de2dd1557cd4b9f07cb5b018154a6e76d0f40635d6cee019"
88+
"packageManager": "pnpm@9.15.9+sha256.cf86a7ad764406395d4286a6d09d730711720acc6d93e9dce9ac7ac4dc4a28a7"
8989
}

packages/react/src/styled.ts

+31-12
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
/* eslint-disable @typescript-eslint/no-explicit-any */
22
/**
3-
* This file contains an runtime version of `styled` component. Responsibilities of the component are:
3+
* This file contains a runtime version of `styled` component. Responsibilities of the component are:
44
* - returns ReactElement based on HTML tag used with `styled` or custom React Component
55
* - injects classNames for the returned component
66
* - injects CSS variables used to define dynamic styles based on props
77
*/
88
import validAttr from '@emotion/is-prop-valid';
9-
import React from 'react';
9+
import { createElement, forwardRef } from 'react';
10+
import type React from 'react';
1011

1112
import { cx } from '@linaria/core';
1213
import type { CSSProperties } from '@linaria/core';
@@ -106,8 +107,26 @@ interface IProps {
106107
style?: Record<string, string>;
107108
}
108109

110+
// React <19
111+
declare global {
112+
// eslint-disable-next-line @typescript-eslint/no-namespace
113+
namespace JSX {
114+
interface IntrinsicElements {}
115+
}
116+
}
117+
118+
// React >=19
119+
declare module 'react' {
120+
// eslint-disable-next-line @typescript-eslint/no-namespace
121+
namespace JSX {
122+
interface IntrinsicElements {}
123+
}
124+
}
125+
109126
let idx = 0;
110127

128+
type IntrinsicElements = React.JSX.IntrinsicElements & JSX.IntrinsicElements;
129+
111130
// Components with props are not allowed
112131
function styled(
113132
componentWithStyle: () => any
@@ -128,7 +147,7 @@ function styled<
128147
>(
129148
componentWithoutStyle: TConstructor & Component<TProps>
130149
): ComponentStyledTagWithoutInterpolation<TConstructor>;
131-
function styled<TName extends keyof React.JSX.IntrinsicElements>(
150+
function styled<TName extends keyof IntrinsicElements>(
132151
tag: TName
133152
): HtmlStyledTag<TName>;
134153
function styled(
@@ -211,13 +230,13 @@ function styled(tag: any): any {
211230
// Otherwise the styles from the underlying component will be ignored
212231
filteredProps.as = component;
213232

214-
return React.createElement(tag, filteredProps);
233+
return createElement(tag, filteredProps);
215234
}
216-
return React.createElement(component, filteredProps);
235+
return createElement(component, filteredProps);
217236
};
218237

219-
const Result = React.forwardRef
220-
? React.forwardRef(render)
238+
const Result = forwardRef
239+
? forwardRef(render)
221240
: // React.forwardRef won't available on older React versions and in Preact
222241
// Fallback to a innerRef prop in that case
223242
(props: any) => {
@@ -244,7 +263,7 @@ export type StyledComponent<T> = WYWEvalMeta &
244263

245264
type StaticPlaceholder = string | number | CSSProperties | WYWEvalMeta;
246265

247-
export type HtmlStyledTag<TName extends keyof React.JSX.IntrinsicElements> = <
266+
export type HtmlStyledTag<TName extends keyof IntrinsicElements> = <
248267
TAdditionalProps = Record<never, unknown>,
249268
>(
250269
strings: TemplateStringsArray,
@@ -253,10 +272,10 @@ export type HtmlStyledTag<TName extends keyof React.JSX.IntrinsicElements> = <
253272
| ((
254273
// Without Omit here TS tries to infer TAdditionalProps
255274
// from a component passed for interpolation
256-
props: React.JSX.IntrinsicElements[TName] & Omit<TAdditionalProps, never>
275+
props: IntrinsicElements[TName] & Omit<TAdditionalProps, never>
257276
) => string | number)
258277
>
259-
) => StyledComponent<React.JSX.IntrinsicElements[TName] & TAdditionalProps>;
278+
) => StyledComponent<IntrinsicElements[TName] & TAdditionalProps>;
260279

261280
type ComponentStyledTagWithoutInterpolation<TOrigCmp> = (
262281
strings: TemplateStringsArray,
@@ -278,14 +297,14 @@ type ComponentStyledTagWithInterpolation<TTrgProps, TOrigCmp> = <OwnProps = {}>(
278297
: StyledComponent<OwnProps & TTrgProps>;
279298

280299
export type StyledJSXIntrinsics = {
281-
readonly [P in keyof React.JSX.IntrinsicElements]: HtmlStyledTag<P>;
300+
readonly [P in keyof IntrinsicElements]: HtmlStyledTag<P>;
282301
};
283302

284303
export type Styled = typeof styled & StyledJSXIntrinsics;
285304

286305
export default (process.env.NODE_ENV !== 'production'
287306
? new Proxy(styled, {
288-
get(o, prop: keyof React.JSX.IntrinsicElements) {
307+
get(o, prop: keyof IntrinsicElements) {
289308
return o(prop);
290309
},
291310
})

0 commit comments

Comments
 (0)