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

Support of react 19 + add a CI for it #543

Merged
merged 18 commits into from
Dec 9, 2024
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
7 changes: 7 additions & 0 deletions .changeset/ten-geckos-promise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@hopper-ui/styled-system": minor
"@hopper-ui/components": minor
"@hopper-ui/icons": minor
---

Added support to React 19
31 changes: 31 additions & 0 deletions .github/composite-actions/setup/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Setup Node and PNPM

runs:
using: composite
steps:
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc"

- name: Install pnpm
uses: pnpm/action-setup@v4
id: pnpm-install
with:
version: 9
run_install: false

- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT

- name: Setup pnpm cache
uses: actions/cache@v4
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-

31 changes: 4 additions & 27 deletions .github/workflows/changeset.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,13 @@ jobs:
pull-requests: write

steps:
- name: Checkout
- name: Checkout code
uses: actions/checkout@v4

- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc"

- name: Install pnpm
uses: pnpm/action-setup@v4
id: pnpm-install
with:
version: 9
run_install: false

- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT

- name: Setup pnpm cache
uses: actions/cache@v4
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Setup Node and PNPM
uses: ./.github/composite-actions/setup

- name: Install Dependencies
- name: Install dependencies
run: pnpm i --frozen-lockfile

- name: Create release Pull Request or publish to NPM
Expand Down
27 changes: 2 additions & 25 deletions .github/workflows/chromatic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,31 +33,8 @@ jobs:
with:
fetch-depth: 0

- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc"

- uses: pnpm/action-setup@v4
name: Install pnpm
id: pnpm-install
with:
version: 9
run_install: false

- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT

- name: Setup pnpm cache
uses: actions/cache@v4
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Setup Node and PNPM
uses: ./.github/composite-actions/setup

- name: Install dependencies
run: pnpm i --frozen-lockfile
Expand Down
41 changes: 41 additions & 0 deletions .github/workflows/ci-react19.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: CI React 19

# Pnpm setup based on https://github.com/pnpm/action-setup#use-cache-to-reduce-installation-time

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

env:
CI: true

concurrency:
group: ci-react19-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node and PNPM
uses: ./.github/composite-actions/setup
with:
install_dependencies: false

- name: Install React 19
run: pnpm install-react19

- name: Install dependencies
run: pnpm i

- name: Build packages
run: pnpm build:pkg

- name: Test packages
run: pnpm test
29 changes: 3 additions & 26 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,34 +20,11 @@ jobs:
runs-on: ubuntu-latest

steps:
- name: Checkout
- name: Checkout code
uses: actions/checkout@v4

- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc"

- uses: pnpm/action-setup@v4
name: Install pnpm
id: pnpm-install
with:
version: 9
run_install: false

- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT

- name: Setup pnpm cache
uses: actions/cache@v4
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Setup Node and PNPM
uses: ./.github/composite-actions/setup

- name: Install dependencies
run: pnpm i --frozen-lockfile
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { withContentlayer } from "next-contentlayer";
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
swcMinify: true, // This will be enabled by default and removed in Next.js 15
productionBrowserSourceMaps: true,
// Eslint only lint pages/, app/, components/, lib/, and src/ directories by default. So we need to add other directories to the eslint config.
// https://nextjs.org/docs/app/building-your-application/configuring/eslint#linting-custom-directories-and-files
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"build:apps": "pnpm -r --filter \"{apps/**}\" build ",
"changeset": "changeset",
"ci-release": "pnpm build:pkg && changeset publish",
"aa": "cd ./apps/docs && pnpm generate:previewRef",
"install-react19": "pnpm -r --filter \"{packages/**}\" add -D react@19 react-dom@19 @types/react@19 @types/react-dom@19 && pnpm add -D -w react@19 react-dom@19 @types/react@19 @types/react-dom@19",
"generate-icons": "pnpm --filter=\"svg-icons\" generate-icons && pnpm --filter=\"@hopper-ui/icons*\" generate-icons",
"lint": "pnpm run \"/^lint:.*/\"",
"lint:eslint": "eslint . --max-warnings=0 --cache --cache-location node_modules/.cache/eslint",
Expand Down
2 changes: 1 addition & 1 deletion packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
},
"peerDependencies": {
"@hopper-ui/styled-system": "^2.4",
"react": "^18",
"react": "^18 || ^19",
"react-aria": "^3.36",
"react-aria-components": "^1.5",
"react-dom": "^18"
Expand Down
12 changes: 6 additions & 6 deletions packages/components/src/Avatar/src/useImageFallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export interface ImageFallbackReturnProps {
status: Status;
}

type Status =
type Status =
"loading" /* When the image is loading. */
| "failed" /* The image has failed to load. */
| "pending" /* There is no src, but it's in a pending state since it could be updated in the future. */
Expand All @@ -47,11 +47,11 @@ export function useImageFallback(props: ImageFallbackProps): ImageFallbackReturn
setStatus(src ? "loading" : "pending");
}, [src]);

