Skip to content

Commit

Permalink
[#285] fix 10 errors
Browse files Browse the repository at this point in the history
  • Loading branch information
darkwebdev committed Nov 16, 2023
1 parent 4d9457f commit 55d1520
Show file tree
Hide file tree
Showing 24 changed files with 100 additions and 95 deletions.
35 changes: 18 additions & 17 deletions src/common/component-utils/utils.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
import { Children, FC, ReactElement, ReactNode } from 'react'
import { Children, FC, isValidElement, JSXElementConstructor, ReactNode } from 'react'
import './array.polyfill.flat' // for Mobile Safari 11

export function findComponent(nodes: ReactNode = [], componentType: FC): ReactElement | undefined {
const elements = Children.toArray(nodes) as ReactElement[]
return elements.find(({ type }) => type === componentType) || null
}
export const findComponent = (nodes: ReactNode = [], componentType: FC<any>): ReactNode | undefined =>
Children.toArray(nodes).find(child =>
isValidElement(child) && child.type === componentType) || null

export function excludeComponent(nodes: ReactNode = [], componentType: FC): ReactElement[] {
const elements = Children.toArray(nodes) as ReactElement[]
return elements.filter(({ type }) => type !== componentType)
}
export const excludeComponent = (nodes: ReactNode = [], componentType: FC<any>): ReactNode[] =>
Children.toArray(nodes).filter(child =>
isValidElement(child) && child.type !== componentType)

export function filterByType(nodes: ReactNode = [], componentType: FC | FC[]): ReactElement[] {
const elements = Children.toArray(nodes) as ReactElement[]
const types = [componentType].flat()
return elements.filter(({ type }) => types.includes(type as any))
export const filterByType = (nodes: ReactNode = [], componentType: FC<any> | FC<any>[]): ReactNode[] => {
const types = [componentType.toString()].flat()
return Children
.toArray(nodes)
.filter(child => isValidElement(child) && types.includes(child.type as string))
}

export function filterBy(nodes: ReactNode = [], predicate: (el: ReactElement) => boolean): ReactElement[] {
const elements = Children.toArray(nodes) as ReactElement[]
return elements.filter(predicate)
}
export const filterBy = (nodes: ReactNode = [], predicate: (el: ReactNode) => boolean): ReactNode[] =>
Children.toArray(nodes).filter(predicate)

export const elementProps = (node: ReactNode): Record<string, any> => isValidElement(node) ? node.props : {}
export const elementType = (node: ReactNode): string | JSXElementConstructor<any> | null =>
isValidElement(node) ? node.type : null
4 changes: 2 additions & 2 deletions src/common/tooltip-utils/tooltip-content.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { FC, CSSProperties, ReactNode } from 'react'
import { EbayIcon } from '../../ebay-icon'
import { excludeComponent, findComponent } from '../component-utils'
import { elementProps, excludeComponent, findComponent } from '../component-utils'
import { PointerDirection, TooltipType } from './types'
import { DEFAULT_POINTER_DIRECTION, POINTER_STYLES, TYPE_ROLES } from './constants'
import TooltipCloseButton from './tooltip-close-button'
Expand Down Expand Up @@ -43,7 +43,7 @@ const TooltipContent: FC<TooltipContentProps> = ({
<span className={`${type}__content`}>{allChildrenExceptFooter}</span>
{showCloseButton ? (
<button
{...closeButton?.props}
{...elementProps(closeButton)}
className={`icon-btn icon-btn--transparent ${type}__close`}
type="button"
aria-label={a11yCloseText}
Expand Down
17 changes: 10 additions & 7 deletions src/common/tooltip-utils/tooltip.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { cloneElement, ComponentProps, FC, RefObject } from 'react'
import React, { cloneElement, ComponentProps, FC, isValidElement, RefObject } from 'react'
import classNames from 'classnames'
import { withForwardRef } from '../component-utils/forwardRef'
import { findComponent, excludeComponent } from '../component-utils'
Expand Down Expand Up @@ -26,12 +26,15 @@ const Tooltip: FC<TooltipProps> = ({
throw new Error(`Tooltip: Please use a TooltipHost that defines the host of the tooltip`)
}

const host = cloneElement(originalHostComponent, {
className: `${type}__host`,
'aria-expanded': isExpanded,
'aria-describedby': content?.props?.id,
...originalHostComponent.props
})
const host =
isValidElement(content) &&
isValidElement(originalHostComponent) &&
cloneElement(originalHostComponent, {
className: `${type}__host`,
'aria-expanded': isExpanded,
'aria-describedby': content?.props?.id,
...originalHostComponent.props
})

return (
<span
Expand Down
7 changes: 4 additions & 3 deletions src/ebay-breadcrumbs/breadcrumbs.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { Children, cloneElement, ComponentProps, FC, isValidElement, ReactElement, ReactNode } from 'react'
import React, { Children, cloneElement, ComponentProps, FC, isValidElement, ReactNode } from 'react'
import classNames from 'classnames'
import { EbayEventHandler } from '../common/event-utils/types'
import { elementProps } from '../common/component-utils'

type BreadcrumbProps = Omit<ComponentProps<'div'>, 'onSelect'> & {
/**
Expand Down Expand Up @@ -28,7 +29,7 @@ const Breadcrumbs: FC<BreadcrumbProps> = ({
const headingId = `${id}-breadcrumbs-heading`
const lastItemIndex = Children.count(breadcrumbItems) - 1
const A11yHeadingTag = a11yHeadingTag
const anyLink = Children.toArray(breadcrumbItems).some(item => isValidElement(item) && item.props.href)
const anyLink = Children.toArray(breadcrumbItems).some(item => elementProps(item).href)
const tag = anyLink ? 'a' : 'button'

return (
Expand All @@ -42,7 +43,7 @@ const Breadcrumbs: FC<BreadcrumbProps> = ({
<ul>
{Children.map(breadcrumbItems, (item, index) => {
const isLastItem = index === lastItemIndex
const { href, children } = isValidElement(item) && item.props
const { href, children } = elementProps(item)
const itemProps = {
tag,
isLastItem,
Expand Down
4 changes: 2 additions & 2 deletions src/ebay-checkbox/checkbox.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { ChangeEvent, cloneElement, ComponentProps, FC, FocusEvent, KeyboardEvent, useState } from 'react'
import React, { ChangeEvent, cloneElement, ComponentProps, FC, FocusEvent, isValidElement, KeyboardEvent, useState } from 'react'
import classNames from 'classnames'
import { EbayIcon } from '../ebay-icon'
import { EbayLabel, EbayLabelProps } from '../ebay-field'
Expand Down Expand Up @@ -75,7 +75,7 @@ const EbayCheckbox: FC<InputProps & EbayCheckboxProps> = ({
</span>
</span>
{ebayLabel ?
cloneElement<EbayLabelProps>(ebayLabel, {
isValidElement(ebayLabel) && cloneElement<EbayLabelProps>(ebayLabel, {
...ebayLabel.props,
position: 'end',
htmlFor: id
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,4 +1,4 @@
import React, { cloneElement, ComponentProps, FC, useEffect, useRef, useState } from 'react'
import React, { cloneElement, ComponentProps, FC, isValidElement, useEffect, useRef, useState } from 'react'
import classnames from 'classnames'

import { filterByType, findComponent } from '../common/component-utils'
Expand Down Expand Up @@ -128,7 +128,7 @@ const EbayMenuButton: FC<Props> = ({
onSelect={onSelect}
>
{menuItems.map((item, i) =>
cloneElement<EbayFakeMenuItemProps>(item, {
isValidElement(item) && cloneElement<EbayFakeMenuItemProps>(item, {
...item.props,
onMouseDown: (e) => {
onMouseDown(e, { index: i })
Expand Down
12 changes: 5 additions & 7 deletions src/ebay-fake-menu/menu.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import React, {
Children, cloneElement,
ComponentProps, FC, ReactElement
} from 'react'
import React, { Children, cloneElement, ComponentProps, FC, isValidElement } from 'react'
import classNames from 'classnames'
import { EbayFakeMenuItemProps } from './index'
import { EbayKeyboardEventHandler, EbayMouseEventHandler } from '../common/event-utils/types'
import { elementProps } from '../common/component-utils'

type SpanProps = Omit<ComponentProps<'div'>, 'onKeyDown' | 'onSelect'>
type Props = SpanProps & {
Expand All @@ -27,16 +25,16 @@ const EbayFakeMenu: FC<Props> = ({
return (
<div {...rest} className={classNames(className, 'fake-menu')}>
<ul className="fake-menu__items" tabIndex={-1}>
{childrenArray.map((child: ReactElement, i) => {
{childrenArray.map((child, i) => {
const {
current,
onClick = () => {},
...itemRest
}: EbayFakeMenuItemProps = child.props
}: EbayFakeMenuItemProps = elementProps(child)

return (
<li key={i}>
{cloneElement(child, {
{isValidElement(child) && cloneElement(child, {
...itemRest,
'aria-current': current ? defaultAriaCurrent : undefined,
onClick: e => {
Expand Down
4 changes: 2 additions & 2 deletions src/ebay-fake-tabs/fake-tabs.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { cloneElement, ComponentProps, FC } from 'react'
import React, { cloneElement, ComponentProps, FC, isValidElement } from 'react'
import classNames from 'classnames'

import { excludeComponent, filterByType } from '../common/component-utils'
Expand All @@ -18,7 +18,7 @@ const EbayFakeTabs: FC<FakeTabsProps> = ({
}) => {
const ariaCurrent = tabMatchesCurrentUrl === false ? 'true' : 'page'
const tabHeadings = filterByType(children, Tab).map((item, i) =>
cloneElement(item, {
isValidElement(item) && cloneElement(item, {
...item.props,
ariaCurrent: selectedIndex === i ? ariaCurrent : null
}))
Expand Down
2 changes: 1 addition & 1 deletion src/ebay-infotip/ebay-infotip-host.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { EbayIcon, Icon } from '../ebay-icon'
import { withForwardRef } from '../common/component-utils/forwardRef'
import { Variant } from './types'

type InfotipHostProps = ComponentProps<'button'> & {
export type InfotipHostProps = ComponentProps<'button'> & {
icon?: Icon;
forwardedRef?: RefObject<HTMLAnchorElement & HTMLButtonElement>;
variant?: Variant;
Expand Down
13 changes: 6 additions & 7 deletions src/ebay-infotip/ebay-infotip.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, { cloneElement, createElement, CSSProperties, FC, useRef, ReactNode } from 'react'
import React, { cloneElement, createElement, CSSProperties, FC, useRef, ReactNode, isValidElement } from 'react'
import classNames from 'classnames'
import { findComponent } from '../common/component-utils'
import { elementProps, findComponent } from '../common/component-utils'
import { Tooltip, TooltipHost, TooltipContent, PointerDirection, useTooltip } from '../common/tooltip-utils'
import { EbayDrawerDialog } from '../ebay-drawer-dialog'
import { EbayDialogHeader } from '../ebay-dialog-base'
import EbayInfotipHost from './ebay-infotip-host'
import EbayInfotipHost, { InfotipHostProps } from './ebay-infotip-host'
import { Icon } from '../ebay-icon'
import { Variant } from './types'
import { EbayInfotipHeading, EbayInfotipContent } from './index'
Expand Down Expand Up @@ -67,7 +67,7 @@ const EbayInfotip: FC<InfotipProps> = ({
throw new Error(`EbayInfotip: Please use a EbayInfotipContent that defines the content of the infotip`)
}

const { children: contentChildren, ...contentProps } = content.props
const { children: contentChildren, ...contentProps } = elementProps(content)

return (
<>
Expand All @@ -78,15 +78,15 @@ const EbayInfotip: FC<InfotipProps> = ({
className={classNames(className, { 'dialog--mini': isModal })}
ref={containerRef}>
<TooltipHost>
{cloneElement(button, {
{isValidElement(button) && cloneElement<InfotipHostProps>(button, {
ref: buttonRef,
onClick: toggleTooltip,
disabled,
variant,
'aria-label': ariaLabel,
'aria-expanded': isExpanded,
icon,
...button.props
...elementProps(button)
})}
</TooltipHost>
{!isModal && (
Expand All @@ -109,7 +109,6 @@ const EbayInfotip: FC<InfotipProps> = ({
{...contentProps}
open={isExpanded}
onClose={collapseTooltip}
mode="mini"
a11yCloseText={a11yCloseText}
className="dialog--mini__overlay"
a11yMaximizeText={a11yMaximizeText}
Expand Down
4 changes: 2 additions & 2 deletions src/ebay-inline-notice/inline-notice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { FC, useEffect, ReactNode } from 'react'
import classNames from 'classnames'
import { EbayNoticeContent } from '../ebay-notice-base/components/ebay-notice-content'
import NoticeContent from '../common/notice-utils/notice-content'
import { findComponent } from '../common/component-utils'
import { elementProps, findComponent } from '../common/component-utils'
import { EbayIcon, Icon } from '../ebay-icon'
import { NoticeStatus } from './types'

Expand Down Expand Up @@ -53,7 +53,7 @@ const EbayInlineNotice: FC<Props> = ({
</span>
) : null}
<NoticeContent
{...content.props}
{...elementProps(content)}
type="inline" />
</div>
)
Expand Down
2 changes: 1 addition & 1 deletion src/ebay-listbox-button/listbox-button-option.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { ComponentProps, FC, MouseEvent, RefObject } from 'react'
import classNames from 'classnames'
import { EbayIcon } from '../ebay-icon'

type EbayListboxButtonOptionProps = ComponentProps<'input'> & {
export type EbayListboxButtonOptionProps = ComponentProps<'input'> & {
selected?: boolean;
index?: number;
onClick?: (event: MouseEvent<HTMLDivElement>, value: any, index: number) => void;
Expand Down
14 changes: 7 additions & 7 deletions src/ebay-listbox-button/listbox-button.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, {
Children, cloneElement, useEffect, useRef, useState,
ComponentProps, FC, KeyboardEvent, ReactElement, useCallback
ComponentProps, FC, KeyboardEvent, ReactElement, useCallback, isValidElement
} from 'react'
import classNames from 'classnames'
import { EbayIcon } from '../ebay-icon'
import { EbayChangeEventHandler, Key } from '../common/event-utils/types'
import { filterByType } from '../common/component-utils'
import EbayListboxButtonOption from './listbox-button-option'
import { elementProps, filterByType } from '../common/component-utils'
import EbayListboxButtonOption, { EbayListboxButtonOptionProps } from './listbox-button-option'

export type ChangeEventProps = {
index: number;
Expand Down Expand Up @@ -57,8 +57,8 @@ const ListboxButton: FC<EbayListboxButtonProps> = ({
EbayListboxButtonOption that defines the options of the listbox`)
}
const getInitialSelectedOption = (): { option: any, index: number } => {
const selectedIndex = selected !== undefined ? selected : listBoxButtonOptions.findIndex(({ props }) =>
value !== undefined && props.value === value)
const selectedIndex = selected !== undefined ? selected : listBoxButtonOptions.findIndex(option =>
value !== undefined && elementProps(option).value === value)
const index = selectedIndex > -1 || floatingLabel ? selectedIndex : undefined
return {
option: listBoxButtonOptions[index],
Expand Down Expand Up @@ -229,15 +229,15 @@ const ListboxButton: FC<EbayListboxButtonProps> = ({
// We want to mimic the select box behavior, so we take the onSelect that passed
// at the parent level and use it for the OnClick on the list box since it is a fake dropdown
const updateListBoxButtonOptions = listBoxButtonOptions
.map((child, index) => cloneElement(child, {
.map((child, index) => isValidElement(child) && cloneElement<EbayListboxButtonOptionProps>(child, {
index,
key: index,
selected: selectedOption && child.props.value === selectedOption.props.value,
onClick: (e) => onOptionsSelect(e, index),
innerRef: optionNode => !optionNode
? optionsByIndexRef.current.delete(index)
: optionsByIndexRef.current.set(index, optionNode)
}))
} as unknown))
const wrapperClassName = classNames('listbox-button', className, { 'listbox-button--fluid': fluid })
const buttonClassName = classNames('btn btn--form', {
'btn--borderless': borderless,
Expand Down
8 changes: 4 additions & 4 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, useEffect, useRef, useState } from 'react'
import React, { cloneElement, ComponentProps, FC, isValidElement, useEffect, useRef, useState } from 'react'
import classnames from 'classnames'
import { filterByType, findComponent } from '../common/component-utils'
import { elementProps, filterByType, findComponent } from '../common/component-utils'
import { handleEscapeKeydown } from '../common/event-utils'
import { randomId } from '../common/random-id'

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

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

const menuButtonLabel = findComponent(children, EbayMenuButtonLabel)
Expand Down Expand Up @@ -167,7 +167,7 @@ const EbayMenuButton: FC<Props> = ({
onSelect={onSelect}
>
{menuItems.map((item, i) =>
cloneElement(item, {
isValidElement(item) && cloneElement(item, {
...item.props,
className: classnames(item.props.className, 'menu-button__item'),
key: i,
Expand Down
6 changes: 3 additions & 3 deletions src/ebay-page-notice/page-notice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import React, {
KeyboardEventHandler,
MouseEvent,
MouseEventHandler,
ReactElement,
useState
} from 'react'
import NoticeContent from '../common/notice-utils/notice-content'
import { EbayNoticeContent } from '../ebay-notice-base/components/ebay-notice-content'
import { EbayIcon, Icon } from '../ebay-icon'
import { EbayPageNoticeFooter } from './index'
import { elementProps, elementType } from '../common/component-utils'

export type PageNoticeStatus = 'general' | 'attention' | 'confirmation' | 'information'
export type Props = ComponentProps<'section'> & {
Expand All @@ -32,7 +32,7 @@ const EbayPageNotice: FC<Props> = ({
}) => {
const [dismissed, setDismissed] = useState(false)
const childrenArray = React.Children.toArray(children)
const content = childrenArray.find((child: ReactElement) => child.type === EbayNoticeContent) as ReactElement
const content = childrenArray.find(child => elementType(child) === EbayNoticeContent)

if (!content) {
throw new Error(`EbayPageNotice: Please use a EbayNoticeContent that defines the content of the notice`)
Expand All @@ -58,7 +58,7 @@ const EbayPageNotice: FC<Props> = ({
/>
</div>
) : null}
<NoticeContent {...content.props} type="page" />
<NoticeContent {...elementProps(content)} type="page" />
{children}
{a11yDismissText && (
<EbayPageNoticeFooter>
Expand Down
2 changes: 1 addition & 1 deletion src/ebay-pagination/__tests__/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ export const InsideADialog = () => {
const [open, setOpen] = useState(false)
const handlePrev = () => setActiveIndex(Math.max(activeIndex - 1, 0))
const handleNext = () => setActiveIndex(Math.min(activeIndex + 1, numOfItems))
const handleSelect = (e, { index }) => setActiveIndex(index)
const handleSelect = (e, props) => setActiveIndex(props.index)

return (
<>
Expand Down

0 comments on commit 55d1520

Please sign in to comment.