Skip to content

Commit

Permalink
fix: declare children prop explicitly for FCs (#5258)
Browse files Browse the repository at this point in the history
  • Loading branch information
adidahiya authored Apr 15, 2022
1 parent 1ab3636 commit 72b9349
Show file tree
Hide file tree
Showing 29 changed files with 83 additions and 76 deletions.
33 changes: 16 additions & 17 deletions packages/core/src/components/breadcrumbs/breadcrumb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import { Icon } from "../icon/icon";
export type BreadcrumbProps = IBreadcrumbProps;
/** @deprecated use BreadcrumbProps */
export interface IBreadcrumbProps extends ActionProps, LinkProps {
children?: React.ReactNode;

/** Whether this breadcrumb is the current breadcrumb. */
current?: boolean;

Expand All @@ -35,41 +37,38 @@ export interface IBreadcrumbProps extends ActionProps, LinkProps {
iconTitle?: string;
}

export const Breadcrumb: React.FunctionComponent<BreadcrumbProps> = breadcrumbProps => {
export const Breadcrumb: React.FC<BreadcrumbProps> = props => {
const classes = classNames(
Classes.BREADCRUMB,
{
[Classes.BREADCRUMB_CURRENT]: breadcrumbProps.current,
[Classes.DISABLED]: breadcrumbProps.disabled,
[Classes.BREADCRUMB_CURRENT]: props.current,
[Classes.DISABLED]: props.disabled,
},
breadcrumbProps.className,
props.className,
);

const icon =
breadcrumbProps.icon != null ? (
<Icon title={breadcrumbProps.iconTitle} icon={breadcrumbProps.icon} />
) : undefined;
const icon = props.icon != null ? <Icon title={props.iconTitle} icon={props.icon} /> : undefined;

if (breadcrumbProps.href == null && breadcrumbProps.onClick == null) {
if (props.href == null && props.onClick == null) {
return (
<span className={classes}>
{icon}
{breadcrumbProps.text}
{breadcrumbProps.children}
{props.text}
{props.children}
</span>
);
}
return (
<a
className={classes}
href={breadcrumbProps.href}
onClick={breadcrumbProps.disabled ? undefined : breadcrumbProps.onClick}
tabIndex={breadcrumbProps.disabled ? undefined : 0}
target={breadcrumbProps.target}
href={props.href}
onClick={props.disabled ? undefined : props.onClick}
tabIndex={props.disabled ? undefined : 0}
target={props.target}
>
{icon}
{breadcrumbProps.text}
{breadcrumbProps.children}
{props.text}
{props.children}
</a>
);
};
3 changes: 3 additions & 0 deletions packages/core/src/components/dialog/dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ import { IBackdropProps, OverlayableProps, Overlay } from "../overlay/overlay";
export type DialogProps = IDialogProps;
/** @deprecated use DialogProps */
export interface IDialogProps extends OverlayableProps, IBackdropProps, Props {
/** Dialog contents. */
children?: React.ReactNode;

/**
* Toggles the visibility of the overlay and its children.
* This prop is required because the component is controlled.
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/components/forms/controls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ interface IControlInternalProps extends ControlProps {
* Renders common control elements, with additional props to customize appearance.
* This component is not exported and is only used in this file for `Checkbox`, `Radio`, and `Switch` below.
*/
const Control: React.FunctionComponent<IControlInternalProps> = ({
const Control: React.FC<IControlInternalProps> = ({
alignIndicator,
children,
className,
Expand Down
18 changes: 11 additions & 7 deletions packages/core/src/components/html/html.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,19 @@ function htmlElement<E extends HTMLElement>(
tagName: keyof JSX.IntrinsicElements,
tagClassName: string,
// eslint-disable-next-line deprecation/deprecation
): React.FunctionComponent<React.HTMLProps<E> & IElementRefProps<E>> {
): React.FC<React.HTMLProps<E> & IElementRefProps<E> & { children?: React.ReactNode }> {
/* eslint-disable-next-line react/display-name */
return props => {
const { className, elementRef, ...htmlProps } = props;
return React.createElement(tagName, {
...htmlProps,
className: classNames(tagClassName, className),
ref: elementRef,
});
const { className, elementRef, children, ...htmlProps } = props;
return React.createElement(
tagName,
{
...htmlProps,
className: classNames(tagClassName, className),
ref: elementRef,
},
children,
);
};
}

Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/components/panel-stack2/panelView2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const PanelView2: PanelView2Component = <T extends Panel<object>>(props:
// `props.panel.renderPanel` is simply a function that returns a JSX.Element. It may be an FC which
// uses hooks. In order to avoid React errors due to inconsistent hook calls, we must encapsulate
// those hooks with their own lifecycle through a very simple wrapper component.
const PanelWrapper: React.FunctionComponent = React.useMemo(
const PanelWrapper: React.FC = React.useMemo(
() => () =>
// N.B. A type cast is required because of error TS2345, where technically `panel.props` could be
// instantiated with a type unrelated to our generic constraint `T` here. We know
Expand Down
5 changes: 1 addition & 4 deletions packages/core/src/components/popover/popoverArrow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,7 @@ export interface IPopoverArrowProps {
placement: Placement;
}

export const PopoverArrow: React.FunctionComponent<IPopoverArrowProps> = ({
arrowProps: { ref, style },
placement,
}) => (
export const PopoverArrow: React.FC<IPopoverArrowProps> = ({ arrowProps: { ref, style }, placement }) => (
<div className={Classes.POPOVER_ARROW} ref={ref} style={style.left == null || isNaN(+style.left) ? {} : style}>
<svg viewBox="0 0 30 30" style={{ transform: `rotate(${getArrowAngle(placement)}deg)` }}>
<path className={Classes.POPOVER_ARROW + "-border"} d={SVG_SHADOW_PATH} />
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/components/slider/multiSlider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { argMin, fillValues, formatPercentage } from "./sliderUtils";
* SFC used to pass slider handle props to a `MultiSlider`.
* This element is not rendered directly.
*/
const MultiSliderHandle: React.FunctionComponent<HandleProps> = () => null;
const MultiSliderHandle: React.FC<HandleProps> = () => null;
MultiSliderHandle.displayName = `${DISPLAYNAME_PREFIX}.MultiSliderHandle`;

export interface ISliderBaseProps extends Props, IntentProps {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/components/tabs/tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import * as Utils from "../../common/utils";
import { TabProps, Tab, TabId } from "./tab";
import { generateTabPanelId, generateTabTitleId, TabTitle } from "./tabTitle";

export const Expander: React.FunctionComponent = () => <div className={Classes.FLEX_EXPANDER} />;
export const Expander: React.FC = () => <div className={Classes.FLEX_EXPANDER} />;

type TabElement = React.ReactElement<TabProps & { children: React.ReactNode }>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,4 +243,4 @@ describe("<MultistepDialog>", () => {
});
});

const Panel: React.FunctionComponent = () => <strong> panel</strong>;
const Panel: React.FC = () => <strong> panel</strong>;
4 changes: 2 additions & 2 deletions packages/core/test/overflow-list/overflowListTests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ interface ITestItem {
const IDS = [0, 1, 2, 3, 4, 5];
const ITEMS: ITestItem[] = IDS.map(id => ({ id }));

const TestItem: React.FunctionComponent<ITestItem> = () => <div style={{ width: 10, flex: "0 0 auto" }} />;
const TestOverflow: React.FunctionComponent<{ items: ITestItem[] }> = () => <div />;
const TestItem: React.FC<ITestItem> = () => <div style={{ width: 10, flex: "0 0 auto" }} />;
const TestOverflow: React.FC<{ items: ITestItem[] }> = () => <div />;

describe.skip("<OverflowList>", function (this) {
// these tests rely on DOM measurement which can be flaky, so we allow some retries
Expand Down
16 changes: 8 additions & 8 deletions packages/core/test/resize-sensor/resizeSensorTests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ import { mount, ReactWrapper } from "enzyme";
import * as React from "react";
import { spy } from "sinon";

import { IResizeSensorProps, ResizeSensor } from "../../src/components/resize-sensor/resizeSensor";
import { ResizeSensorProps, ResizeSensor } from "../../src/components/resize-sensor/resizeSensor";

describe("<ResizeSensor>", () => {
// this scope variable is assigned in mountResizeSensor() and used in resize()
let wrapper: ReactWrapper<IResizeTesterProps, any> | undefined;
let wrapper: ReactWrapper<ResizeTesterProps, any> | undefined;
const testsContainerElement = document.createElement("div");
document.documentElement.appendChild(testsContainerElement);

Expand Down Expand Up @@ -68,15 +68,15 @@ describe("<ResizeSensor>", () => {
assert.equal(onResize2.callCount, 2);
});

function mountResizeSensor(onResize: IResizeSensorProps["onResize"]) {
return (wrapper = mount<IResizeTesterProps>(
function mountResizeSensor(onResize: ResizeSensorProps["onResize"]) {
return (wrapper = mount<ResizeTesterProps>(
<ResizeTester onResize={onResize} />,
// must be in the DOM for measurement
{ attachTo: testsContainerElement },
));
}

function resize(size: ISizeProps) {
function resize(size: SizeProps) {
wrapper!.setProps(size);
return new Promise(resolve => setTimeout(resolve, 30));
}
Expand All @@ -91,15 +91,15 @@ describe("<ResizeSensor>", () => {
}
});

interface ISizeProps {
interface SizeProps {
/** Used as React `key`, so changing it will force a new element to be created. */
id?: number;
width?: number;
height?: number;
}

type IResizeTesterProps = IResizeSensorProps & ISizeProps;
const ResizeTester: React.FunctionComponent<IResizeTesterProps> = ({ id, width, height, ...resizeProps }) => (
type ResizeTesterProps = ResizeSensorProps & SizeProps;
const ResizeTester: React.FC<ResizeTesterProps> = ({ id, width, height, ...resizeProps }) => (
<ResizeSensor {...resizeProps}>
<div key={id} style={{ width, height }} />
</ResizeSensor>
Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/tabs/tabsTests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -409,4 +409,4 @@ describe("<Tabs>", () => {
}
});

const Panel: React.FunctionComponent<{ title: string }> = ({ title }) => <strong>{title} panel</strong>;
const Panel: React.FC<{ title: string }> = ({ title }) => <strong>{title} panel</strong>;
8 changes: 4 additions & 4 deletions packages/docs-app/src/components/colorPalettes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ function getLuminance(hex: string) {
const DARK_LUMA_CUTOFF = 111;

// a single swatch of color, name on left & hex on right. click to copy hex.
const ColorSwatch: React.FunctionComponent<{ colorName: string; hexCode: string }> = ({ colorName, hexCode }) => {
const ColorSwatch: React.FC<{ colorName: string; hexCode: string }> = ({ colorName, hexCode }) => {
const style = {
backgroundColor: hexCode,
color: getLuminance(hexCode) < DARK_LUMA_CUTOFF ? Colors.WHITE : Colors.BLACK,
Expand All @@ -65,7 +65,7 @@ const ColorSwatch: React.FunctionComponent<{ colorName: string; hexCode: string
};

// vertical list of swatches for each color
const ColorPalette: React.FunctionComponent<{ colors: string[] }> = ({ colors }) => (
const ColorPalette: React.FC<{ colors: string[] }> = ({ colors }) => (
<div
className={classNames("docs-color-palette", {
"docs-color-palette-single": colors.length === 1,
Expand All @@ -79,7 +79,7 @@ const ColorPalette: React.FunctionComponent<{ colors: string[] }> = ({ colors })

// horizontal list of swatches for each color
// no text in swatch; display all hex codes underneath
export const ColorBar: React.FunctionComponent<{ colors: string[] }> = ({ colors }) => {
export const ColorBar: React.FC<{ colors: string[] }> = ({ colors }) => {
const hexString = colors.map(getHexCode).join(", ");
const jsonString = `[${colors.map(c => `"${getHexCode(c)}"`).join(", ")}]`;

Expand All @@ -104,7 +104,7 @@ export const ColorBar: React.FunctionComponent<{ colors: string[] }> = ({ colors
};

// a group of ColorPalettes, arranged by default in two columns
function createPaletteBook(palettes: string[][], className?: string): React.FunctionComponent {
function createPaletteBook(palettes: string[][], className?: string): React.FC {
return () => (
<section className={classNames("docs-color-book", className)}>
{palettes.map((palette, index) => (
Expand Down
6 changes: 3 additions & 3 deletions packages/docs-app/src/components/colorSchemes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -205,17 +205,17 @@ export class ColorScheme extends React.PureComponent<IColorSchemeProps, IColorSc
}
}

export const QualitativeSchemePalette: React.FunctionComponent = () => <ColorBar colors={QUALITATIVE} />;
export const QualitativeSchemePalette: React.FC = () => <ColorBar colors={QUALITATIVE} />;

export const SequentialSchemePalette: React.FunctionComponent = () => {
export const SequentialSchemePalette: React.FC = () => {
const schemes = [
{ label: "Single hue", palettes: SINGLE_HUE },
{ label: "Multi-hue", palettes: SEQUENTIAL },
];
return <ColorScheme schemes={schemes} />;
};

export const DivergingSchemePalette: React.FunctionComponent = () => {
export const DivergingSchemePalette: React.FC = () => {
const schemes = [{ diverging: true, label: "Diverging", palettes: DIVERGING }];
return <ColorScheme schemes={schemes} />;
};
2 changes: 1 addition & 1 deletion packages/docs-app/src/components/logo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import * as React from "react";

export const Logo: React.FunctionComponent = () => (
export const Logo: React.FC = () => (
<svg width="65" height="76" xmlns="http://www.w3.org/2000/svg">
<g fillRule="nonzero">
<path d="M28.795 2.421l2.177-1.254a4 4 0 0 1 4.039.027l28.032 16.643A4 4 0 0 1 65 21.277v33.446a4 4 0 0 1-1.958 3.44l-28.03 16.644a4 4 0 0 1-4.039.027L2.004 58.154A4 4 0 0 1 0 54.687V21.313a4 4 0 0 1 2.004-3.467l26.79-15.425zm3.175.48l-.499-.867v-1h3.742L32.01 2.878a2.008 2.008 0 0 0-.04.023zM3.002 19.58A2 2 0 0 0 2 21.313v33.374a2 2 0 0 0 1.002 1.733l28.97 16.68a2 2 0 0 0 2.018-.013l28.03-16.644a2 2 0 0 0 .98-1.72V21.277a2 2 0 0 0-.979-1.72L33.99 2.914a2 2 0 0 0-1.98-.036L3.003 19.58z" />
Expand Down
2 changes: 1 addition & 1 deletion packages/docs-app/src/components/navIcons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import * as React from "react";

export const NavIcon: React.FunctionComponent<{ route: string }> = ({ route }) => {
export const NavIcon: React.FC<{ route: string }> = ({ route }) => {
return (
<svg className="docs-nav-package-icon" width="24" height="24" xmlns="http://www.w3.org/2000/svg">
{ICON_CONTENTS[route]}
Expand Down
2 changes: 1 addition & 1 deletion packages/docs-app/src/components/resources.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const RESOURCES: IResourceProps[] = [
{ fileName: "blueprint-colors.sketchpalette", lastUpdated: "January 22, 2020" },
];

export const Resources: React.FunctionComponent = () => (
export const Resources: React.FC = () => (
<>
<div className="blueprint-resources">
{RESOURCES.map(resource => (
Expand Down
3 changes: 2 additions & 1 deletion packages/docs-app/src/components/welcome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ export class Welcome extends React.PureComponent {
}
}

const WelcomeCard: React.FunctionComponent<{
const WelcomeCard: React.FC<{
children?: React.ReactNode;
icon: IconName;
title: string;
href: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export interface IFileMenuProps extends Props {
shouldDismissPopover?: boolean;
}

export const FileMenu: React.FunctionComponent<IFileMenuProps> = props => (
export const FileMenu: React.FC<IFileMenuProps> = props => (
<Menu className={props.className}>
<MenuItem text="New" icon="document" {...props} />
<MenuItem text="Open" icon="folder-shared" {...props} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export interface IIntentSelectProps {
onChange: React.FormEventHandler<HTMLSelectElement>;
}

export const IntentSelect: React.FunctionComponent<IIntentSelectProps> = props => (
export const IntentSelect: React.FC<IIntentSelectProps> = props => (
<Label>
Intent
<HTMLSelect value={props.intent} onChange={props.onChange} options={INTENTS} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export class MenuExample extends React.PureComponent<IExampleProps> {
}
}

const PalantirLogo: React.FunctionComponent = () => (
const PalantirLogo: React.FC = () => (
<svg className={Classes.ICON} width="16" height="16" viewBox="0 0 18 23" xmlns="http://www.w3.org/2000/svg">
<path
d="M16.718 16.653L9 20.013l-7.718-3.36L0 19.133 9 23l9-3.868-1.282-2.48zM9 14.738c-3.297 0-5.97-2.696-5.97-6.02C3.03 5.39 5.703 2.695 9 2.695c3.297 0 5.97 2.696 5.97 6.02 0 3.326-2.673 6.022-5.97 6.022zM9 0C4.23 0 .366 3.9.366 8.708c0 4.81 3.865 8.71 8.634 8.71 4.77 0 8.635-3.9 8.635-8.71C17.635 3.898 13.77 0 9 0z"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ export interface ISelectPanelProps {
onChange: (event: React.FormEvent<HTMLInputElement>) => void;
}

const SelectPanel: React.FunctionComponent<ISelectPanelProps> = props => (
const SelectPanel: React.FC<ISelectPanelProps> = props => (
<div className={classNames(Classes.DIALOG_BODY, "docs-multistep-dialog-example-step")}>
<p>Use this dialog to divide content into multiple sequential steps.</p>
<p>Select one of the options below in order to proceed to the next step:</p>
Expand All @@ -218,7 +218,7 @@ export interface IConfirmPanelProps {
selectedValue: string;
}

const ConfirmPanel: React.FunctionComponent<IConfirmPanelProps> = props => {
const ConfirmPanel: React.FC<IConfirmPanelProps> = props => {
return (
<div className={classNames(Classes.DIALOG_BODY, "docs-multistep-dialog-example-step")}>
<p>
Expand Down
8 changes: 4 additions & 4 deletions packages/docs-app/src/examples/core-examples/tabsExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export class TabsExample extends React.PureComponent<IExampleProps, ITabsExample
private handleNavbarTabChange = (navbarTabId: TabId) => this.setState({ navbarTabId });
}

const ReactPanel: React.FunctionComponent = () => (
const ReactPanel: React.FC = () => (
<div>
<H3>Example panel: React</H3>
<p className={Classes.RUNNING_TEXT}>
Expand All @@ -109,7 +109,7 @@ const ReactPanel: React.FunctionComponent = () => (
</div>
);

const AngularPanel: React.FunctionComponent = () => (
const AngularPanel: React.FC = () => (
<div>
<H3>Example panel: Angular</H3>
<p className={Classes.RUNNING_TEXT}>
Expand All @@ -120,7 +120,7 @@ const AngularPanel: React.FunctionComponent = () => (
</div>
);

const EmberPanel: React.FunctionComponent = () => (
const EmberPanel: React.FC = () => (
<div>
<H3>Example panel: Ember</H3>
<p className={Classes.RUNNING_TEXT}>
Expand All @@ -132,7 +132,7 @@ const EmberPanel: React.FunctionComponent = () => (
</div>
);

const BackbonePanel: React.FunctionComponent = () => (
const BackbonePanel: React.FC = () => (
<div>
<H3>Backbone</H3>
</div>
Expand Down
Loading

1 comment on commit 72b9349

@blueprint-bot
Copy link

Choose a reason for hiding this comment

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

fix: declare children prop explicitly for FCs (#5258)

Previews: documentation | landing | table | demo

Please sign in to comment.