diff --git a/examples/bpk-component-accordion/examples.js b/examples/bpk-component-accordion/examples.tsx similarity index 98% rename from examples/bpk-component-accordion/examples.js rename to examples/bpk-component-accordion/examples.tsx index 8ec6b2aad3..f7f787a1ae 100644 --- a/examples/bpk-component-accordion/examples.js +++ b/examples/bpk-component-accordion/examples.tsx @@ -16,8 +16,6 @@ * limitations under the License. */ -/* @flow strict */ - import { colorMonteverde, colorPanjin, @@ -32,6 +30,7 @@ import { BpkAccordionItem, withAccordionItemState, } from '../../packages/bpk-component-accordion'; +// @ts-expect-error Untyped import - see `decisions/imports-ts-suppressions.md`. import BpkCheckbox from '../../packages/bpk-component-checkbox'; import { withAlignment } from '../../packages/bpk-component-icon'; import StopsIcon from '../../packages/bpk-component-icon/sm/stops'; @@ -44,7 +43,7 @@ const StatefulAccordionItem = withAccordionItemState(BpkAccordionItem); const AlignedStopsIcon = withAlignment(StopsIcon, lineHeightBase, iconSizeSm); const AlignedTimeIcon = withAlignment(TimeIcon, lineHeightBase, iconSizeSm); -const CheckboxWrapper = (props) => ( +const CheckboxWrapper = (props: any) => (
); diff --git a/examples/bpk-component-accordion/stories-utils.js b/examples/bpk-component-accordion/stories-utils.tsx similarity index 100% rename from examples/bpk-component-accordion/stories-utils.js rename to examples/bpk-component-accordion/stories-utils.tsx diff --git a/examples/bpk-component-accordion/stories.js b/examples/bpk-component-accordion/stories.tsx similarity index 96% rename from examples/bpk-component-accordion/stories.js rename to examples/bpk-component-accordion/stories.tsx index 2b000faea4..52f8193039 100644 --- a/examples/bpk-component-accordion/stories.js +++ b/examples/bpk-component-accordion/stories.tsx @@ -77,7 +77,9 @@ export const WithoutDividerOnDark = SingleItemExampleWithoutDividerOnDark; export const VisualTest = SingleItemExample; export const VisualTestOnDark = WithDarkBackgroundExample; -export const VisualTestWithZoom = VisualTest.bind({}); -VisualTestWithZoom.args = { - zoomEnabled: true, +export const VisualTestWithZoom = { + render: VisualTest, + args: { + zoomEnabled: true, + } }; diff --git a/packages/bpk-component-accordion/index.js b/packages/bpk-component-accordion/index.ts similarity index 98% rename from packages/bpk-component-accordion/index.js rename to packages/bpk-component-accordion/index.ts index 0be49bf9c7..908560a875 100644 --- a/packages/bpk-component-accordion/index.js +++ b/packages/bpk-component-accordion/index.ts @@ -16,8 +16,6 @@ * limitations under the License. */ -/* @flow strict */ - import BpkAccordion from './src/BpkAccordion'; import BpkAccordionItem from './src/BpkAccordionItem'; import withAccordionItemState from './src/withAccordionItemState'; diff --git a/packages/bpk-component-accordion/src/BpkAccordion-test.js b/packages/bpk-component-accordion/src/BpkAccordion-test.tsx similarity index 98% rename from packages/bpk-component-accordion/src/BpkAccordion-test.js rename to packages/bpk-component-accordion/src/BpkAccordion-test.tsx index a807babb8f..b857dd40ef 100644 --- a/packages/bpk-component-accordion/src/BpkAccordion-test.js +++ b/packages/bpk-component-accordion/src/BpkAccordion-test.tsx @@ -16,8 +16,6 @@ * limitations under the License. */ -/* @flow strict */ - import { render } from '@testing-library/react'; import BpkAccordion from './BpkAccordion'; diff --git a/packages/bpk-component-accordion/src/BpkAccordion.js b/packages/bpk-component-accordion/src/BpkAccordion.tsx similarity index 67% rename from packages/bpk-component-accordion/src/BpkAccordion.js rename to packages/bpk-component-accordion/src/BpkAccordion.tsx index 6d1881a04f..2c613bca47 100644 --- a/packages/bpk-component-accordion/src/BpkAccordion.js +++ b/packages/bpk-component-accordion/src/BpkAccordion.tsx @@ -16,10 +16,8 @@ * limitations under the License. */ -/* @flow strict */ - -import PropTypes from 'prop-types'; -import { createContext, Node } from 'react'; +import { createContext } from 'react'; +import type { ReactNode } from 'react'; import { cssModules } from '../../bpk-react-utils'; @@ -27,15 +25,26 @@ import STYLES from './BpkAccordion.module.scss'; const getClassName = cssModules(STYLES); -type Props = { children: Node, className: ?string }; +export type BpkAccordionProps = { + children: ReactNode; + className?: string; + divider?: boolean; + onDark?: boolean; +}; export const BpkAccordionContext = createContext({ onDark: false, divider: true, }); -const BpkAccordion = (props: Props) => { - const { children, className, divider, onDark, ...rest } = props; +const BpkAccordion = (props: BpkAccordionProps) => { + const { + children, + className, + divider = true, + onDark = false, + ...rest + } = props; const classNames = getClassName( 'bpk-accordion', @@ -45,7 +54,6 @@ const BpkAccordion = (props: Props) => { return ( - {/* // $FlowFixMe[cannot-spread-inexact] - inexact rest. See decisions/flowfixme.md */}
{children}
@@ -53,17 +61,4 @@ const BpkAccordion = (props: Props) => { ); }; -BpkAccordion.propTypes = { - children: PropTypes.node.isRequired, - className: PropTypes.string, - onDark: PropTypes.bool, - divider: PropTypes.bool, -}; - -BpkAccordion.defaultProps = { - className: null, - onDark: false, - divider: true, -}; - export default BpkAccordion; diff --git a/packages/bpk-component-accordion/src/BpkAccordionItem-test.js b/packages/bpk-component-accordion/src/BpkAccordionItem-test.tsx similarity index 99% rename from packages/bpk-component-accordion/src/BpkAccordionItem-test.js rename to packages/bpk-component-accordion/src/BpkAccordionItem-test.tsx index ec6b429be3..743bc85266 100644 --- a/packages/bpk-component-accordion/src/BpkAccordionItem-test.js +++ b/packages/bpk-component-accordion/src/BpkAccordionItem-test.tsx @@ -16,8 +16,6 @@ * limitations under the License. */ -/* @flow strict */ - import { render } from '@testing-library/react'; import StopsIcon from '../../bpk-component-icon/sm/stops'; diff --git a/packages/bpk-component-accordion/src/BpkAccordionItem.js b/packages/bpk-component-accordion/src/BpkAccordionItem.tsx similarity index 80% rename from packages/bpk-component-accordion/src/BpkAccordionItem.js rename to packages/bpk-component-accordion/src/BpkAccordionItem.tsx index ae3ef59be5..16c25040a9 100644 --- a/packages/bpk-component-accordion/src/BpkAccordionItem.js +++ b/packages/bpk-component-accordion/src/BpkAccordionItem.tsx @@ -16,11 +16,10 @@ * limitations under the License. */ -/* @flow strict */ - -import PropTypes from 'prop-types'; -import { Node, Element, useContext, cloneElement } from 'react'; +import { useContext, cloneElement } from 'react'; +import type { ReactNode, ReactElement } from 'react'; +// @ts-expect-error Untyped import. See `decisions/imports-ts-suppressions.md`. import AnimateHeight from '../../bpk-animate-height'; import { withButtonAlignment } from '../../bpk-component-icon'; import ChevronDownIcon from '../../bpk-component-icon/sm/chevron-down'; @@ -35,18 +34,20 @@ const getClassName = cssModules(STYLES); const ExpandIcon = withButtonAlignment(ChevronDownIcon); -type Props = { - children: Node, - id: string, - title: string, - expanded: boolean, - icon: ?Element, - onClick: () => mixed, - tagName: 'span' | 'p' | 'text' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', - textStyle: $Values, +export type BpkAccordionItemProps = { + children: ReactNode; + id: string; + title: string; + className?: string; + expanded?: boolean; + initiallyExpanded?: boolean; + icon?: ReactElement; + onClick?: () => void; + tagName?: 'span' | 'p' | 'text' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; + textStyle?: (typeof TEXT_STYLES)[keyof typeof TEXT_STYLES]; }; -const BpkAccordionItem = (props: Props) => { +const BpkAccordionItem = (props: BpkAccordionItemProps) => { const { divider, onDark } = useContext(BpkAccordionContext); const itemClassNames = [getClassName('bpk-accordion__item')]; const iconClassNames = [getClassName('bpk-accordion__item-expand-icon')]; @@ -59,12 +60,12 @@ const BpkAccordionItem = (props: Props) => { const { children, - expanded, - icon, + expanded = false, + icon = null, id, - onClick, - tagName, - textStyle, + onClick = () => null, + tagName = 'h3', + textStyle = TEXT_STYLES.bodyDefault, title, ...rest } = props; @@ -72,7 +73,6 @@ const BpkAccordionItem = (props: Props) => { // if this component is passed initiallyExpanded, this makes sure it doesn't // end up on the node. Not ideal as our container component shouldn't be passing // it, but the benefit of a better container api versus this was worth it - // $FlowFixMe[prop-missing] - see above delete rest.initiallyExpanded; if (divider) { @@ -147,7 +147,9 @@ const BpkAccordionItem = (props: Props) => {
@@ -163,23 +165,4 @@ const BpkAccordionItem = (props: Props) => { ); }; -BpkAccordionItem.propTypes = { - children: PropTypes.node.isRequired, - id: PropTypes.string.isRequired, - title: PropTypes.string.isRequired, - expanded: PropTypes.bool, - icon: PropTypes.node, - onClick: PropTypes.func, - tagName: PropTypes.string, - textStyle: PropTypes.string, -}; - -BpkAccordionItem.defaultProps = { - expanded: false, - icon: null, - onClick: () => null, - tagName: 'h3', - textStyle: TEXT_STYLES.bodyDefault, -}; - export default BpkAccordionItem; diff --git a/packages/bpk-component-accordion/src/__snapshots__/BpkAccordion-test.js.snap b/packages/bpk-component-accordion/src/__snapshots__/BpkAccordion-test.tsx.snap similarity index 100% rename from packages/bpk-component-accordion/src/__snapshots__/BpkAccordion-test.js.snap rename to packages/bpk-component-accordion/src/__snapshots__/BpkAccordion-test.tsx.snap diff --git a/packages/bpk-component-accordion/src/__snapshots__/BpkAccordionItem-test.js.snap b/packages/bpk-component-accordion/src/__snapshots__/BpkAccordionItem-test.tsx.snap similarity index 100% rename from packages/bpk-component-accordion/src/__snapshots__/BpkAccordionItem-test.js.snap rename to packages/bpk-component-accordion/src/__snapshots__/BpkAccordionItem-test.tsx.snap diff --git a/packages/bpk-component-accordion/src/__snapshots__/withAccordionItemState-test.js.snap b/packages/bpk-component-accordion/src/__snapshots__/withAccordionItemState-test.tsx.snap similarity index 100% rename from packages/bpk-component-accordion/src/__snapshots__/withAccordionItemState-test.js.snap rename to packages/bpk-component-accordion/src/__snapshots__/withAccordionItemState-test.tsx.snap diff --git a/packages/bpk-component-accordion/src/__snapshots__/withSingleItemAccordionState-test.js.snap b/packages/bpk-component-accordion/src/__snapshots__/withSingleItemAccordionState-test.tsx.snap similarity index 100% rename from packages/bpk-component-accordion/src/__snapshots__/withSingleItemAccordionState-test.js.snap rename to packages/bpk-component-accordion/src/__snapshots__/withSingleItemAccordionState-test.tsx.snap diff --git a/packages/bpk-component-accordion/src/accessibility-test.js b/packages/bpk-component-accordion/src/accessibility-test.tsx similarity index 98% rename from packages/bpk-component-accordion/src/accessibility-test.js rename to packages/bpk-component-accordion/src/accessibility-test.tsx index 9b66379c94..d4b3879100 100644 --- a/packages/bpk-component-accordion/src/accessibility-test.js +++ b/packages/bpk-component-accordion/src/accessibility-test.tsx @@ -16,8 +16,6 @@ * limitations under the License. */ -/* @flow strict */ - import { render } from '@testing-library/react'; import { axe } from 'jest-axe'; diff --git a/packages/bpk-component-accordion/src/withAccordionItemState-test.js b/packages/bpk-component-accordion/src/withAccordionItemState-test.tsx similarity index 99% rename from packages/bpk-component-accordion/src/withAccordionItemState-test.js rename to packages/bpk-component-accordion/src/withAccordionItemState-test.tsx index 5bd764a777..c5e4189b6c 100644 --- a/packages/bpk-component-accordion/src/withAccordionItemState-test.js +++ b/packages/bpk-component-accordion/src/withAccordionItemState-test.tsx @@ -16,8 +16,6 @@ * limitations under the License. */ -/* @flow strict */ - import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import '@testing-library/jest-dom'; diff --git a/packages/bpk-component-accordion/src/withAccordionItemState.js b/packages/bpk-component-accordion/src/withAccordionItemState.tsx similarity index 69% rename from packages/bpk-component-accordion/src/withAccordionItemState.js rename to packages/bpk-component-accordion/src/withAccordionItemState.tsx index f57551ee41..c2a7e5b494 100644 --- a/packages/bpk-component-accordion/src/withAccordionItemState.js +++ b/packages/bpk-component-accordion/src/withAccordionItemState.tsx @@ -16,31 +16,31 @@ * limitations under the License. */ -/* @flow strict */ - -import PropTypes from 'prop-types'; import { Component } from 'react'; import type { ComponentType } from 'react'; import { wrapDisplayName } from '../../bpk-react-utils'; +import type { BpkAccordionItemProps } from './BpkAccordionItem'; + type Props = { - initiallyExpanded: boolean, - expanded: boolean, - onClick: ?() => mixed, + initiallyExpanded: boolean; + expanded: boolean; + onClick?: () => void; }; type State = { - expanded: boolean, + expanded: boolean; }; -const withAccordionItemState = (ComposedComponent: ComponentType) => { - class WithAccordionItemState extends Component { - static propTypes = { - initiallyExpanded: PropTypes.bool, - expanded: PropTypes.bool, - onClick: PropTypes.func, - }; +const withAccordionItemState =

( + ComposedComponent: ComponentType

, +) => { + class WithAccordionItemState extends Component

{ + static displayName = wrapDisplayName( + ComposedComponent, + 'withAccordionItemState', + ); static defaultProps = { initiallyExpanded: false, @@ -48,7 +48,7 @@ const withAccordionItemState = (ComposedComponent: ComponentType) => { onClick: null, }; - constructor(props: Props) { + constructor(props: P & Props) { super(props); this.state = { @@ -69,21 +69,15 @@ const withAccordionItemState = (ComposedComponent: ComponentType) => { const { expanded, initiallyExpanded, onClick, ...rest } = this.props; return ( - // $FlowFixMe[cannot-spread-inexact] - inexact rest. See 'decisions/flowfixme.md'. ); } } - WithAccordionItemState.displayName = wrapDisplayName( - ComposedComponent, - 'withAccordionItemState', - ); - return WithAccordionItemState; }; diff --git a/packages/bpk-component-accordion/src/withSingleItemAccordionState-test.js b/packages/bpk-component-accordion/src/withSingleItemAccordionState-test.tsx similarity index 83% rename from packages/bpk-component-accordion/src/withSingleItemAccordionState-test.js rename to packages/bpk-component-accordion/src/withSingleItemAccordionState-test.tsx index afe0c4dc7e..a3ebd281be 100644 --- a/packages/bpk-component-accordion/src/withSingleItemAccordionState-test.js +++ b/packages/bpk-component-accordion/src/withSingleItemAccordionState-test.tsx @@ -16,8 +16,6 @@ * limitations under the License. */ -/* @flow strict */ - import { render } from '@testing-library/react'; import '@testing-library/jest-dom'; @@ -40,6 +38,7 @@ describe('withSingleItemAccordionState(BpkAccordion)', () => { it('should render correctly with arbitrary props', () => { const { asFragment } = render( + // @ts-expect-error - foo is not a valid prop

Accordion Item 1
Accordion Item 2
@@ -51,25 +50,32 @@ describe('withSingleItemAccordionState(BpkAccordion)', () => { it('should render correctly with custom initially expanded item', () => { const { asFragment } = render( + /* eslint-disable react/no-unknown-property */
Accordion Item 1
- {/* eslint-disable-next-line react/no-unknown-property */} + {/* + // @ts-expect-error testing unknown property */}
Accordion Item 2
Accordion Item 3
, + /* eslint-enable react/no-unknown-property */ ); expect(asFragment()).toMatchSnapshot(); }); it('should render correctly even when multiple items are marked as initially expanded', () => { const { asFragment } = render( + /* eslint-disable react/no-unknown-property */
Accordion Item 1
- {/* eslint-disable-next-line react/no-unknown-property */} + {/* + // @ts-expect-error testing unknown property */}
Accordion Item 2
- {/* eslint-disable-next-line react/no-unknown-property */} + {/* + // @ts-expect-error testing unknown property */}
Accordion Item 3
, + /* eslint-enable react/no-unknown-property */ ); expect(asFragment()).toMatchSnapshot(); }); diff --git a/packages/bpk-component-accordion/src/withSingleItemAccordionState.js b/packages/bpk-component-accordion/src/withSingleItemAccordionState.tsx similarity index 61% rename from packages/bpk-component-accordion/src/withSingleItemAccordionState.js rename to packages/bpk-component-accordion/src/withSingleItemAccordionState.tsx index 2436d3d110..c89ffa3808 100644 --- a/packages/bpk-component-accordion/src/withSingleItemAccordionState.js +++ b/packages/bpk-component-accordion/src/withSingleItemAccordionState.tsx @@ -16,36 +16,40 @@ * limitations under the License. */ -/* @flow strict */ - -import PropTypes from 'prop-types'; import { Component, Children, cloneElement } from 'react'; -import type { Node, Element, ComponentType } from 'react'; +import type { ReactNode, ReactElement, ComponentType } from 'react'; import { wrapDisplayName } from '../../bpk-react-utils'; -const getInitiallyExpanded = (children) => { - const accordionItems = Children.toArray(children); +import type { BpkAccordionProps } from './BpkAccordion'; + +const getInitiallyExpanded = (children: ReactNode) => { + const accordionItems = Children.toArray(children) as ReactElement[]; const result = accordionItems.reduceRight( (prev, item) => (item.props.initiallyExpanded ? item : prev), - {}, + {} as ReactElement, ); return (result || {}).key || null; }; type Props = { - children: Node, + children: ReactNode; }; type State = { - expanded: ?string | ?number, + expanded?: string | number | null; }; -const withSingleItemAccordionState = ( - ComposedComponent: ComponentType, +const withSingleItemAccordionState =

( + ComposedComponent: ComponentType

, ) => { - class WithSingleItemAccordionState extends Component { - constructor(props: Props) { + class WithSingleItemAccordionState extends Component

{ + static displayName = wrapDisplayName( + ComposedComponent, + 'withSingleItemAccordionState', + ); + + constructor(props: P & Props) { super(props); this.state = { @@ -53,13 +57,13 @@ const withSingleItemAccordionState = ( }; } - openAccordionItem = (key: ?string | ?number) => { + openAccordionItem = (key?: string | number | null) => { this.setState({ expanded: key }); }; - renderAccordionItem = (accordionItem: Element) => { + renderAccordionItem = (accordionItem: ReactElement) => { const expanded = this.state.expanded === accordionItem.key; - const onClick = () => this.openAccordionItem(accordionItem.key); + const onClick = () => this.openAccordionItem(accordionItem?.key); return cloneElement(accordionItem, { expanded, onClick }); }; @@ -68,22 +72,15 @@ const withSingleItemAccordionState = ( const { children, ...rest } = this.props; return ( - - {Children.toArray(children).map(this.renderAccordionItem)} + + {Children.toArray(children).map((el) => + this.renderAccordionItem(el as ReactElement), + )} ); } } - WithSingleItemAccordionState.propTypes = { - children: PropTypes.node.isRequired, - }; - - WithSingleItemAccordionState.displayName = wrapDisplayName( - ComposedComponent, - 'withSingleItemAccordionState', - ); - return WithSingleItemAccordionState; };