Skip to content
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Significance: patch
Type: fixed
Comment: Fix typing for React 19: onInput is an `InputEvent`, not a `ChangeEvent`.


Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import './prompt.scss';
* Types
*/
import type { ImageStyle, ImageStyleObject } from '../../hooks/use-image-generator/constants.ts';
import type { ChangeEvent, ClipboardEvent, KeyboardEvent } from 'react';
import type { ClipboardEvent, InputEvent, KeyboardEvent } from 'react';

const debug = debugFactory( 'jetpack-ai-calypso:prompt-box' );

Expand All @@ -57,8 +57,8 @@ export const AiModalPromptInput = ( {
} ) => {
const inputRef = useRef< HTMLDivElement | null >( null );

const onPromptInput = ( event: ChangeEvent< HTMLInputElement > ) => {
setPrompt( event.target.textContent || '' );
const onPromptInput = ( event: InputEvent< HTMLInputElement > ) => {
setPrompt( ( event.target as HTMLInputElement ).textContent || '' );
};

const onPromptPaste = ( event: ClipboardEvent< HTMLInputElement > ) => {
Expand Down
5 changes: 5 additions & 0 deletions projects/js-packages/charts/changelog/fix-misc-react-19-stuff
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Significance: patch
Type: changed
Comment: Fix typing for React 19: `FC<>` now wants to allow for returning async, which the places we use `renderLabel` and `renderLabelPopover` can't actually handle. So declare their types without the `FC<>` helper.


Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Significance: patch
Type: changed
Comment: React 19 recognizes `popoverTarget` and `popoverTargetAction`, and rejects `popovertarget` and `popovertargetaction`, while React 18 needs the latter as it doesn't recognize the former. So supply whichever is appropriate at runtime based on the React version.


Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { __ } from '@wordpress/i18n';
import { Stack } from '@wordpress/ui';
import clsx from 'clsx';
import { useEffect, useId, useRef, useState } from 'react';
import { useEffect, useId, useRef, useState, version as reactVersion } from 'react';
import { isSafari } from '../../../utils';
import styles from '../line-chart.module.scss';
import type { ButtonWithPopover, PopoverElement, ToggleEvent } from '../../../types';
import type { FC } from 'react';
import type { FC, ReactNode } from 'react';

export const POPOVER_BUTTON_SIZE = 44;

// @todo Remove this (and uses of it below) when we drop support for WordPress versions shipping React 18.
const isReact18 = reactVersion.startsWith( '18.' );

const CloseIcon = () => (
<svg
width="16"
Expand All @@ -29,8 +32,8 @@ const CloseIcon = () => (
interface LineChartAnnotationLabelWithPopoverProps {
title: string;
subtitle?: string;
renderLabel: FC< { title: string; subtitle?: string } >;
renderLabelPopover: FC< { title: string; subtitle?: string } >;
renderLabel: ( props: { title: string; subtitle?: string } ) => ReactNode;
renderLabelPopover: ( props: { title: string; subtitle?: string } ) => ReactNode;
}

const LineChartAnnotationLabelWithPopover: FC< LineChartAnnotationLabelWithPopoverProps > = ( {
Expand Down Expand Up @@ -83,7 +86,9 @@ const LineChartAnnotationLabelWithPopover: FC< LineChartAnnotationLabelWithPopov
<div className={ styles[ 'line-chart__annotation-label' ] }>
<button
ref={ buttonRef }
{ ...( { popovertarget: popoverId } as ButtonWithPopover ) }
{ ...( isReact18
? ( { popovertarget: popoverId } as ButtonWithPopover )
: { popoverTarget: popoverId } ) }
className={ styles[ 'line-chart__annotation-label-trigger-button' ] }
style={ {
width: `${ POPOVER_BUTTON_SIZE }px`,
Expand All @@ -110,10 +115,15 @@ const LineChartAnnotationLabelWithPopover: FC< LineChartAnnotationLabelWithPopov
{ renderLabelPopover( { title, subtitle } ) }
</div>
<button
{ ...( {
popovertarget: popoverId,
popovertargetaction: 'hide',
} as ButtonWithPopover ) }
{ ...( isReact18
? ( {
popovertarget: popoverId,
popovertargetaction: 'hide',
} as ButtonWithPopover )
: {
popoverTarget: popoverId,
popoverTargetAction: 'hide',
} ) }
className={ styles[ 'line-chart__annotation-label-popover-close-button' ] }
aria-label={ __( 'Close', 'jetpack-charts' ) }
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ Individual annotation component for highlighting specific data points or events.
| `subtitle` | `string` | - | Additional descriptive text |
| `subjectType` | `'circle' \| 'line-vertical' \| 'line-horizontal'` | `'circle'` | Visual annotation style |
| `styles` | `AnnotationStyles` | - | Custom styling options |
| `renderLabel` | `FC<{title: string, subtitle?: string}>` | - | Custom label component. **Disables smart positioning.** |
| `renderLabelPopover` | `FC<{title: string, subtitle?: string}>` | - | Interactive popover content |
| `renderLabel` | `(props: {title: string, subtitle?: string} ) => ReactNode` | - | Custom label component. **Disables smart positioning.** |
| `renderLabelPopover` | `(props: {title: string, subtitle?: string}) => ReactNode` | - | Interactive popover content |
| `testId` | `string` | - | Test identifier |

## SeriesData Type
Expand Down
6 changes: 3 additions & 3 deletions projects/js-packages/charts/src/charts/line-chart/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type {
} from '../../types';
import type { CrosshairStyle, RenderTooltipParams } from '../../visx/types';
import type { GlyphProps } from '@visx/xychart';
import type { ReactNode, SVGProps, FC, CSSProperties } from 'react';
import type { ReactNode, SVGProps, CSSProperties } from 'react';

export type LineChartAnnotationProps = {
datum: DataPointDate;
Expand All @@ -19,8 +19,8 @@ export type LineChartAnnotationProps = {
subjectType?: 'circle' | 'line-vertical' | 'line-horizontal';
styles?: AnnotationStyles;
testId?: string;
renderLabel?: FC< { title: string; subtitle?: string } >;
renderLabelPopover?: FC< { title: string; subtitle?: string } >;
renderLabel?: ( props: { title: string; subtitle?: string } ) => ReactNode;
renderLabelPopover?: ( props: { title: string; subtitle?: string } ) => ReactNode;
};

export type CurveType = 'smooth' | 'linear' | 'monotone';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Significance: patch
Type: removed
Comment: React 19 wants `transformOrigin`, while 18 needs `transform-origin`. It turns out there are no transforms anymore needing an origin in the first place, so just remove it.


Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@ const DonutMeter: FC< DonutMeterProps > = ( {
cy="20"
r="15.91549430918954"
fill="transparent"
transform-origin="center" // eslint-disable-line react/no-unknown-property -- @todo Switch to transformOrigin when we use React 19.
strokeWidth={ thickness }
strokeDasharray={ `${ percentage } ${ 100 - percentage }` }
strokeDashoffset="-25" // this ensures the segment begins at the bottom of the donut instead of the top
Expand Down
5 changes: 5 additions & 0 deletions projects/packages/backup/changelog/fix-misc-react-19-stuff
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Significance: patch
Type: fixed
Comment: The `useRestore` test was advancing jest's fake timer by a large amount. React 19 doesn't like this: it doesn't get a gap between updates and winds up throwing a "Maximum update depth exceeded" error. Advance in steps of `POLL_INTERVAL_MS` instead, which gives React 19 the gaps it needs.


Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import apiFetch from '@wordpress/api-fetch';
import { createElement, type ReactNode } from 'react';
import { pickLiveRestore } from '../../data/api/restore';
import { DEFAULT_RESTORE_ITEMS } from '../../types/restore';
import { useRestore } from '../use-restore';
import { useRestore, POLL_INTERVAL_MS } from '../use-restore';

jest.mock( '@wordpress/api-fetch', () => ( { __esModule: true, default: jest.fn() } ) );
const mockedApiFetch = apiFetch as unknown as jest.Mock;
Expand Down Expand Up @@ -97,9 +97,13 @@ function submitAll( result: RenderedRestore ) {
* @param ms - How far to advance.
*/
async function advance( ms: number ) {
await act( async () => {
await jest.advanceTimersByTimeAsync( ms );
} );
// Advance in small steps (POLL_INTERVAL_MS). Longer steps never give React 19 a gap between updates, so it throws "Maximum update depth exceeded".
while ( ms > 0 ) {
await act( async () => {
await jest.advanceTimersByTimeAsync( Math.min( ms, POLL_INTERVAL_MS ) );
} );
ms -= POLL_INTERVAL_MS;
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ type Result = {
* no responsiveness and costs a WordPress.com round trip per tick for its
* whole duration.
*/
const POLL_INTERVAL_MS = 5000;
export const POLL_INTERVAL_MS = 5000;

/**
* How long the screen will go without a recognisable sign of life before
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ describe( 'ManageConnectionsModal', () => {
// some via timers) so no state update escapes act.
await act( async () => {
await Promise.resolve();
jest.runAllTimers();
await jest.runAllTimersAsync();
} );
await act( async () => {
jest.runAllTimers();
await jest.runAllTimersAsync();
} );
};

Expand Down
5 changes: 5 additions & 0 deletions projects/packages/publicize/changelog/fix-misc-react-19-stuff
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Significance: patch
Type: fixed
Comment: The `ManageConnectionsModal` test breaks in React 19. Using `await jest.runAllTimersAsync()` instead of `jest.runAllTimers()` in the already-async `act()` call fixes this.


Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Significance: patch
Type: fixed
Comment: Fix another argless `useRef` added since #53002 fixed all the rest. Sigh.


2 changes: 1 addition & 1 deletion projects/packages/videopress/routes/video/stage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ const StageInner = () => {
? id
: Object.keys( completedUploads ).find( key => completedUploads[ key ] === id );
const queuedUpload = uploadQueue.find( item => item.id === id );
const retainedUpload = useRef< UploadItem >();
const retainedUpload = useRef< UploadItem >( undefined );
// Keep the editor present if queue cleanup precedes a slow attachment fetch.
if ( queuedUpload ) {
retainedUpload.current = queuedUpload;
Expand Down
4 changes: 3 additions & 1 deletion projects/plugins/jetpack/_inc/client/ai/test/main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,9 @@ describe( 'AI admin page (main.jsx)', () => {
);
// One page-level notice — AiFeatures must not render a second copy.
expect( screen.getAllByText( MASTER_OFF_TITLE, IGNORE_A11Y ) ).toHaveLength( 1 );
expect( screen.getByRole( 'checkbox', { name: /Writing Assistant/ } ) ).toBeDisabled();
await expect(
screen.findByRole( 'checkbox', { name: /Writing Assistant/ } )
).resolves.toBeDisabled();
} );

test( 'a host without My Jetpack is sent to the modules page instead', async () => {
Expand Down
5 changes: 5 additions & 0 deletions projects/plugins/jetpack/changelog/fix-misc-react-19-stuff
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Significance: patch
Type: other
Comment: An `AI admin page` test was looking for the "Writing Assistant" checkbox synchronously, even though it gets added asynchronously and all the other tests look for it async. Somehow this worked ok in React 18, but breaks in 19; looking async like everything else does fixes it.


Loading