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

UnitControl component: Refactor utils to TypeScript #35138

Merged
merged 7 commits into from
Sep 29, 2021

Conversation

andrewserong
Copy link
Contributor

@andrewserong andrewserong commented Sep 27, 2021

Description

Following on from discussion in #34768 (review), this PR refactors the UnitControl component's utils file and set of functions to TypeScript and adds a couple of types. To avoid creating a large PR that might make reviewing difficult, I thought we could look at refactoring this component one file at a time, with this one just focusing on the utils for the moment.

It looks like I could safely remove the lodash dependency from the file, too. I've also updated the documentation for some of the attributes where there were some slight inaccuracies.

Something I noticed while working on the file is that often the list of units could have a value set to false (there were a few places where this is expected). I believe this is to support either useCustomUnits returning the false value to switch off custom units, or possibly a theme.json file explicitly setting units to false. I think I've managed to get this fairly consistent, but I'm very open to feedback if folks think there's a better way to deal with it.

How has this been tested?

Ensure tests pass

npm run test-unit -- --testPathPattern packages/components/src/unit-control/test/

Ensure the UnitControl component works correctly

Via Storybook, run npm run storybook:dev and then visit http://localhost:50240/?path=/story/components-unitcontrol--default

Or, in the editor, go to edit a block that uses padding and adjust the controls (the Cover block is a good one to try)

Ensure that a theme's theme.json units settings overrides the available units

With TT1-Blocks applied, you should see that the list of available units does not include %, but you can also manually edit the theme.json file's settings.spacing.units attribute to a reduced list of unit strings (e.g. [ 'px', 'em', 'rem' ] to ensure it works as expected.

Screenshots

Types of changes

Code quality, non-breaking change.

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • I've tested my changes with keyboard and screen readers.
  • My code has proper inline documentation.
  • I've included developer documentation if appropriate.
  • I've updated all React Native files affected by any refactorings/renamings in this PR (please manually search all *.native.js files for terms that need renaming or removal).

@andrewserong andrewserong added [Feature] UI Components Impacts or related to the UI component system [Type] Code Quality Issues or PRs that relate to code quality labels Sep 27, 2021
@andrewserong andrewserong requested a review from ciampo September 27, 2021 06:54
@andrewserong andrewserong self-assigned this Sep 27, 2021
@andrewserong
Copy link
Contributor Author

CC @ciampo, I've started looking into refactoring the UnitControl component to TypeScript — I thought I'd try doing it in smaller PRs one file at a time to hopefully make it easier to review, but also since I don't have much TypeScript experience. Hopefully this will give me the chance to learn from any feedback before venturing too much deeper! 😄

@github-actions
Copy link

github-actions bot commented Sep 27, 2021

Size Change: -2.22 kB (0%)

Total Size: 1.06 MB

Filename Size Change
build/api-fetch/index.min.js 2.21 kB +20 B (+1%)
build/block-editor/index.min.js 134 kB -4.18 kB (-3%)
build/block-library/blocks/gallery/editor-rtl.css 977 B -6 B (-1%)
build/block-library/blocks/gallery/editor.css 982 B -6 B (-1%)
build/block-library/editor-rtl.css 9.76 kB -2 B (0%)
build/block-library/editor.css 9.75 kB -2 B (0%)
build/block-library/index.min.js 146 kB -1.27 kB (-1%)
build/block-library/reset-rtl.css 536 B +9 B (+2%)
build/block-library/reset.css 536 B +9 B (+2%)
build/blocks/index.min.js 45.7 kB -1.28 kB (-3%)
build/components/index.min.js 214 kB +3.85 kB (+2%)
build/components/style-rtl.css 15.9 kB -36 B (0%)
build/components/style.css 15.9 kB -36 B (0%)
build/customize-widgets/index.min.js 11.1 kB -13 B (0%)
build/edit-navigation/index.min.js 15.3 kB -153 B (-1%)
build/edit-navigation/style-rtl.css 3.71 kB +12 B (0%)
build/edit-navigation/style.css 3.7 kB +12 B (0%)
build/edit-post/index.min.js 29 kB +22 B (0%)
build/edit-post/style-rtl.css 7.19 kB +12 B (0%)
build/edit-post/style.css 7.18 kB +11 B (0%)
build/edit-site/index.min.js 28.4 kB +649 B (+2%)
build/edit-site/style-rtl.css 5.36 kB +147 B (+3%)
build/edit-site/style.css 5.36 kB +149 B (+3%)
build/edit-widgets/index.min.js 15.7 kB -316 B (-2%)
build/edit-widgets/style-rtl.css 4.1 kB +10 B (0%)
build/edit-widgets/style.css 4.1 kB +9 B (0%)
build/editor/index.min.js 37.4 kB +10 B (0%)
build/editor/style.css 3.75 kB +1 B (0%)
build/format-library/index.min.js 5.68 kB +347 B (+7%) 🔍
build/format-library/style-rtl.css 571 B -97 B (-15%) 👏
build/format-library/style.css 571 B -99 B (-15%) 👏
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 931 B
build/admin-manifest/index.min.js 1.09 kB
build/annotations/index.min.js 2.7 kB
build/autop/index.min.js 2.08 kB
build/blob/index.min.js 459 B
build/block-directory/index.min.js 6.19 kB
build/block-directory/style-rtl.css 1.01 kB
build/block-directory/style.css 1.01 kB
build/block-editor/default-editor-styles-rtl.css 378 B
build/block-editor/default-editor-styles.css 378 B
build/block-editor/style-rtl.css 13.9 kB
build/block-editor/style.css 13.9 kB
build/block-library/blocks/archives/editor-rtl.css 61 B
build/block-library/blocks/archives/editor.css 60 B
build/block-library/blocks/archives/style-rtl.css 65 B
build/block-library/blocks/archives/style.css 65 B
build/block-library/blocks/audio/editor-rtl.css 58 B
build/block-library/blocks/audio/editor.css 58 B
build/block-library/blocks/audio/style-rtl.css 111 B
build/block-library/blocks/audio/style.css 111 B
build/block-library/blocks/audio/theme-rtl.css 125 B
build/block-library/blocks/audio/theme.css 125 B
build/block-library/blocks/block/editor-rtl.css 161 B
build/block-library/blocks/block/editor.css 161 B
build/block-library/blocks/button/editor-rtl.css 474 B
build/block-library/blocks/button/editor.css 474 B
build/block-library/blocks/button/style-rtl.css 600 B
build/block-library/blocks/button/style.css 600 B
build/block-library/blocks/buttons/editor-rtl.css 315 B
build/block-library/blocks/buttons/editor.css 315 B
build/block-library/blocks/buttons/style-rtl.css 370 B
build/block-library/blocks/buttons/style.css 370 B
build/block-library/blocks/calendar/style-rtl.css 207 B
build/block-library/blocks/calendar/style.css 207 B
build/block-library/blocks/categories/editor-rtl.css 84 B
build/block-library/blocks/categories/editor.css 83 B
build/block-library/blocks/categories/style-rtl.css 79 B
build/block-library/blocks/categories/style.css 79 B
build/block-library/blocks/code/style-rtl.css 90 B
build/block-library/blocks/code/style.css 90 B
build/block-library/blocks/code/theme-rtl.css 131 B
build/block-library/blocks/code/theme.css 131 B
build/block-library/blocks/columns/editor-rtl.css 206 B
build/block-library/blocks/columns/editor.css 205 B
build/block-library/blocks/columns/style-rtl.css 497 B
build/block-library/blocks/columns/style.css 496 B
build/block-library/blocks/cover/editor-rtl.css 666 B
build/block-library/blocks/cover/editor.css 670 B
build/block-library/blocks/cover/style-rtl.css 1.23 kB
build/block-library/blocks/cover/style.css 1.23 kB
build/block-library/blocks/embed/editor-rtl.css 488 B
build/block-library/blocks/embed/editor.css 488 B
build/block-library/blocks/embed/style-rtl.css 417 B
build/block-library/blocks/embed/style.css 417 B
build/block-library/blocks/embed/theme-rtl.css 124 B
build/block-library/blocks/embed/theme.css 124 B
build/block-library/blocks/file/editor-rtl.css 300 B
build/block-library/blocks/file/editor.css 300 B
build/block-library/blocks/file/style-rtl.css 255 B
build/block-library/blocks/file/style.css 255 B
build/block-library/blocks/file/view.min.js 322 B
build/block-library/blocks/freeform/editor-rtl.css 2.44 kB
build/block-library/blocks/freeform/editor.css 2.44 kB
build/block-library/blocks/gallery/style-rtl.css 1.6 kB
build/block-library/blocks/gallery/style.css 1.59 kB
build/block-library/blocks/gallery/theme-rtl.css 122 B
build/block-library/blocks/gallery/theme.css 122 B
build/block-library/blocks/group/editor-rtl.css 159 B
build/block-library/blocks/group/editor.css 159 B
build/block-library/blocks/group/style-rtl.css 57 B
build/block-library/blocks/group/style.css 57 B
build/block-library/blocks/group/theme-rtl.css 78 B
build/block-library/blocks/group/theme.css 78 B
build/block-library/blocks/heading/style-rtl.css 114 B
build/block-library/blocks/heading/style.css 114 B
build/block-library/blocks/home-link/style-rtl.css 247 B
build/block-library/blocks/home-link/style.css 247 B
build/block-library/blocks/html/editor-rtl.css 332 B
build/block-library/blocks/html/editor.css 333 B
build/block-library/blocks/image/editor-rtl.css 728 B
build/block-library/blocks/image/editor.css 728 B
build/block-library/blocks/image/style-rtl.css 482 B
build/block-library/blocks/image/style.css 487 B
build/block-library/blocks/image/theme-rtl.css 124 B
build/block-library/blocks/image/theme.css 124 B
build/block-library/blocks/latest-comments/style-rtl.css 284 B
build/block-library/blocks/latest-comments/style.css 284 B
build/block-library/blocks/latest-posts/editor-rtl.css 137 B
build/block-library/blocks/latest-posts/editor.css 137 B
build/block-library/blocks/latest-posts/style-rtl.css 528 B
build/block-library/blocks/latest-posts/style.css 527 B
build/block-library/blocks/list/style-rtl.css 94 B
build/block-library/blocks/list/style.css 94 B
build/block-library/blocks/media-text/editor-rtl.css 266 B
build/block-library/blocks/media-text/editor.css 263 B
build/block-library/blocks/media-text/style-rtl.css 488 B
build/block-library/blocks/media-text/style.css 485 B
build/block-library/blocks/more/editor-rtl.css 431 B
build/block-library/blocks/more/editor.css 431 B
build/block-library/blocks/navigation-link/editor-rtl.css 568 B
build/block-library/blocks/navigation-link/editor.css 570 B
build/block-library/blocks/navigation-link/style-rtl.css 94 B
build/block-library/blocks/navigation-link/style.css 94 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 300 B
build/block-library/blocks/navigation-submenu/editor.css 299 B
build/block-library/blocks/navigation-submenu/style-rtl.css 195 B
build/block-library/blocks/navigation-submenu/style.css 195 B
build/block-library/blocks/navigation-submenu/view.min.js 343 B
build/block-library/blocks/navigation/editor-rtl.css 1.72 kB
build/block-library/blocks/navigation/editor.css 1.72 kB
build/block-library/blocks/navigation/style-rtl.css 1.48 kB
build/block-library/blocks/navigation/style.css 1.47 kB
build/block-library/blocks/navigation/view.min.js 2.74 kB
build/block-library/blocks/nextpage/editor-rtl.css 395 B
build/block-library/blocks/nextpage/editor.css 395 B
build/block-library/blocks/page-list/editor-rtl.css 377 B
build/block-library/blocks/page-list/editor.css 377 B
build/block-library/blocks/page-list/style-rtl.css 198 B
build/block-library/blocks/page-list/style.css 198 B
build/block-library/blocks/paragraph/editor-rtl.css 157 B
build/block-library/blocks/paragraph/editor.css 157 B
build/block-library/blocks/paragraph/style-rtl.css 273 B
build/block-library/blocks/paragraph/style.css 273 B
build/block-library/blocks/post-author/editor-rtl.css 210 B
build/block-library/blocks/post-author/editor.css 210 B
build/block-library/blocks/post-author/style-rtl.css 182 B
build/block-library/blocks/post-author/style.css 181 B
build/block-library/blocks/post-comments-form/style-rtl.css 140 B
build/block-library/blocks/post-comments-form/style.css 140 B
build/block-library/blocks/post-comments/style-rtl.css 360 B
build/block-library/blocks/post-comments/style.css 359 B
build/block-library/blocks/post-content/editor-rtl.css 138 B
build/block-library/blocks/post-content/editor.css 138 B
build/block-library/blocks/post-excerpt/editor-rtl.css 73 B
build/block-library/blocks/post-excerpt/editor.css 73 B
build/block-library/blocks/post-excerpt/style-rtl.css 69 B
build/block-library/blocks/post-excerpt/style.css 69 B
build/block-library/blocks/post-featured-image/editor-rtl.css 398 B
build/block-library/blocks/post-featured-image/editor.css 398 B
build/block-library/blocks/post-featured-image/style-rtl.css 143 B
build/block-library/blocks/post-featured-image/style.css 143 B
build/block-library/blocks/post-template/editor-rtl.css 99 B
build/block-library/blocks/post-template/editor.css 98 B
build/block-library/blocks/post-template/style-rtl.css 378 B
build/block-library/blocks/post-template/style.css 379 B
build/block-library/blocks/post-terms/style-rtl.css 73 B
build/block-library/blocks/post-terms/style.css 73 B
build/block-library/blocks/post-title/style-rtl.css 60 B
build/block-library/blocks/post-title/style.css 60 B
build/block-library/blocks/preformatted/style-rtl.css 103 B
build/block-library/blocks/preformatted/style.css 103 B
build/block-library/blocks/pullquote/editor-rtl.css 198 B
build/block-library/blocks/pullquote/editor.css 198 B
build/block-library/blocks/pullquote/style-rtl.css 378 B
build/block-library/blocks/pullquote/style.css 378 B
build/block-library/blocks/pullquote/theme-rtl.css 167 B
build/block-library/blocks/pullquote/theme.css 167 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B
build/block-library/blocks/query-pagination/editor-rtl.css 262 B
build/block-library/blocks/query-pagination/editor.css 255 B
build/block-library/blocks/query-pagination/style-rtl.css 234 B
build/block-library/blocks/query-pagination/style.css 231 B
build/block-library/blocks/query-title/editor-rtl.css 85 B
build/block-library/blocks/query-title/editor.css 85 B
build/block-library/blocks/query/editor-rtl.css 131 B
build/block-library/blocks/query/editor.css 132 B
build/block-library/blocks/quote/style-rtl.css 187 B
build/block-library/blocks/quote/style.css 187 B
build/block-library/blocks/quote/theme-rtl.css 220 B
build/block-library/blocks/quote/theme.css 222 B
build/block-library/blocks/rss/editor-rtl.css 202 B
build/block-library/blocks/rss/editor.css 204 B
build/block-library/blocks/rss/style-rtl.css 289 B
build/block-library/blocks/rss/style.css 288 B
build/block-library/blocks/search/editor-rtl.css 165 B
build/block-library/blocks/search/editor.css 165 B
build/block-library/blocks/search/style-rtl.css 374 B
build/block-library/blocks/search/style.css 375 B
build/block-library/blocks/search/theme-rtl.css 64 B
build/block-library/blocks/search/theme.css 64 B
build/block-library/blocks/separator/editor-rtl.css 99 B
build/block-library/blocks/separator/editor.css 99 B
build/block-library/blocks/separator/style-rtl.css 250 B
build/block-library/blocks/separator/style.css 250 B
build/block-library/blocks/separator/theme-rtl.css 172 B
build/block-library/blocks/separator/theme.css 172 B
build/block-library/blocks/shortcode/editor-rtl.css 474 B
build/block-library/blocks/shortcode/editor.css 474 B
build/block-library/blocks/site-logo/editor-rtl.css 462 B
build/block-library/blocks/site-logo/editor.css 464 B
build/block-library/blocks/site-logo/style-rtl.css 153 B
build/block-library/blocks/site-logo/style.css 153 B
build/block-library/blocks/site-tagline/editor-rtl.css 86 B
build/block-library/blocks/site-tagline/editor.css 86 B
build/block-library/blocks/site-title/editor-rtl.css 84 B
build/block-library/blocks/site-title/editor.css 84 B
build/block-library/blocks/social-link/editor-rtl.css 165 B
build/block-library/blocks/social-link/editor.css 165 B
build/block-library/blocks/social-links/editor-rtl.css 812 B
build/block-library/blocks/social-links/editor.css 811 B
build/block-library/blocks/social-links/style-rtl.css 1.3 kB
build/block-library/blocks/social-links/style.css 1.3 kB
build/block-library/blocks/spacer/editor-rtl.css 307 B
build/block-library/blocks/spacer/editor.css 307 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 B
build/block-library/blocks/table/editor-rtl.css 471 B
build/block-library/blocks/table/editor.css 472 B
build/block-library/blocks/table/style-rtl.css 481 B
build/block-library/blocks/table/style.css 481 B
build/block-library/blocks/table/theme-rtl.css 188 B
build/block-library/blocks/table/theme.css 188 B
build/block-library/blocks/tag-cloud/style-rtl.css 146 B
build/block-library/blocks/tag-cloud/style.css 146 B
build/block-library/blocks/template-part/editor-rtl.css 636 B
build/block-library/blocks/template-part/editor.css 635 B
build/block-library/blocks/template-part/theme-rtl.css 101 B
build/block-library/blocks/template-part/theme.css 101 B
build/block-library/blocks/term-description/editor-rtl.css 90 B
build/block-library/blocks/term-description/editor.css 90 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B
build/block-library/blocks/text-columns/editor.css 95 B
build/block-library/blocks/text-columns/style-rtl.css 166 B
build/block-library/blocks/text-columns/style.css 166 B
build/block-library/blocks/verse/style-rtl.css 87 B
build/block-library/blocks/verse/style.css 87 B
build/block-library/blocks/video/editor-rtl.css 571 B
build/block-library/blocks/video/editor.css 572 B
build/block-library/blocks/video/style-rtl.css 173 B
build/block-library/blocks/video/style.css 173 B
build/block-library/blocks/video/theme-rtl.css 124 B
build/block-library/blocks/video/theme.css 124 B
build/block-library/common-rtl.css 853 B
build/block-library/common.css 849 B
build/block-library/style-rtl.css 10.3 kB
build/block-library/style.css 10.3 kB
build/block-library/theme-rtl.css 665 B
build/block-library/theme.css 669 B
build/block-serialization-default-parser/index.min.js 1.09 kB
build/block-serialization-spec-parser/index.min.js 2.79 kB
build/compose/index.min.js 10.3 kB
build/core-data/index.min.js 12.3 kB
build/customize-widgets/style-rtl.css 1.5 kB
build/customize-widgets/style.css 1.49 kB
build/data-controls/index.min.js 614 B
build/data/index.min.js 7.1 kB
build/date/index.min.js 31.5 kB
build/deprecated/index.min.js 428 B
build/dom-ready/index.min.js 304 B
build/dom/index.min.js 4.45 kB
build/edit-post/classic-rtl.css 492 B
build/edit-post/classic.css 494 B
build/editor/style-rtl.css 3.76 kB
build/element/index.min.js 3.17 kB
build/escape-html/index.min.js 517 B
build/hooks/index.min.js 1.55 kB
build/html-entities/index.min.js 424 B
build/i18n/index.min.js 3.6 kB
build/is-shallow-equal/index.min.js 501 B
build/keyboard-shortcuts/index.min.js 1.72 kB
build/keycodes/index.min.js 1.3 kB
build/list-reusable-blocks/index.min.js 1.85 kB
build/list-reusable-blocks/style-rtl.css 838 B
build/list-reusable-blocks/style.css 838 B
build/media-utils/index.min.js 2.92 kB
build/notices/index.min.js 845 B
build/nux/index.min.js 2.03 kB
build/nux/style-rtl.css 747 B
build/nux/style.css 743 B
build/plugins/index.min.js 1.83 kB
build/primitives/index.min.js 921 B
build/priority-queue/index.min.js 582 B
build/react-i18n/index.min.js 671 B
build/redux-routine/index.min.js 2.63 kB
build/reusable-blocks/index.min.js 2.28 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/rich-text/index.min.js 10.6 kB
build/server-side-render/index.min.js 1.5 kB
build/shortcode/index.min.js 1.48 kB
build/token-list/index.min.js 562 B
build/url/index.min.js 1.74 kB
build/viewport/index.min.js 1.02 kB
build/warning/index.min.js 248 B
build/widgets/index.min.js 7.11 kB
build/widgets/style-rtl.css 1.16 kB
build/widgets/style.css 1.16 kB
build/wordcount/index.min.js 1.04 kB

