Skip to content

Commit

Permalink
ToolsPanel component: refactor to typescript (#34028)
Browse files Browse the repository at this point in the history
* Refactors the ToolsPanel and its subcomponents to TypeScript

Co-authored-by: Glen Davies <glen.davies@a8c.com>
Co-authored-by: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
  • Loading branch information
3 people authored Sep 23, 2021
1 parent 4582d02 commit 1620d51
Show file tree
Hide file tree
Showing 26 changed files with 339 additions and 113 deletions.
29 changes: 16 additions & 13 deletions packages/components/src/dropdown-menu/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-nocheck
/**
* External dependencies
*/
Expand Down Expand Up @@ -33,19 +34,21 @@ function mergeProps( defaultProps = {}, props = {} ) {
return mergedProps;
}

function DropdownMenu( {
children,
className,
controls,
icon = menu,
label,
popoverProps,
toggleProps,
menuProps,
disableOpenOnArrowDown = false,
text,
noIcons,
} ) {
function DropdownMenu( dropdownMenuProps ) {
const {
children,
className,
controls,
icon = menu,
label,
popoverProps,
toggleProps,
menuProps,
disableOpenOnArrowDown = false,
text,
noIcons,
} = dropdownMenuProps;

if ( isEmpty( controls ) && ! isFunction( children ) ) {
return null;
}
Expand Down
1 change: 1 addition & 0 deletions packages/components/src/dropdown/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-nocheck
/**
* External dependencies
*/
Expand Down
9 changes: 3 additions & 6 deletions packages/components/src/menu-group/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-nocheck
/**
* External dependencies
*/
Expand All @@ -9,12 +10,8 @@ import classnames from 'classnames';
import { Children } from '@wordpress/element';
import { useInstanceId } from '@wordpress/compose';

export function MenuGroup( {
children,
className = '',
label,
hideSeparator,
} ) {
export function MenuGroup( props ) {
const { children, className = '', label, hideSeparator } = props;
const instanceId = useInstanceId( MenuGroup );

if ( ! Children.count( children ) ) {
Expand Down
29 changes: 7 additions & 22 deletions packages/components/src/menu-item/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-nocheck
/**
* External dependencies
*/
Expand All @@ -16,34 +17,18 @@ import Shortcut from '../shortcut';
import Button from '../button';
import Icon from '../icon';

/**
* Renders a generic menu item for use inside the more menu.
*
* @param {Object} props Component props.
* @param {WPElement} props.children Element to render as child of button.
* @param {string} props.info Text to use as description for button text.
* @param {string} props.className Class to set on the container.
* @param {WPIcon} props.icon Button's `icon` prop.
* @param {string|Object} props.shortcut Shortcut's `shortcut` prop.
* @param {boolean} props.isSelected Whether or not the menu item is currently selected.
* @param {string} [props.role="menuitem"] ARIA role of the menu item.
* @param {Object} ref React Element ref.
*
* @return {WPComponent} The component to be rendered.
*/
export function MenuItem(
{
export function MenuItem( props, ref ) {
let {
children,
info,
className,
icon,
shortcut,
isSelected,
role = 'menuitem',
...props
},
ref
) {
...buttonProps
} = props;

className = classnames( 'components-menu-item__button', className );

if ( info ) {
Expand Down Expand Up @@ -72,7 +57,7 @@ export function MenuItem(
}
role={ role }
className={ className }
{ ...props }
{ ...buttonProps }
>
<span className="components-menu-item__item">{ children }</span>
<Shortcut
Expand Down
1 change: 1 addition & 0 deletions packages/components/src/navigable-container/container.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-nocheck
/**
* External dependencies
*/
Expand Down
1 change: 1 addition & 0 deletions packages/components/src/navigable-container/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-nocheck
/**
* Internal Dependencies
*/
Expand Down
1 change: 1 addition & 0 deletions packages/components/src/navigable-container/menu.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-nocheck
/**
* External dependencies
*/
Expand Down
1 change: 1 addition & 0 deletions packages/components/src/navigable-container/tabbable.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-nocheck
/**
* WordPress dependencies
*/
Expand Down
7 changes: 0 additions & 7 deletions packages/components/src/tools-panel/context.js

This file was deleted.

23 changes: 23 additions & 0 deletions packages/components/src/tools-panel/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* WordPress dependencies
*/
import { createContext, useContext } from '@wordpress/element';

/**
* Internal dependencies
*/
import type { ToolsPanelContext as ToolsPanelContextType } from './types';

const noop = () => undefined;

export const ToolsPanelContext = createContext< ToolsPanelContextType >( {
menuItems: { default: {}, optional: {} },
hasMenuItems: false,
isResetting: false,
registerPanelItem: noop,
deregisterPanelItem: noop,
flagItemCustomization: noop,
} );

export const useToolsPanelContext = () =>
useContext< ToolsPanelContextType >( ToolsPanelContext );
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ Text to be displayed within the panel header. It is also passed along as the

- Required: Yes

### `resetAll`: `function`
### `resetAll`: `() => void`

The `resetAll` prop provides the callback to execute when the "Reset all" menu
item is selected. Its purpose is to facilitate resetting any control values
for items contained within this header's panel.

- Required: Yes

### `toggleItem`: `function`
### `toggleItem`: `( label: string ) => void`

This is executed when an individual control's menu item is toggled. It
will update the panel's menu item state and call the panel item's `onSelect` or
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
/**
* External dependencies
*/
// eslint-disable-next-line no-restricted-imports
import type { Ref } from 'react';

/**
* WordPress dependencies
*/
Expand All @@ -11,9 +17,19 @@ import DropdownMenu from '../../dropdown-menu';
import MenuGroup from '../../menu-group';
import MenuItem from '../../menu-item';
import { useToolsPanelHeader } from './hook';
import { contextConnect } from '../../ui/context';
import { contextConnect, WordPressComponentProps } from '../../ui/context';
import type {
ToolsPanelControlsGroupProps,
ToolsPanelHeaderProps,
} from '../types';

const noop = () => {};

const DefaultControlsGroup = ( { items, onClose, toggleItem } ) => {
const DefaultControlsGroup = ( {
items,
onClose,
toggleItem,
}: ToolsPanelControlsGroupProps ) => {
if ( ! items.length ) {
return null;
}
Expand Down Expand Up @@ -51,7 +67,11 @@ const DefaultControlsGroup = ( { items, onClose, toggleItem } ) => {
);
};

const OptionalControlsGroup = ( { items, onClose, toggleItem } ) => {
const OptionalControlsGroup = ( {
items,
onClose,
toggleItem,
}: ToolsPanelControlsGroupProps ) => {
if ( ! items.length ) {
return null;
}
Expand Down Expand Up @@ -91,7 +111,10 @@ const OptionalControlsGroup = ( { items, onClose, toggleItem } ) => {
);
};

const ToolsPanelHeader = ( props, forwardedRef ) => {
const ToolsPanelHeader = (
props: WordPressComponentProps< ToolsPanelHeaderProps, 'h2' >,
forwardedRef: Ref< any >
) => {
const {
dropdownMenuClassName,
hasMenuItems,
Expand All @@ -118,7 +141,7 @@ const ToolsPanelHeader = ( props, forwardedRef ) => {
label={ labelText }
menuProps={ { className: dropdownMenuClassName } }
>
{ ( { onClose } ) => (
{ ( { onClose = noop } ) => (
<>
<DefaultControlsGroup
items={ defaultItems }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ import { useMemo } from '@wordpress/element';
*/
import * as styles from '../styles';
import { useToolsPanelContext } from '../context';
import { useContextSystem } from '../../ui/context';
import { useContextSystem, WordPressComponentProps } from '../../ui/context';
import { useCx } from '../../utils/hooks/use-cx';
import type { ToolsPanelHeaderProps } from '../types';

export function useToolsPanelHeader( props ) {
export function useToolsPanelHeader(
props: WordPressComponentProps< ToolsPanelHeaderProps, 'h2' >
) {
const { className, ...otherProps } = useContextSystem(
props,
'ToolsPanelHeader'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ for how to use `ToolsPanelItem`.

## Props

### `hasValue`: `function`
### `hasValue`: `() => boolean`

This is called when building the `ToolsPanel` menu to determine the item's
initial checked state.
Expand All @@ -45,14 +45,14 @@ A panel item's `label` should be unique among all items within a single panel.

- Required: Yes

### `onDeselect`: `function`
### `onDeselect`: `() => void`

Called when this item is deselected in the `ToolsPanel` menu. This is normally
used to reset the panel item control's value.

- Required: No

### `onSelect`: `function`
### `onSelect`: `() => void`

A callback to take action when this item is selected in the `ToolsPanel` menu.

Expand All @@ -66,7 +66,7 @@ allows items to be injected from a shared source.

- Required: No

### `resetAllFilter`: `function`
### `resetAllFilter`: `() => void`

A `ToolsPanel` will collect each item's `resetAllFilter` and pass an array of
these functions through to the panel's `resetAll` callback. They can then be
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
/**
* External dependencies
*/
// eslint-disable-next-line no-restricted-imports
import type { Ref } from 'react';

/**
* Internal dependencies
*/
import { useToolsPanelItem } from './hook';
import { View } from '../../view';
import { contextConnect } from '../../ui/context';
import { contextConnect, WordPressComponentProps } from '../../ui/context';
import type { ToolsPanelItemProps } from '../types';

// This wraps controls to be conditionally displayed within a tools panel. It
// prevents props being applied to HTML elements that would make them invalid.
const ToolsPanelItem = ( props, forwardedRef ) => {
const ToolsPanelItem = (
props: WordPressComponentProps< ToolsPanelItemProps, 'div' >,
forwardedRef: Ref< any >
) => {
const { children, isShown, ...toolsPanelItemProps } = useToolsPanelItem(
props
);
Expand Down
Loading

0 comments on commit 1620d51

Please sign in to comment.