Skip to content

TypeScript: Migrate viewport package#71118

Merged
manzoorwanijk merged 14 commits into
WordPress:trunkfrom
yashjawale:refactor/ts-migration-viewport-package
Apr 9, 2026
Merged

TypeScript: Migrate viewport package#71118
manzoorwanijk merged 14 commits into
WordPress:trunkfrom
yashjawale:refactor/ts-migration-viewport-package

Conversation

@yashjawale
Copy link
Copy Markdown
Contributor

@yashjawale yashjawale commented Aug 7, 2025

What?

Part of #67691

This PR migrates viewport package to use TypeScript

Why?

Migrating to TypeScript provides improved type-hinting in the editor & helps identify bugs early on

How?

The PR ports the existing component code to use TypeScript syntax & creates types accordingly as needed

Testing Instructions

The existing unit tests for the component should suffice

@yashjawale yashjawale marked this pull request as ready for review August 8, 2025 08:21
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Aug 8, 2025

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: yashjawale <yashjawale@git.wordpress.org>
Co-authored-by: manzoorwanijk <manzoorwanijk@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@yashjawale yashjawale changed the title [WIP] TypeScript: Migrate viewport package TypeScript: Migrate viewport package Aug 8, 2025
@im3dabasia im3dabasia added [Type] Code Quality Issues or PRs that relate to code quality [Package] Viewport /packages/viewport labels Aug 8, 2025
Copy link
Copy Markdown
Member

@manzoorwanijk manzoorwanijk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to get rid of some as any assertions.

Comment on lines 44 to +61
// we are respecting that as from the static query of the HOC we generate
// a hook that calls other hooks always in the same order (because the query never changes).
// eslint-disable-next-line react-hooks/rules-of-hooks
return [ key, useViewportMatch( breakpointName, operator ) ];
return [
key,
// eslint-disable-next-line react-hooks/rules-of-hooks
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we please move that comment above inline to the eslint rule?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry missed that, fixed ✅

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR migrates the viewport package from JavaScript to TypeScript as part of a broader TypeScript migration effort. The migration includes creating comprehensive type definitions for viewport queries, breakpoints, and store state management while preserving all existing functionality.

Key changes include:

  • Added comprehensive TypeScript types for viewport queries, breakpoints, and store state
  • Converted all JavaScript files to TypeScript with proper type annotations
  • Added TypeScript configuration and project references

Reviewed Changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/viewport/tsconfig.json New TypeScript configuration for the viewport package
packages/viewport/src/types.ts Comprehensive type definitions for viewport functionality
packages/viewport/src/with-viewport-match.ts Migrated HOC with proper TypeScript types and generics
packages/viewport/src/store/selectors.ts Converted selectors with typed parameters and return values
packages/viewport/src/store/reducer.ts Migrated reducer with proper action and state typing
packages/viewport/src/store/actions.ts Converted actions with typed parameters and return values
packages/viewport/src/listener.ts Migrated event listener with proper type annotations
packages/viewport/src/index.ts Updated main entry point with typed constants
packages/viewport/src/if-viewport-matches.ts Converted HOC with TypeScript generics and type casting
packages/edit-site/tsconfig.json Added viewport package reference
packages/block-library/tsconfig.json Added viewport package reference
packages/viewport/README.md Updated documentation to reflect TypeScript types
docs/reference-guides/data/data-core-viewport.md Updated documentation paths and type references

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

const ifViewportMatches = ( query: ViewportQuery ) =>
createHigherOrderComponent(
compose( [
( compose as any )( [
Copy link

Copilot AI Sep 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using as any type assertion defeats the purpose of TypeScript's type safety. Consider importing compose with proper types from @wordpress/compose or defining a more specific type for this use case.

Suggested change
( compose as any )( [
compose( [

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can live with it for now.

Copy link
Copy Markdown
Member

@manzoorwanijk manzoorwanijk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me but I would prefer other code owners to have a look as well

Comment thread packages/viewport/src/listener.ts Outdated
const queries = Object.entries( breakpoints ).flatMap(
( [ name, width ] ) => {
return operatorEntries.map( ( [ operator, condition ] ) => {
const queries: Array< [ string, MediaQueryList ] > = Object.entries(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't hurt but you don't need the type annotation here. TS can infer it easily.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated ✅

const ifViewportMatches = ( query: ViewportQuery ) =>
createHigherOrderComponent(
compose( [
( compose as any )( [
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose it's not easy to get rid of this assertion.

Comment thread packages/viewport/tsconfig.json Outdated
{ "path": "../data" },
{ "path": "../element" }
],
"include": [ "src/**/*" ]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need wildcard here.

Suggested change
"include": [ "src/**/*" ]
"include": [ "src" ]

const ifViewportMatches = ( query: ViewportQuery ) =>
createHigherOrderComponent(
compose( [
( compose as any )( [
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can live with it for now.

@github-actions github-actions Bot added [Package] Block library /packages/block-library [Package] Edit Site /packages/edit-site labels Apr 9, 2026
@manzoorwanijk manzoorwanijk requested a review from Copilot April 9, 2026 08:50
Copy link
Copy Markdown
Member

@manzoorwanijk manzoorwanijk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is close. Let us clean this up a bit.

Comment thread packages/viewport/tsconfig.json Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 17 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread docs/reference-guides/data/data-core-viewport.md
Comment thread docs/reference-guides/data/data-core-viewport.md
*
* @return Higher-order component.
*/
const withViewportMatch = ( queries: ViewportQueries ) => {
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current generic typing makes the returned HOC accept the same props as the wrapped component (T), even though the HOC injects additional boolean props derived from queries. To model this correctly for consumers, consider typing withViewportMatch so the wrapped component expects OwnProps & InjectedProps, while the returned component expects only OwnProps (i.e., omit/strip the injected keys from the public props type).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense but is not a big deal for now, but will be good to update it though.

Comment on lines +69 to +73
return createHigherOrderComponent(
< T extends Record< string, unknown > >(
WrappedComponent: ComponentType< T >
) => {
const WrappedWithViewport = ( props: T ) => {
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current generic typing makes the returned HOC accept the same props as the wrapped component (T), even though the HOC injects additional boolean props derived from queries. To model this correctly for consumers, consider typing withViewportMatch so the wrapped component expects OwnProps & InjectedProps, while the returned component expects only OwnProps (i.e., omit/strip the injected keys from the public props type).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same about this - a nice to have.

Comment thread packages/viewport/src/types.ts Outdated
Co-authored-by: Manzoor Wani <manzoorwani.jk@gmail.com>
yashjawale and others added 2 commits April 9, 2026 15:00
Copy link
Copy Markdown
Member

@manzoorwanijk manzoorwanijk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One last bit - we need to add types field to package.json and also to exports['.'] field in it.

Copy link
Copy Markdown
Member

@manzoorwanijk manzoorwanijk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good now. Thanks

@manzoorwanijk manzoorwanijk merged commit d77101a into WordPress:trunk Apr 9, 2026
40 checks passed
@github-actions github-actions Bot added this to the Gutenberg 23.0 milestone Apr 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Block library /packages/block-library [Package] Edit Site /packages/edit-site [Package] Viewport /packages/viewport [Type] Code Quality Issues or PRs that relate to code quality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants