Skip to content

Commit

Permalink
Merge branch 'main' into add-floating-label-opaque-textarea
Browse files Browse the repository at this point in the history
  • Loading branch information
HenriqueLimas authored Sep 20, 2023
2 parents 4b4e8b2 + cef3c78 commit 6fc2af4
Show file tree
Hide file tree
Showing 142 changed files with 5,557 additions and 4,655 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ebay/ui-core-react",
"version": "4.2.6",
"version": "5.0.0",
"description": "Skin components build off React",
"publishConfig": {
"registry": "https://registry.npmjs.org"
Expand Down
31 changes: 20 additions & 11 deletions src/common/event-utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Based on https://github.com/eBay/ebayui-core/edit/master/src/common/event-utils/index.js
*/

import React from 'react'
import { Key } from './types'

type Callback = () => void
Expand All @@ -12,41 +13,49 @@ type Callback = () => void
* @param {KeyboardEvent} e
* @param {Function} callback
*/
function handleKeydown(keyList: Key[], e: KeyboardEvent, callback: Callback = () => {}): void {
function handleKeydown(keyList: Key[], e: React.KeyboardEvent, callback: Callback = () => {}): void {
if (keyList.includes(e.key as Key)) {
callback()
}
}

// inverse of found keys
function handleNotKeydown(keyList: Key[], e: KeyboardEvent, callback: Callback = () => {}): void {
function handleNotKeydown(keyList: Key[], e: React.KeyboardEvent, callback: Callback = () => {}): void {
if (!keyList.includes(e.key as Key)) {
callback()
}
}

export function handleEnterKeydown(e: KeyboardEvent, callback: Callback): void {
handleKeydown(['Enter'], e, callback)
export function handleEnterKeydown(e: React.KeyboardEvent, callback: Callback): void {
if (e.key === 'Enter') {
callback()
}
}

export function handleActionKeydown(e: React.KeyboardEvent, callback: Callback): void {
if (isActionKey(e.key as Key)) {
callback()
}
}

export function handleActionKeydown(e: KeyboardEvent, callback: Callback): void {
handleKeydown([' ', 'Enter'], e, callback)
export function isActionKey(key: Key): boolean {
return [' ', 'Enter'].includes(key)
}

export function handleEscapeKeydown(e: KeyboardEvent, callback: Callback): void {
export function handleEscapeKeydown(e: React.KeyboardEvent, callback: Callback): void {
handleKeydown(['Esc', 'Escape'], e, callback)
}

export function handleUpDownArrowsKeydown(e: KeyboardEvent, callback: Callback): void {
export function handleUpDownArrowsKeydown(e: React.KeyboardEvent, callback: Callback): void {
handleKeydown(['Up', 'ArrowUp', 'Down', 'ArrowDown'], e, callback)
}

export function handleLeftRightArrowsKeydown(e: KeyboardEvent, callback: Callback): void {
export function handleLeftRightArrowsKeydown(e: React.KeyboardEvent, callback: Callback): void {
handleKeydown(['Left', 'ArrowLeft', 'Right', 'ArrowRight'], e, callback)
}

// only fire for character input, not modifier/meta keys (enter, escape, backspace, tab, etc.)
export function handleTextInput(e: KeyboardEvent, callback: Callback): void {
export function handleTextInput(e: React.KeyboardEvent, callback: Callback): void {
const keyList: Key[] = [
// Edge
'Esc',
Expand All @@ -72,7 +81,7 @@ export function handleTextInput(e: KeyboardEvent, callback: Callback): void {
handleNotKeydown(keyList, e, callback)
}

export function preventDefaultIfHijax(e: KeyboardEvent, hijax: boolean): void {
export function preventDefaultIfHijax(e: React.KeyboardEvent, hijax: boolean): void {
if (hijax) {
e.preventDefault()
}
Expand Down
26 changes: 26 additions & 0 deletions src/common/event-utils/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ChangeEvent, KeyboardEvent, MouseEvent, FocusEvent, SyntheticEvent } from 'react'

type ModifierKeys = 'Alt' | 'AltGraph' | 'Control' | 'Shift' | 'CapsLock' | 'Meta'
// | 'Fn' | 'FnLock' | 'Hyper' | 'NumLock' | 'ScrollLock' | 'Super' | 'Symbol' | 'SymbolLock'
type NavigationKeys = 'ArrowDown' | 'ArrowLeft' | 'ArrowRight' | 'ArrowUp' | 'Enter' | 'Tab' | ' ' | 'Escape'
Expand All @@ -10,3 +12,27 @@ type NavigationKeysEdge = 'Down' | 'Left' | 'Right' | 'Up' | 'Esc'

export type Key = ModifierKeys | NavigationKeys | NavigationKeysEdge

type BaseEventHandler<E extends SyntheticEvent<any>, P> = (event: E, props?: P) => void;

export type EbayEventHandler<ElementType = Element, PropsObject = Record<string, any>> =
BaseEventHandler<SyntheticEvent<ElementType>, PropsObject>;
export type EbayMouseEventHandler<ElementType = Element, PropsObject = Record<string, any>> =
BaseEventHandler<MouseEvent<ElementType>, PropsObject>;
export type EbayKeyboardEventHandler<ElementType = Element, PropsObject = Record<string, any>> =
BaseEventHandler<KeyboardEvent<ElementType>, PropsObject>;
export type EbayChangeEventHandler<ElementType = Element, PropsObject = Record<string, any>> =
BaseEventHandler<ChangeEvent<ElementType>, PropsObject>;
export type EbayFocusEventHandler<ElementType = Element, PropsObject = Record<string, any>> =
BaseEventHandler<FocusEvent<ElementType>, PropsObject>;
/*
type ClipboardEventHandler<T = Element> = EventHandler<ClipboardEvent<T>>;
type CompositionEventHandler<T = Element> = EventHandler<CompositionEvent<T>>;
type DragEventHandler<T = Element> = EventHandler<DragEvent<T>>;
type FormEventHandler<T = Element> = EventHandler<FormEvent<T>>;
type TouchEventHandler<T = Element> = EventHandler<TouchEvent<T>>;
type PointerEventHandler<T = Element> = EventHandler<PointerEvent<T>>;
type UIEventHandler<T = Element> = EventHandler<UIEvent<T>>;
type WheelEventHandler<T = Element> = EventHandler<WheelEvent<T>>;
type AnimationEventHandler<T = Element> = EventHandler<AnimationEvent<T>>;
type TransitionEventHandler<T = Element> = EventHandler<TransitionEvent<T>>;
*/
5 changes: 4 additions & 1 deletion src/common/floating-label-utils/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type FloatingLabelHookProps = {
placeholder?: string;
invalid?: boolean;
opaqueLabel?: boolean;
onMount?: () => void;
}

type FloatingLabelHookReturn = {
Expand Down Expand Up @@ -76,7 +77,8 @@ export function useFloatingLabel({
inputValue,
placeholder,
invalid,
opaqueLabel
opaqueLabel,
onMount = () => {}
} : FloatingLabelHookProps): FloatingLabelHookReturn {
const _internalInputRef = useRef(null)
const inputRef = () => ref || _internalInputRef
Expand Down Expand Up @@ -105,6 +107,7 @@ export function useFloatingLabel({
}
selectFirstOptionText.current = getPlaceholder(inputRef()?.current)
setPlaceholder(inputRef()?.current, ``)
onMount()
}, [])

useEffect(() => {
Expand Down
5 changes: 3 additions & 2 deletions src/ebay-alert-dialog/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ Name | Type | Stateful | Required | Description
## Events

Event | Data | Description
--- | --- | ---
`onConfirm` | | triggered when confirm button is clicked
--- |------| ---
`onOpen` | () | triggered when dialog is opened
`onConfirm` | () | triggered when confirm button is clicked

## EbayDialogHeader
Will render a header content for the dialog. Will always render the header element even if this is not present
Expand Down
54 changes: 31 additions & 23 deletions src/ebay-alert-dialog/__tests__/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,49 @@
import React from 'react'
import requireContext from 'node-require-context'
import { fireEvent, render, RenderResult } from '@testing-library/react'
import { screen, fireEvent, render, RenderResult } from '@testing-library/react'
import { EbayAlertDialog } from '../index';
import { initStoryshots } from '../../../config/jest/storyshots'
import { EbayDialogHeader } from '../../ebay-dialog-base'

jest.mock('../../common/random-id', () => ({ randomId: () => 'abc123' }))

describe('<EbayAlertDialog>', () => {
let wrapper: RenderResult
const closeDrawerHandler = jest.fn()
const closeSpy = jest.fn()
const openSpy = jest.fn()
const openDialog = () =>
render(
<EbayAlertDialog
confirmText="Confirm"
open
onOpen={openSpy}
onConfirm={closeSpy}
a11yCloseText="Close"
>
<EbayDialogHeader>Heading</EbayDialogHeader>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</p>
<p><a href="http://www.ebay.com">www.ebay.com</a></p>
<input placeholder="Enter a value" />
</EbayAlertDialog>
)

beforeEach(() => {
wrapper = render(
<EbayAlertDialog
confirmText="Confirm"
open
onConfirm={closeDrawerHandler}>
<EbayDialogHeader>Heading</EbayDialogHeader>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</p>
<p><a href="http://www.ebay.com">www.ebay.com</a></p>
<input placeholder="Enter a value" />
</EbayAlertDialog>
)
describe('<EbayAlertDialog>', () => {
it('should trigger onOpen when dialog appears', () => {
openDialog()
expect(openSpy).toBeCalled()
})

it('should have close button', () => {
expect(wrapper.getByText('Confirm')).toBeInTheDocument()
openDialog()
expect(screen.getByText('Confirm')).toBeInTheDocument()
})

it('should trigger onClose when close button is clicked', () => {
fireEvent.click(wrapper.getByText('Confirm'))
expect(closeDrawerHandler).toBeCalled()
openDialog()
fireEvent.click(screen.getByText('Confirm'))
expect(closeSpy).toBeCalled()
})
})

Expand Down
14 changes: 12 additions & 2 deletions src/ebay-alert-dialog/__tests__/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useState } from 'react'
import { EbayAlertDialog } from '../index';
import { EbayDialogHeader } from '../../ebay-dialog-base'
import { action } from '../../../.storybook/action'

const story: any = {
component: EbayAlertDialog,
Expand All @@ -22,7 +23,16 @@ export const _Default = () => {
Open Dialog
</button>
<p>Some outside content...</p>
<EbayAlertDialog open={open} onConfirm={close} confirmText="Confirm">
<EbayAlertDialog
open={open}
onOpen={() => action('onOpen')()}
onConfirm={() => {
action('onConfirm')()
close()
}}
confirmText="Confirm"
a11yCloseText="Close"
>
<EbayDialogHeader>Heading</EbayDialogHeader>
{textParagraph}
<p><a href="http://www.ebay.com">www.ebay.com</a></p>
Expand All @@ -40,7 +50,7 @@ export const _WithAnimation= () => {
Open Dialog
</button>
<p>Some outside content...</p>
<EbayAlertDialog open={open} onConfirm={close} confirmText="Confirm" animated>
<EbayAlertDialog open={open} onConfirm={close} confirmText="Confirm" animated a11yCloseText="Close">
<EbayDialogHeader>Heading</EbayDialogHeader>
{textParagraph}
<p><a href="http://www.ebay.com">www.ebay.com</a></p>
Expand Down
2 changes: 0 additions & 2 deletions src/ebay-alert-dialog/alert-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,12 @@ const classPrefix = 'alert-dialog'
export interface Props<T = any> extends DialogBaseProps<T> {
open?: boolean;
confirmText: string;
onOpen?: () => void;
onConfirm?: () => void;
}

const EbayAlertDialog: FC<Props> = ({
a11yCloseText = 'Close Dialog',
confirmText,
onOpen = () => {},
onConfirm = () => {},
...rest
}) => {
Expand Down
2 changes: 1 addition & 1 deletion src/ebay-breadcrumbs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Name | Type | Stateful | Description | Data
--- | --- | --- | --- | ---
`a11yHeadingText` | String | No | heading for breadcrumb which will be clipped (default: 'Page navigation')
`a11yHeadingTag` | String | No | heading tag for breadcrumb (default: `h2`)
`onSelect` | Function | No | click breadcrumb items | `{ originalEvent, el }`
`onSelect` | Function | No | click breadcrumb items | `(event: MouseEvent | KeyboardEvent)`

All other props will be applied to the main wrapper (`nav`) element.

Expand Down
9 changes: 6 additions & 3 deletions src/ebay-breadcrumbs/__tests__/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React from 'react'
import { render, fireEvent } from '@testing-library/react'
import { render } from '@testing-library/react'
import { initStoryshots } from '../../../config/jest/storyshots'

import { EbayBreadcrumbs, EbayBreadcrumbItem } from '../index'
import userEvent from '@testing-library/user-event'

describe('<EbayBreadcrumbs>', () => {
describe('on category click', () => {
Expand All @@ -13,9 +14,11 @@ describe('<EbayBreadcrumbs>', () => {
<EbayBreadcrumbItem>home</EbayBreadcrumbItem>
</EbayBreadcrumbs>
)
fireEvent.click(wrapper.getByRole('button'))
const button = wrapper.getByRole('button')
userEvent.click(button)

expect(spy).toBeCalled()
const syntheticEvent = expect.objectContaining( { target: null })
expect(spy).toBeCalledWith(syntheticEvent)
})
})

Expand Down
2 changes: 1 addition & 1 deletion src/ebay-breadcrumbs/__tests__/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { EbayBreadcrumbs, EbayBreadcrumbItem as Item } from '../index'

storiesOf('ebay-breadcrumb', module)
.add('default', () => (<>
<EbayBreadcrumbs onSelect={action('select')}>
<EbayBreadcrumbs onSelect={(e, { el }) => action('select')(e, { el })}>
<Item href="https://www.ebay.com/">eBay</Item>
<Item href="https://www.ebay.com/rpp/cell-phone-pda">Cell Phones, Smart Watches & Accessories</Item>
<Item href="https://www.ebay.com/b/Smart-Watch-Accessories/182064/bn_16565905">Smart Watch Accessories</Item>
Expand Down
7 changes: 4 additions & 3 deletions src/ebay-breadcrumbs/breadcrumbs.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React, { Children, cloneElement, ComponentProps, FC, ReactElement, ReactNode } from 'react'
import classNames from 'classnames'
import { EbayEventHandler } from '../common/event-utils/types'

type BreadcrumbProps = ComponentProps<'div'> & {
type BreadcrumbProps = Omit<ComponentProps<'div'>, 'onSelect'> & {
/**
* Breadcrumbs expects `<EbayBreadcrumbItem/>` as children.
* Other elements will not work.
Expand All @@ -12,7 +13,7 @@ type BreadcrumbProps = ComponentProps<'div'> & {
id?: string;
a11yHeadingTag?: keyof JSX.IntrinsicElements;
a11yHeadingText?: string;
onSelect?: (event: MouseEvent | KeyboardEvent, target: HTMLElement) => void;
onSelect?: EbayEventHandler<HTMLElement>;
}

const Breadcrumbs: FC<BreadcrumbProps> = ({
Expand Down Expand Up @@ -47,7 +48,7 @@ const Breadcrumbs: FC<BreadcrumbProps> = ({
isLastItem,
href,
children,
onClick: event => onSelect(event, event.target)
onClick: event => onSelect(event)
}

return cloneElement(item, itemProps)
Expand Down
8 changes: 4 additions & 4 deletions src/ebay-button/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Name | Type | Stateful | Required | Description | Data
`truncate` | Boolean | No | No | will truncate the text of the button onto a single line, and adds an ellipsis, when the button's text overflows
`borderless` | Boolean | No | No | shows button without border
`fixedHeight` | Boolean | No | No | fixes the height based on `size`
`onClick` | Function | - | No | click or action key pressed (`Space` / `Enter`)
`onEscape` | Function | - | No | `Esc`-key pressed
`onFocus` | Function | - | No | triggered on focus
`onBlur` | Function | - | No | triggered on blur
`onClick` | Function | - | No | click or action key pressed (`Space` / `Enter`) | `(event: MouseEvent | KeyboardEvent)`
`onEscape` | Function | - | No | `Esc`-key pressed | `(event: KeyboardEvent)`
`onFocus` | Function | - | No | triggered on focus | `(event: FocusEvent)`
`onBlur` | Function | - | No | triggered on blur | `(event: FocusEvent)`
Loading

0 comments on commit 6fc2af4

Please sign in to comment.