Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

upgrade to react 19 #234

Merged
merged 11 commits into from
Dec 10, 2024
Merged
Changes from 1 commit
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
Next Next commit
upgrade to react 19
  • Loading branch information
jantimon committed Dec 9, 2024
commit a68be906aecf109666cce098bfb12cbe705bd8f7
6 changes: 3 additions & 3 deletions packages/benchmarks/package.json
Original file line number Diff line number Diff line change
@@ -16,10 +16,10 @@
},
"dependencies": {
"@swc/core": "1.7.42",
"next": "15.0.2",
"next": "15.0.4",
"next-yak": "workspace:*",
"react": "18.3.1",
"react-dom": "18.3.1",
"react": "19.0.0",
"react-dom": "19.0.0",
"styled-components": "6.1.1",
"yak-swc": "workspace:^"
},
13 changes: 7 additions & 6 deletions packages/example/package.json
Original file line number Diff line number Diff line change
@@ -18,19 +18,20 @@
},
"dependencies": {
"@types/node": "20.4.5",
"@types/react": "18.3.12",
"@types/react-dom": "18.3.1",
"next": "15.0.2",
"@types/react": "19.0.1",
"@types/react-dom": "19.0.1",
"next": "15.0.4",
"next-yak": "workspace:*",
"postcss-nested": "^6.2.0",
"react": "18.3.1",
"react-dom": "18.3.1",
"react": "19.0.0",
"react-dom": "19.0.0",
"typescript": "5.5.2",
"yak-swc": "workspace:*"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^14.0.0",
"@testing-library/dom": "10.4.0",
"@testing-library/react": "^16.1.0",
"@types/jest": "^29.5.12",
"@vitejs/plugin-react": "4.3.1",
"jest": "^29.6.2",
14 changes: 7 additions & 7 deletions packages/next-yak/package.json
Original file line number Diff line number Diff line change
@@ -84,17 +84,17 @@
"@types/webpack": "5.28.5",
"@babel/types": "7.23.0",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^14.0.0",
"@testing-library/react": "^16.1.0",
"@types/jest": "29.5.5",
"@types/node": "20.4.5",
"@types/react": "18.3.12",
"@types/react-dom": "18.3.1",
"@types/react": "19.0.1",
"@types/react-dom": "19.0.1",
"@types/react-test-renderer": "^18.0.3",
"fast-glob": "3.3.2",
"jsdom": "^22.1.0",
"next": "15.0.2",
"react": "18.3.1",
"react-test-renderer": "18.3.1",
"jsdom": "^25.0.1",
"next": "15.0.4",
"react": "19.0.0",
"react-test-renderer": "19.0.0",
"typescript": "5.5.2",
"vite": "5.3.4",
"vitest": "2.0.4",
2 changes: 1 addition & 1 deletion packages/next-yak/runtime/jsx-runtime.ts
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ export declare namespace YakJSX {
export type IntrinsicClassAttributes<T> =
React.JSX.IntrinsicClassAttributes<T>;
export type IntrinsicElements = {
[K in keyof JSX.IntrinsicElements]: React.JSX.IntrinsicElements[K] & {
[K in keyof React.JSX.IntrinsicElements]: React.JSX.IntrinsicElements[K] & {
css?: StaticCSSProp;
};
};
95 changes: 50 additions & 45 deletions packages/next-yak/runtime/styled.tsx
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ const yakForwardRef: <
TAttrsOut extends AttrsMerged<TProps, TAttrsIn>,
>(
component: ForwardRefRenderFunction<any, TProps>,
attrsFn?: (props: any) => any,
attrsFn?: (props: any) => any
) => YakComponent<TProps, TAttrsIn, TAttrsOut> = (component, attrsFn) =>
Object.assign(React.forwardRef(component as any), {
[yakComponentSymbol]: [component, attrsFn],
@@ -37,13 +37,13 @@ const yakForwardRef: <
*/
type FunctionComponent<T> = (
props: T,
context?: any,
context?: any
) => React.ReactNode | React.ReactElement;

/**
* All valid html tags
*/
type HtmlTags = keyof JSX.IntrinsicElements;
type HtmlTags = keyof React.JSX.IntrinsicElements;

/**
* Return type of the provided props merged with the initial props
@@ -88,7 +88,7 @@ const StyledFactory = <T,>(Component: HtmlTags | FunctionComponent<T>) =>
TAttrsIn extends object = {},
TAttrsOut extends AttrsMerged<T, TAttrsIn> = AttrsMerged<T, TAttrsIn>,
>(
attrs: Attrs<T, TAttrsIn, TAttrsOut>,
attrs: Attrs<T, TAttrsIn, TAttrsOut>
) => yakStyled<T, TAttrsIn, TAttrsOut>(Component, attrs),
});

@@ -117,7 +117,7 @@ const yakStyled = <
| FunctionComponent<T>
| YakComponent<T, TAttrsIn, TAttrsOut>
| HtmlTags,
attrs?: Attrs<T, TAttrsIn, TAttrsOut>,
attrs?: Attrs<T, TAttrsIn, TAttrsOut>
) => {
const isYakComponent =
typeof Component !== "string" && yakComponentSymbol in Component;
@@ -138,7 +138,7 @@ const yakStyled = <
>
) => {
const getRuntimeStyles = css(styles, ...(values as any));
const yak = (props: Substitute<TCSSProps & T, TAttrsIn>, ref: unknown) => {
const yak = (props: Substitute<TCSSProps & T, TAttrsIn>) => {
// if the css component does not require arguments
// it can be called without arguments and we skip calling useTheme()
//
@@ -159,12 +159,7 @@ const yakStyled = <
// starting from the innermost yak component to the outermost yak component (itself)
const combinedProps =
"$__attrs" in props
? // if the props already contain the $__attrs key, we assume that the props have already been processed
// and skip processing the attrs again.
// e.g. const Child = styled(Parent)`color: red;`
// We process the attrs once in the child (with all attrs functions merged (including the one from the child))
// and in the subsequent call in the parent we skip processing the attrs again
{
? {
theme,
...props,
}
@@ -182,7 +177,7 @@ const yakStyled = <
mergedAttrsFn?.({ theme, ...props } as Substitute<
T & { theme: YakTheme },
TAttrsIn
>),
>)
);
// execute all functions inside the style literal
// e.g. styled.button`color: ${props => props.color};`
@@ -192,39 +187,47 @@ const yakStyled = <
// this must happen after the runtimeStyles are calculated
// prevents passing the theme prop to the DOM element of a styled component
const { theme: themeAfterAttr, ...combinedPropsWithoutTheme } =
combinedProps as { theme?: unknown };
combinedProps;
const propsBeforeFiltering =
themeAfterAttr === theme ? combinedPropsWithoutTheme : combinedProps;

// remove all props that start with a $ sign for string components e.g. "button" or "div"
// so that they are not passed to the DOM element
const filteredProps = !isYakComponent
? removeNonDomProperties(propsBeforeFiltering)
: propsBeforeFiltering;

// yak provides a className and style prop that needs to be merged with the
// user provided className and style prop
(filteredProps as { className?: string }).className = mergeClassNames(
(filteredProps as { className?: string }).className,
runtimeStyles.className,
const filteredProps = (
!isYakComponent
? removeNonDomProperties(propsBeforeFiltering)
: propsBeforeFiltering
) as T & {
className?: string;
style?: React.CSSProperties;
};

filteredProps.className = mergeClassNames(
filteredProps.className,
runtimeStyles.className
);
(filteredProps as { style?: React.CSSProperties }).style =
filteredProps.style =
"style" in filteredProps
? {
...(filteredProps as { style?: React.CSSProperties }).style,
...filteredProps.style,
...runtimeStyles.style,
}
: runtimeStyles.style;
// if the styled(Component) syntax is used and the component is a yak component
// we can call the yak function directly to avoid an unnecessary wrapper with an additional
// forwardRef call
if (parentYakComponent) {
return parentYakComponent(filteredProps as T, ref);
}
(filteredProps as { ref?: unknown }).ref = ref;
return <Component {...(filteredProps as any)} />;

return parentYakComponent ? (
// if the styled(Component) syntax is used and the component is a yak component
// we can call the yak function directly without running through react createElement
parentYakComponent(filteredProps)
) : (
// if the final component is a string component e.g. styled("div") or a custom non yak fn e.g. styled(MyComponent)
<Component {...filteredProps} />
);
};
return yakForwardRef(yak, mergedAttrsFn);

// Assign the yakComponentSymbol directly without forwardRef
return Object.assign(yak, {
[yakComponentSymbol]: [yak, mergedAttrsFn],
});
};
};

@@ -259,23 +262,23 @@ type StyledLiteral<T> = <TCSSProps>(
*/
export const styled = new Proxy(
StyledFactory as typeof StyledFactory & {
[Tag in HtmlTags]: StyledLiteral<JSX.IntrinsicElements[Tag]> & {
[Tag in HtmlTags]: StyledLiteral<React.JSX.IntrinsicElements[Tag]> & {
attrs: <
TAttrsIn extends object = {},
TAttrsOut extends AttrsMerged<
JSX.IntrinsicElements[Tag],
React.JSX.IntrinsicElements[Tag],
TAttrsIn
> = AttrsMerged<JSX.IntrinsicElements[Tag], TAttrsIn>,
> = AttrsMerged<React.JSX.IntrinsicElements[Tag], TAttrsIn>,
>(
attrs: Attrs<JSX.IntrinsicElements[Tag], TAttrsIn, TAttrsOut>,
) => StyledLiteral<Substitute<JSX.IntrinsicElements[Tag], TAttrsIn>>;
attrs: Attrs<React.JSX.IntrinsicElements[Tag], TAttrsIn, TAttrsOut>
) => StyledLiteral<Substitute<React.JSX.IntrinsicElements[Tag], TAttrsIn>>;
};
},
{
get(target, TagName: keyof JSX.IntrinsicElements) {
get(target, TagName: keyof React.JSX.IntrinsicElements) {
return target(TagName);
},
},
}
);

/**
@@ -284,7 +287,9 @@ export const styled = new Proxy(
* This allows to have props that are used for internal stylingen purposes
* but are not be passed to the DOM element
*/
const removeNonDomProperties = <T extends Record<string, unknown>>(obj: T) => {
const removeNonDomProperties = <T extends Record<string, unknown>>(
obj: T
): T => {
const result = {} as T;
for (const key in obj) {
if (!key.startsWith("$") && obj[key] !== undefined) {
@@ -322,7 +327,7 @@ const combineProps = <
| undefined,
>(
props: T,
newProps: TOther,
newProps: TOther
) =>
newProps
? (props.className === newProps.className || !newProps.className) &&
@@ -370,7 +375,7 @@ const buildRuntimeAttrsProcessor = <
TAttrsOut extends AttrsMerged<T, TAttrsIn>,
>(
attrs?: Attrs<T, TAttrsIn, TAttrsOut>,
parentAttrsFn?: AttrsFunction<T, TAttrsIn, TAttrsOut>,
parentAttrsFn?: AttrsFunction<T, TAttrsIn, TAttrsOut>
): AttrsFunction<T, TAttrsIn, TAttrsOut> | undefined => {
const ownAttrsFn =
attrs && (typeof attrs === "function" ? attrs : () => attrs);
@@ -386,7 +391,7 @@ const buildRuntimeAttrsProcessor = <
// the whole props object calculated from the previous attrs functions
return combineProps(
parentProps,
ownAttrsFn(combineProps(props, parentProps)),
ownAttrsFn(combineProps(props, parentProps))
);
};
}
Loading
Loading