const imageRef = useRef<HTMLImageElement | null>();
const imageRef = useRef<HTMLImageElement | null>(null);

const load = useCallback(() => {
if (!src) {return;}

flush();

const image = new Image();
Expand All @@ -76,7 +76,7 @@ export function useImageFallback(props: ImageFallbackProps): ImageFallbackReturn
}
onError?.(event as unknown as ImageEvent);
};

imageRef.current = image;
}, [src, onLoad, fallbackSrc, onError]);

Expand All @@ -92,11 +92,11 @@ export function useImageFallback(props: ImageFallbackProps): ImageFallbackReturn
if (status === "loading") {
load();
}

return () => {
flush();
};
}, [status, load]);

return { imageUrl, status };
}
}
4 changes: 2 additions & 2 deletions packages/components/src/utils/src/isTextOnlyChildren.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Children, Fragment, isValidElement, type ReactNode } from "react";
import { Children, Fragment, isValidElement, type PropsWithChildren, type ReactNode } from "react";

/**
* Determines whether the provided React children consist only of text content.
Expand All @@ -11,7 +11,7 @@ export function isTextOnlyChildren(children: ReactNode) {
}

function resolveChildren(children: ReactNode) {
if (isValidElement(children) && children.type === Fragment) {
if (isValidElement<PropsWithChildren>(children) && children.type === Fragment) {
return resolveChildren(children.props.children);
}

Expand Down
4 changes: 2 additions & 2 deletions packages/components/src/utils/src/useIsOverflow.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useIsomorphicLayoutEffect } from "@hopper-ui/styled-system";
import { type RefObject, useState } from "react";

export const useIsOverflow = (ref?: RefObject<HTMLElement>, callback?: (isOverflow: boolean) => void) => {
export const useIsOverflow = (ref: RefObject<HTMLElement | null>, callback?: (isOverflow: boolean) => void) => {
const [isOverflow, setIsOverflow] = useState(false);

useIsomorphicLayoutEffect(() => {
Expand All @@ -27,4 +27,4 @@ export const useIsOverflow = (ref?: RefObject<HTMLElement>, callback?: (isOverfl
}, [callback, ref, ref?.current]);

return isOverflow;
};
};
2 changes: 1 addition & 1 deletion packages/icons/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
},
"peerDependencies": {
"@hopper-ui/styled-system": "^2.4",
"react": "^18",
"react": "^18 || ^19",
"react-aria-components": "^1.5",
"react-dom": "^18"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useRef, useState } from "react";
import { useRef, useState, type RefObject } from "react";

import { useColorSchemeContext, type ColorScheme } from "../color-scheme/ColorSchemeContext.ts";
import { StyledSystemRootCssClass } from "../styledSystemRootCssClass.ts";
Expand Down Expand Up @@ -36,7 +36,7 @@ export function BodyStyleProvider() {

useIsomorphicLayoutEffect(() => {
if (ref.current) {
const computedStyle = new ThemeComputedStyle(ref, `.${StyledSystemRootCssClass}`);
const computedStyle = new ThemeComputedStyle(ref as RefObject<Element>, `.${StyledSystemRootCssClass}`);

const color = computedStyle.getPropertyValue(BodyTokens.color);
const backgroundColor = computedStyle.getPropertyValue(BodyTokens.backgroundColor);
Expand Down
4 changes: 2 additions & 2 deletions packages/styled-system/src/html-wrappers/htmlElement.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import clsx from "clsx";
import { forwardRef, type CSSProperties, type ElementRef } from "react";
import { forwardRef, type CSSProperties, type ComponentRef, type JSX } from "react";

import type { StyledComponentProps } from "../styledSystemProps.ts";
import { useStyledSystem } from "../useStyledSystem.ts";
Expand All @@ -12,7 +12,7 @@ export const GlobalHtmlElementCssSelector = "hop-HtmlElement";
export const GlobalHtmlElementSpecificCssSelector = (elementType: string) => `${GlobalHtmlElementCssSelector}-${elementType}`;

export function htmlElement<T extends keyof JSX.IntrinsicElements>(elementType: T) {
return forwardRef<ElementRef<T>, HtmlElementProps<T>>((props, ref) => {
return forwardRef<ComponentRef<T>, HtmlElementProps<T>>((props, ref) => {
const { stylingProps, ...ownProps } = useStyledSystem(props);
const { className, style, ...otherProps } = ownProps;

Expand Down
2 changes: 1 addition & 1 deletion packages/styled-system/src/styledSystemProps.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// this file will contain handlers for all the style props
import type { Property } from "csstype";
import type { ComponentProps, JSXElementConstructor } from "react";
import type { ComponentProps, JSX, JSXElementConstructor } from "react";

import type { ResponsiveProp } from "./responsive/useResponsiveValue.tsx";
import type {
Expand Down
Loading
Loading