compressed-size-action

@ciampo ciampo requested a review from diegohaz September 27, 2021 07:32
Copy link
Contributor

@ciampo ciampo left a comment

Choose a reason for hiding this comment

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

Thank you for your work on this, @andrewserong, it is much needed!

I've left a few comments inline, but overall it's looking good!

packages/components/src/unit-control/types.ts Outdated Show resolved Hide resolved
packages/components/src/unit-control/utils.ts Show resolved Hide resolved
packages/components/src/unit-control/types.ts Outdated Show resolved Hide resolved
legacyUnit,
units = ALL_CSS_UNITS
) {
currentValue: number | string,
Copy link
Contributor

Choose a reason for hiding this comment

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

I would probably add a new type in types.ts:

type Value = number | string;

And then replace it everywhere we currently intend to represent such a value (including in the WPUnitControlUnit and UseCustomUnitsProps types).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I like that idea, it neatens things a fair bit and ensures consistency (previously I see I'd inconsistently used number | string and string | number). I've updated, but please let me know if I've missed anything.

Comment on lines 321 to 322
units: Array< WPUnitControlUnit > | false = ALL_CSS_UNITS
): Array< WPUnitControlUnit > | false {
Copy link
Contributor

Choose a reason for hiding this comment

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

Using false as a valid value for units and also as a potential return value of the function feels a bit weird (I know the implementation was there before this PR, and in fact, it's thanks to using TypeScript that we can spot situations like this one).

I can see that the same pattern happens in the hasUnits function — this is probably something that we should tackle separately in a follow-up PR. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought the same, it does feel a bit weird in these functions. I think we'll still need to support theme.json providing false as a valid value to switch off units support, but there's likely a neater way of handling it than having these functions use it as an expected type.

this is probably something that we should tackle separately in a follow-up PR.

Agreed, it'll probably be easier to do as a follow-up as the implementation might need to change slightly.

packages/components/src/unit-control/utils.ts Outdated Show resolved Hide resolved

if ( isNaN( parsedValue ) || parsedValue === '' ) {
if ( ! Number.isFinite( parsedValue ) || parsedValue === '' ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We should consider this change carefully, since it introduces a runtime change — isNaN doesn't always return the same results as ! Number.isFinite

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for pointing this out, I meant to leave a specific comment for it. With the switch to TypeScript, using isNaN here generated an error:

image

This seems to be that in TS, isNaN expects to be called with a variable of type number, but our parsedValue is either a number or a string. At this point in getValidParsedUnit the parsedValue variable must be either a number or an empty string (the results of calling parseUnit). So, I think Number.isFinite is a more appropriate check than isNaN anyway, at least from my mental model of what this function should be doing:

  • Check that the number is not NaN
  • Check that the number is a valid value that we can use (e.g. not Infinity or -Infinity) and not an arbitrary string

If it doesn't meet the above criteria then we fall back to the fallbackValue. One difference in using Number.isFinite is that the value won't be coerced to a number before checking to see if it's finite. I think this is okay, because the value has already been coerced in parseUnit so at this point it should be a real (finite) value in order for us to consider it valid.

Please let me know if you think that's not right, though! Happy to change the logic here, I think it's the main place where I had to introduce a runtime change, but 🤞 it isn't an unexpected one in usage.

It could be that we might want to tighten up the Value type a bit further, too, given that in some places it'll only be number or the string literal '' — I was a bit cautious about doing that, as we'd then have two different Value types floating around in the file, which could get confusing? But it also might make it a bit clearer 🤔

Copy link
Contributor

@ciampo ciampo Sep 28, 2021

Choose a reason for hiding this comment

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

Please let me know if you think that's not right, though! Happy to change the logic here, I think it's the main place where I had to introduce a runtime change, but 🤞 it isn't an unexpected one in usage.

Thank you for the explanation! With this context (and the extra reassurance given by the passing unit tests), I think we can leave your new implementation untouched.

I would maybe only add a comment with a short version of the explanation you just gave in your previous message.

It could be that we might want to tighten up the Value type a bit further, too, given that in some places it'll only be number or the string literal '' — I was a bit cautious about doing that, as we'd then have two different Value types floating around in the file, which could get confusing? But it also might make it a bit clearer 🤔

I had the same thought and came to the same conclusion

packages/components/src/unit-control/types.ts Show resolved Hide resolved
@ciampo ciampo added the [Package] Components /packages/components label Sep 27, 2021
@andrewserong
Copy link
Contributor Author

Thanks for the detailed feedback @ciampo, much appreciated! I think I've either answered or implemented all the feedback and questions, but do let me know if there are any other changes you'd like to see 🙂

Copy link
Contributor

@ciampo ciampo left a comment

Choose a reason for hiding this comment

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

Most feedback has been addressed, I just left a couple of minor comments. This is close to getting merged!

packages/components/src/unit-control/types.ts Show resolved Hide resolved
*/
export function hasUnits( units ) {
return ! isEmpty( units ) && units !== false;
export function hasUnits( units: Array< WPUnitControlUnit > | false ): boolean {
Copy link
Contributor

Choose a reason for hiding this comment

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

We could also extract Array< WPUnitControlUnit > | false type to types.ts, to make this pattern more clear. Maybe something like

type WPUnitControlUnitList = Array< WPUnitControlUnit > | false;

This would also help us when potentially working on #35138 (comment)


if ( isNaN( parsedValue ) || parsedValue === '' ) {
if ( ! Number.isFinite( parsedValue ) || parsedValue === '' ) {
Copy link
Contributor

@ciampo ciampo Sep 28, 2021

Choose a reason for hiding this comment

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

Please let me know if you think that's not right, though! Happy to change the logic here, I think it's the main place where I had to introduce a runtime change, but 🤞 it isn't an unexpected one in usage.

Thank you for the explanation! With this context (and the extra reassurance given by the passing unit tests), I think we can leave your new implementation untouched.

I would maybe only add a comment with a short version of the explanation you just gave in your previous message.

It could be that we might want to tighten up the Value type a bit further, too, given that in some places it'll only be number or the string literal '' — I was a bit cautious about doing that, as we'd then have two different Value types floating around in the file, which could get confusing? But it also might make it a bit clearer 🤔

I had the same thought and came to the same conclusion

Copy link
Contributor

@ciampo ciampo left a comment

Choose a reason for hiding this comment

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

Actually, to speed this up, I can already approve this PR, since the two actionable pieces of feedback that I left are quite trivial and wouldn't change the runtime code. Feel free to address them and merge! 🚀


I can see two follow-ups from here:

I'm happy to help with both items, in case you have the time to work on them!

@andrewserong
Copy link
Contributor Author

Thanks @ciampo! I've added in the contextual comment for the isFinite check, and the additional type.

I did add in another small runtime change to filterUnitsWithSettings. When adding in the new WPUnitControlUnitList type, I noticed that this function expected to be called with an array. In all current usage of it, it is called with an array, but given that the other similar functions are written to also factor in that they could be called with false, I've added in another Array.isArray check, with a fallback to an empty array, to harden the function a little. I've also included an additional unit test.

I've tested the change in a couple of different themes (with and without theme.json files with custom units settings) and in the iOS simulator to make sure that the native Button block border radius control still uses its filtered units correctly. So, once the performance tests pass, I'll merge this one in.

Happy to continue work in follow-ups (I'll look at fully typing the rest of the UnitControl component later on this week), but let me know if there are any issues and I can do other follow-ups too.

@andrewserong andrewserong merged commit 608a105 into trunk Sep 29, 2021
@andrewserong andrewserong deleted the update/unit-control-component-to-typescript branch September 29, 2021 02:51
@github-actions github-actions bot added this to the Gutenberg 11.7 milestone Sep 29, 2021
@ciampo
Copy link
Contributor

ciampo commented Sep 29, 2021

Thank you!

In the context of refactoring to the WPUnitControlUnitList type, I noticed that the units argument in the getParsedValue, filterUnitsWithSettings and useCustomUnits functions didn't previously accept false — it's probably a good idea to keep it the way it used to be, so that we don't widen the types more than they need to be?

We could make these changes in the follow-up issue/PR that investigates how to improve the WPUnitControlUnitList type

@andrewserong
Copy link
Contributor Author

Thanks again @ciampo!

We could make these changes in the follow-up issue/PR that investigates how to improve the WPUnitControlUnitList type

Yes, let's look at it in that context in the follow-up. Hopefully it should be a little clearer / cleaner when we're just looking at that one thing in isolation.

I thought I'd start on typing the JSX -> TSX first later on this week, and then come back to the WPUnitControlUnitList type, but let me know if you'd prefer we do it the other way around 🙂

@ciampo
Copy link
Contributor

ciampo commented Sep 29, 2021

I thought I'd start on typing the JSX -> TSX first later on this week, and then come back to the WPUnitControlUnitList type, but let me know if you'd prefer we do it the other way around 🙂

Sounds good to me! Feel free to open a draft issue and ping me there if you want early feedback too :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] UI Components Impacts or related to the UI component system [Package] Components /packages/components [Type] Code Quality Issues or PRs that relate to code quality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants