Skip to content

Commit

Permalink
[#285] add more types instead of any
Browse files Browse the repository at this point in the history
  • Loading branch information
darkwebdev committed Dec 21, 2023
1 parent 2c85323 commit b83bb75
Show file tree
Hide file tree
Showing 10 changed files with 40 additions and 40 deletions.
36 changes: 19 additions & 17 deletions src/common/component-utils/utils.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,39 @@
import { Children, FC, ForwardRefExoticComponent, isValidElement, JSXElementConstructor, ReactNode } from 'react'
import './array.polyfill.flat' // for Mobile Safari 11

const componentName =
(component: FC<any> | JSXElementConstructor<any> | ForwardRefExoticComponent<any> | string): string | undefined => {
switch (typeof component) {
case 'string':
return component
case 'function':
return component.name
case 'symbol':
return (component as any).displayName
default:
return undefined
}
}
export type AnyProps = Record<string, unknown>
type AnyComponent<P> = FC<P> | JSXElementConstructor<P> | ForwardRefExoticComponent<P> | string

const componentName = <P = AnyProps>(component: AnyComponent<P>): string | undefined => {
switch (typeof component) {
case 'string':
return component
case 'function':
return component.name
case 'symbol':
return (component as any).displayName
default:
return undefined
}
}

// Returns props of a valid ReactElement
export const elementProps = (node: ReactNode): Record<string, any> => isValidElement(node) ? node.props : {}
export const elementProps = <P = AnyProps>(node: ReactNode): P => isValidElement(node) ? node.props : {}

// Returns component type name or null
export const elementType = (node: ReactNode): string | null =>
isValidElement(node) ? componentName(node.type) : null

// Finds first node of certain component type
export const findComponent = (nodes: ReactNode = [], componentType: FC<any>): ReactNode | undefined =>
export const findComponent = <P = AnyProps>(nodes: ReactNode = [], componentType: FC<P>): ReactNode | undefined =>
Children.toArray(nodes).find(child => elementType(child) === componentName(componentType)) || null

// Filters nodes by predicate
export const filterBy = (nodes: ReactNode = [], predicate: (el: ReactNode) => boolean): ReactNode[] =>
Children.toArray(nodes).filter(predicate)

// Filters nodes by component type(s)
export const filterByType = (nodes: ReactNode = [], componentType: FC<any> | FC<any>[]): ReactNode[] => {
export const filterByType = <P = AnyProps>(nodes: ReactNode = [], componentType: FC<P> | FC<P>[]): ReactNode[] => {
const types = [componentType]
.flat()
.map(comp => typeof comp === 'function' && comp.name)
Expand All @@ -40,7 +42,7 @@ export const filterByType = (nodes: ReactNode = [], componentType: FC<any> | FC<
}

// Filters out nodes of certain component type(s)
export const excludeComponent = (nodes: ReactNode = [], componentType: FC<any> | FC<any>[]): ReactNode[] => {
export const excludeComponent = <P = AnyProps>(nodes: ReactNode = [], componentType: FC<P> | FC<P>[]): ReactNode[] => {
const types = [componentType]
.flat()
.map(comp => typeof comp === 'function' && comp.name)
Expand Down
4 changes: 2 additions & 2 deletions src/ebay-button/__tests__/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ export const Default = () => (
<p>
<EbayButton
onClick={action('clicked')}
onEscape={action('escape pressed')}
onFocus={(e) => action('focus')(e)}
onEscape={e => action('escape pressed')(e)}
onFocus={e => action('focus')(e)}
onBlur={action('blur')}
onKeyDown={action('key down')}
>
Expand Down
2 changes: 1 addition & 1 deletion src/ebay-button/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export type EbayButtonProps = {
split?: Split;
transparent?: boolean;
onClick?: (e: MouseEvent) => void;
onEscape?: EbayKeyboardEventHandler<HTMLButtonElement & HTMLAnchorElement>;
onEscape?: EbayKeyboardEventHandler<HTMLButtonElement | HTMLAnchorElement>;
forwardedRef?: RefObject<HTMLAnchorElement & HTMLButtonElement>;
borderless?: boolean;
fixedHeight?: boolean;
Expand Down
4 changes: 2 additions & 2 deletions src/ebay-fake-menu-button/menu-button.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { cloneElement, ComponentProps, FC, isValidElement, useEffect, useRef, useState } from 'react'
import classnames from 'classnames'

import { filterByType, findComponent } from '../common/component-utils'
import { AnyProps, filterByType, findComponent } from '../common/component-utils'
import { handleEscapeKeydown } from '../common/event-utils'
import { EbayKeyboardEventHandler, EbayMouseEventHandler } from '../common/event-utils/types'
import { randomId } from '../common/random-id'
Expand Down Expand Up @@ -56,7 +56,7 @@ const EbayMenuButton: FC<Props> = ({

const icon = findComponent(children, EbayIcon)
const label = findComponent(children, EbayFakeMenuButtonLabel) || (icon ? <span>{text}</span> : text)
const menuItems = filterByType(children, [EbayFakeMenuButtonItem, EbayFakeMenuButtonSeparator])
const menuItems = filterByType<AnyProps>(children, [EbayFakeMenuButtonItem, EbayFakeMenuButtonSeparator])

useEffect(() => {
const handleBackgroundClick = (e: React.MouseEvent) => {
Expand Down
4 changes: 2 additions & 2 deletions src/ebay-menu-button/menu-button-separator.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { ComponentProps, FC } from 'react'
import classNames from 'classnames'

type Props = ComponentProps<'hr'>
export type EbayMenuButtonSeparatorProps = ComponentProps<'hr'>

const EbayMenuButtonSeparator: FC<Props> = ({
const EbayMenuButtonSeparator: FC<EbayMenuButtonSeparatorProps> = ({
className,
...rest
}) => (
Expand Down
4 changes: 2 additions & 2 deletions src/ebay-menu-button/menu-button.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { cloneElement, ComponentProps, FC, isValidElement, useEffect, useRef, useState } from 'react'
import classnames from 'classnames'
import { elementProps, filterByType, findComponent } from '../common/component-utils'
import { AnyProps, elementProps, filterByType, findComponent } from '../common/component-utils'
import { handleEscapeKeydown } from '../common/event-utils'
import { randomId } from '../common/random-id'

Expand Down Expand Up @@ -62,7 +62,7 @@ const EbayMenuButton: FC<Props> = ({
const buttonRef = useRef(null)
const menuRef = useRef()

const menuItems = filterByType(children, [EbayMenuButtonItem, EbayMenuButtonSeparator])
const menuItems = filterByType<AnyProps>(children, [EbayMenuButtonItem, EbayMenuButtonSeparator])
const defaultIndexes = menuItems.map(item => Boolean(elementProps(item).checked))
const [checkedIndexes, setCheckedIndexes] = useState<boolean[]>(defaultIndexes)

Expand Down
6 changes: 3 additions & 3 deletions src/ebay-pagination/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { default as EbayPagination } from './pagination'
export { default as EbayPaginationItem } from './pagination-item'
export { PaginationVariant } from './types'
export { default as EbayPagination, PaginationProps } from './pagination'
export { default as EbayPaginationItem, PaginationItemProps, PaginationItemType } from './pagination-item'
export { PaginationVariant, ItemState } from './types'
8 changes: 3 additions & 5 deletions src/ebay-pagination/pagination.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, {
Children, ComponentProps, FC, ReactElement,
MouseEvent, KeyboardEvent,
cloneElement, useEffect, useRef, useState, createRef, isValidElement
} from 'react'
import {
Expand All @@ -11,10 +10,9 @@ import classNames from 'classnames'
import { debounce } from '../common/debounce'
import { calcPageState, getMaxWidth } from './helpers'
import { elementProps, filterBy } from '../common/component-utils'
import { PaginationItemType } from './pagination-item'
import { ItemState, PaginationVariant } from './types'
import { EbayIcon } from '../ebay-icon'
import { EbayEventHandler } from '../common/event-utils/types'
import { PaginationItemProps, PaginationItemType, ItemState, PaginationVariant } from './index'

export type PaginationProps = Omit<ComponentProps<'nav'>, 'onSelect'> & {
id?: string;
Expand Down Expand Up @@ -47,7 +45,7 @@ const EbayPagination: FC<PaginationProps> = ({
childPageRefs.current = Children.map(children, createRef)
const totalPages = filterBy(
children,
child => [undefined, 'page'].includes(elementProps(child).type)
child => [undefined, 'page'].includes(elementProps<PaginationItemProps>(child).type)
).length
const itemWidthRef = useRef<number>(0)
const arrowWidthRef = useRef<number>(0)
Expand Down Expand Up @@ -104,7 +102,7 @@ const EbayPagination: FC<PaginationProps> = ({
const lastDot = page.lastIndexOf('dots')

return Children.map(children, (item, index) => {
const { type = 'page', current, disabled, href, children: text } = elementProps(item)
const { type = 'page', current, disabled, href, children: text } = elementProps<PaginationItemProps>(item)
const isDot = page[index] === 'dots'
const key = `${id}-item-${index}`
const hide = page[index] === 'hidden'
Expand Down
6 changes: 3 additions & 3 deletions src/ebay-split-button/split-button.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { FC } from 'react'
import { excludeComponent, filterByType } from '../common/component-utils'
import { AnyProps, excludeComponent, filterByType } from '../common/component-utils'
import { EbayButton } from '../ebay-button'
import { EbayMenuButton, EbayMenuButtonItem, EbayMenuButtonSeparator } from '../ebay-menu-button'
import { Props } from './types'
Expand All @@ -18,8 +18,8 @@ const EbaySplitButton: FC<Props> = ({
...rest
}) => {
const menuItemComponents = [EbayMenuButtonItem, EbayMenuButtonSeparator]
const buttonLabel = excludeComponent(children, menuItemComponents)[0]
const menuItems = filterByType(children, menuItemComponents)
const buttonLabel = excludeComponent<AnyProps>(children, menuItemComponents)[0]
const menuItems = filterByType<AnyProps>(children, menuItemComponents)

return (
<span className="split-button">
Expand Down
6 changes: 3 additions & 3 deletions src/ebay-tourtip/ebay-tourtip.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { CSSProperties, FC, useRef } from 'react'
import { elementProps, findComponent } from '../common/component-utils'
import { AnyProps, elementProps, findComponent } from '../common/component-utils'
import {
Tooltip,
TooltipHost,
Expand Down Expand Up @@ -45,7 +45,7 @@ const EbayTourtip:FC<TourtipProps> = ({
if (!content) {
throw new Error(`EbayTourtip: Please use a EbayTourtipContent that defines the content of the tourtip`)
}
const { children: contentChildren, contentProps } = elementProps(content)
const { children: contentChildren, contentProps = {} } = elementProps(content)
const host = findComponent(children, EbayTourtipHost)
if (!host) {
throw new Error(`EbayTourtip: Please use a EbayTourtipHost that defines the host of the tourtip`)
Expand All @@ -67,7 +67,7 @@ const EbayTourtip:FC<TourtipProps> = ({
aria-label={ariaLabel}
aria-expanded={isExpanded} />
<TooltipContent
{...contentProps}
{...contentProps as AnyProps}
a11yCloseText={a11yCloseText}
onClose={collapseTooltip}
pointer={pointer}
Expand Down

0 comments on commit b83bb75

Please sign in to comment.