From 2fe092ebcc901d0da4062e162d0723f4bd75b34b Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Thu, 5 Sep 2024 17:36:36 +0200 Subject: [PATCH] Composite: deprecate legacy, unstable version (#63572) * Add deprecated tags to JSDocs * Add deprecated console warnings * Update unit tests to expect the warnings * CHANGELOG * Remove mention of store hook --- Co-authored-by: ciampo Co-authored-by: tyxla --- packages/components/CHANGELOG.md | 4 + .../components/src/composite/legacy/index.tsx | 73 +++++++++++++++++-- .../src/composite/legacy/test/index.tsx | 58 ++++++++++++++- 3 files changed, 126 insertions(+), 9 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 499a3b69c06a2b..35549e8cb77998 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Deprecations + +- Deprecate `__unstableComposite`, `__unstableCompositeGroup`, `__unstableCompositeItem` and `__unstableUseCompositeState`. Consumers of the package should use the stable `Composite` component instead ([#63572](https://github.com/WordPress/gutenberg/pull/63572)). + ### New Features - `Composite`: add stable version of the component ([#63569](https://github.com/WordPress/gutenberg/pull/63569)). diff --git a/packages/components/src/composite/legacy/index.tsx b/packages/components/src/composite/legacy/index.tsx index cff564af1f8e7a..22ddff6572dd01 100644 --- a/packages/components/src/composite/legacy/index.tsx +++ b/packages/components/src/composite/legacy/index.tsx @@ -22,12 +22,13 @@ import * as Ariakit from '@ariakit/react'; * WordPress dependencies */ import { forwardRef } from '@wordpress/element'; +import { useInstanceId } from '@wordpress/compose'; +import deprecated from '@wordpress/deprecated'; /** * Internal dependencies */ import { Composite as Current } from '..'; -import { useInstanceId } from '@wordpress/compose'; type Orientation = 'horizontal' | 'vertical'; @@ -123,12 +124,31 @@ function mapLegacyStatePropsToComponentProps( return legacyProps; } +const LEGACY_TO_NEW_DISPLAY_NAME = { + __unstableComposite: 'Composite', + __unstableCompositeGroup: 'Composite.Group or Composite.Row', + __unstableCompositeItem: 'Composite.Item', + __unstableUseCompositeState: 'Composite', +}; + function proxyComposite< C extends Component >( ProxiedComponent: C | React.ForwardRefExoticComponent< C >, propMap: Record< string, string > = {} ): CompositeComponent< C > { - const displayName = ProxiedComponent.displayName; + const displayName = ProxiedComponent.displayName ?? ''; + const Component = ( legacyProps: CompositeStateProps ) => { + deprecated( `wp.components.${ displayName }`, { + since: '6.7', + alternative: LEGACY_TO_NEW_DISPLAY_NAME.hasOwnProperty( + displayName + ) + ? LEGACY_TO_NEW_DISPLAY_NAME[ + displayName as keyof typeof LEGACY_TO_NEW_DISPLAY_NAME + ] + : undefined, + } ); + const { store, ...rest } = mapLegacyStatePropsToComponentProps( legacyProps ); const props = rest as ComponentProps< C >; @@ -153,7 +173,7 @@ function proxyComposite< C extends Component >( // `CompositeRow`, but this has been split into two different // components. We handle that difference by checking on the // provided role, and returning the appropriate component. -const unproxiedCompositeGroup = forwardRef< +const UnproxiedCompositeGroup = forwardRef< any, React.ComponentPropsWithoutRef< typeof Current.Group | typeof Current.Row > >( ( { role, ...props }, ref ) => { @@ -161,15 +181,52 @@ const unproxiedCompositeGroup = forwardRef< return ; } ); -export const Composite = proxyComposite( Current, { baseId: 'id' } ); -export const CompositeGroup = proxyComposite( unproxiedCompositeGroup ); -export const CompositeItem = proxyComposite( Current.Item, { - focusable: 'accessibleWhenDisabled', -} ); +/** + * _Note: please use the `Composite` component instead._ + * + * @deprecated + */ +export const Composite = proxyComposite( + Object.assign( Current, { displayName: '__unstableComposite' } ), + { baseId: 'id' } +); +/** + * _Note: please use the `Composite.Row` or `Composite.Group` components instead._ + * + * @deprecated + */ +export const CompositeGroup = proxyComposite( + Object.assign( UnproxiedCompositeGroup, { + displayName: '__unstableCompositeGroup', + } ) +); +/** + * _Note: please use the `Composite.Item` component instead._ + * + * @deprecated + */ +export const CompositeItem = proxyComposite( + Object.assign( Current.Item, { + displayName: '__unstableCompositeItem', + } ), + { + focusable: 'accessibleWhenDisabled', + } +); +/** + * _Note: please use the `Composite` component instead._ + * + * @deprecated + */ export function useCompositeState( legacyStateOptions: LegacyStateOptions = {} ): CompositeState { + deprecated( `wp.components.__unstableUseCompositeState`, { + since: '6.7', + alternative: LEGACY_TO_NEW_DISPLAY_NAME.__unstableUseCompositeState, + } ); + const { baseId, currentId: defaultActiveId, diff --git a/packages/components/src/composite/legacy/test/index.tsx b/packages/components/src/composite/legacy/test/index.tsx index 07398e54b27ca3..c034d31442ca8d 100644 --- a/packages/components/src/composite/legacy/test/index.tsx +++ b/packages/components/src/composite/legacy/test/index.tsx @@ -1,7 +1,12 @@ /** * External dependencies */ -import { queryByAttribute, render, screen } from '@testing-library/react'; +import { + queryByAttribute, + render, + screen, + renderHook, +} from '@testing-library/react'; import { press, waitFor } from '@ariakit/test'; /** @@ -156,6 +161,57 @@ function getShiftTestItems() { }; } +// Checking for deprecation warnings before other tests because the `deprecated` +// utility only fires a console.warn the first time a component is rendered. +describe( 'Shows a deprecation warning', () => { + it( 'useCompositeState', () => { + renderHook( () => useCompositeState() ); + expect( console ).toHaveWarnedWith( + 'wp.components.__unstableUseCompositeState is deprecated since version 6.7. Please use Composite instead.' + ); + } ); + it( 'Composite', () => { + const Test = () => { + const props = useCompositeState(); + return ; + }; + render( ); + expect( console ).toHaveWarnedWith( + 'wp.components.__unstableComposite is deprecated since version 6.7. Please use Composite instead.' + ); + } ); + it( 'CompositeItem', () => { + const Test = () => { + const props = useCompositeState(); + return ( + + + + ); + }; + render( ); + expect( console ).toHaveWarnedWith( + 'wp.components.__unstableCompositeItem is deprecated since version 6.7. Please use Composite.Item instead.' + ); + } ); + it( 'CompositeGroup', () => { + const Test = () => { + const props = useCompositeState(); + return ( + + + + + + ); + }; + render( ); + expect( console ).toHaveWarnedWith( + 'wp.components.__unstableCompositeGroup is deprecated since version 6.7. Please use Composite.Group or Composite.Row instead.' + ); + } ); +} ); + describe.each( [ [ 'With "spread" state',