Skip to content

Commit

Permalink
Rewrite _commons to Typescript (#730)
Browse files Browse the repository at this point in the history
* Working with typescript

* Take two with combined refs

* ♻️ Rewrite code to avoid ts errors.

* ♻️ Get rid of ts lint error

* ♻️ Fix eslint error

* ♻️ Fix eslint error and warning

* ♻️ Change elements to fix ts error

* 🐛 Fix ts error

* ♻️ More specific type
  • Loading branch information
wenche authored and vnys committed Nov 13, 2020
1 parent 75c057f commit 03c35dd
Show file tree
Hide file tree
Showing 13 changed files with 85 additions and 65 deletions.
11 changes: 7 additions & 4 deletions libraries/core-react/src/Menu/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ export type MenuProps = {
focus?: FocusTarget
/** onClose handler */
onClose?: (e?: React.MouseEvent<ReactNode, MouseEvent>) => void
} & HTMLAttributes<HTMLDivElement>
} & HTMLAttributes<HTMLUListElement>

export const Menu = React.forwardRef<HTMLDivElement, MenuProps>(function Menu(
export const Menu = React.forwardRef<HTMLUListElement, MenuProps>(function Menu(
{ children, anchorEl, onClose: onCloseCallback, open = false, ...rest },
ref,
) {
const listRef = useRef<HTMLLIElement>(null)
const listRef = useRef<HTMLUListElement>(null)

const { setPosition, position, isPositioned, setOnClose, onClose } = useMenu()
useOutsideClick(listRef, () => {
Expand Down Expand Up @@ -100,7 +100,10 @@ export const Menu = React.forwardRef<HTMLDivElement, MenuProps>(function Menu(

return (
<StyledPaper {...paperProps} elevation="raised">
<MenuList {...menuProps} ref={useCombinedRefs(ref, listRef)}>
<MenuList
{...menuProps}
ref={useCombinedRefs<HTMLUListElement>(ref, listRef)}
>
{children}
</MenuList>
</StyledPaper>
Expand Down
5 changes: 4 additions & 1 deletion libraries/core-react/src/Menu/MenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,10 @@ export const MenuItem = React.memo(
return (
<ListItem
{...props}
ref={useCombinedRefs(ref, (el: HTMLElement) => isFocused && el.focus())}
ref={useCombinedRefs<HTMLLIElement>(
ref,
(el: HTMLLIElement) => isFocused && el.focus(),
)}
onFocus={() => toggleFocus(index)}
onClick={(e) => {
if (!disabled) {
Expand Down
4 changes: 2 additions & 2 deletions libraries/core-react/src/Search/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ export const Search = React.forwardRef<HTMLInputElement, SearchProps>(
}, [value, defaultValue])

const handleOnClick = () => {
const inputEl = inputRef.current as HTMLInputElement
const inputEl = inputRef.current
inputEl.focus()
}
const handleFocus = () => setState({ ...state, isFocused: true })
Expand All @@ -220,7 +220,7 @@ export const Search = React.forwardRef<HTMLInputElement, SearchProps>(
}

const handleOnDelete = () => {
const input = inputRef.current as HTMLInputElement
const input = inputRef.current
const clearedValue = ''
setReactInputValue(input, clearedValue)
setState({ ...state, isActive: false })
Expand Down
7 changes: 5 additions & 2 deletions libraries/core-react/src/Tabs/TabList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import React, {
useEffect,
ReactElement,
HTMLAttributes,
ButtonHTMLAttributes,
RefAttributes,
} from 'react'
import styled from 'styled-components'
import { useCombinedRefs } from '../_common/useCombinedRefs'
Expand Down Expand Up @@ -42,7 +44,8 @@ type TabListProps = {
type TabChild = {
disabled?: boolean
index?: number
} & JSX.IntrinsicElements['button'] &
} & ButtonHTMLAttributes<HTMLButtonElement> &
RefAttributes<HTMLButtonElement> &
ReactElement

const TabList = forwardRef<HTMLDivElement, TabListProps>(function TabsList(
Expand Down Expand Up @@ -77,7 +80,7 @@ const TabList = forwardRef<HTMLDivElement, TabListProps>(function TabsList(
(child: TabChild, index: number) => {
const tabRef =
index === activeTab
? useCombinedRefs(child.ref, selectedTabRef)
? useCombinedRefs<HTMLButtonElement>(child.ref, selectedTabRef)
: child.ref

return React.cloneElement(child, {
Expand Down
17 changes: 0 additions & 17 deletions libraries/core-react/src/_common/hooks/useOutsideClick.js

This file was deleted.

20 changes: 20 additions & 0 deletions libraries/core-react/src/_common/hooks/useOutsideClick.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { useEffect, MutableRefObject } from 'react'

export const useOutsideClick = (
ref: MutableRefObject<HTMLElement>,
callback: () => void,
): void => {
const handleClick = (e: MouseEvent) => {
if (ref.current && !ref.current.contains(e.target as Node)) {
callback()
}
}

useEffect(() => {
document.addEventListener('click', handleClick)

return () => {
document.removeEventListener('click', handleClick)
}
})
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// @ts-nocheck
import * as templates from './templates'

export { setReactInputValue } from './setReactInputValue'
Expand Down
17 changes: 0 additions & 17 deletions libraries/core-react/src/_common/setReactInputValue.js

This file was deleted.

21 changes: 21 additions & 0 deletions libraries/core-react/src/_common/setReactInputValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Workaround
// React ignores 'dispathEvent' on input/textarea, see https://github.com/facebook/react/issues/10135
type ReactInternalHack = { _valueTracker?: { setValue: (a: string) => void } }

export const setReactInputValue = (
input: HTMLInputElement & ReactInternalHack,
value: string,
): void => {
const previousValue = input.value

input.value = value

const tracker = input._valueTracker

if (typeof tracker !== 'undefined') {
tracker.setValue(previousValue)
}

//'change' instead of 'input', see https://github.com/facebook/react/issues/11488#issuecomment-381590324
input.dispatchEvent(new Event('change', { bubbles: true }))
}
19 changes: 0 additions & 19 deletions libraries/core-react/src/_common/useCombinedRefs.js

This file was deleted.

21 changes: 21 additions & 0 deletions libraries/core-react/src/_common/useCombinedRefs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useRef, useEffect, MutableRefObject } from 'react'

type Ref<T> = MutableRefObject<T>
type Props<T, P> = T | ((a: P) => void)

export const useCombinedRefs = <T extends HTMLElement>(
...refs: Props<Ref<T>, T>[]
): Ref<T> => {
const targetRef = useRef<T>(null)
useEffect(() => {
refs.forEach((ref) => {
if (!ref) return
if (typeof ref === 'function') {
ref(targetRef.current)
} else {
ref.current = targetRef.current
}
})
}, [refs])
return targetRef
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// @ts-nocheck
import { useEffect, useState } from 'react'

export function useKeyPress(targetKey, onPressDown = () => {}) {
export function useKeyPress(
targetKey: number,
// eslint-disable-next-line @typescript-eslint/no-empty-function
onPressDown = () => {},
): boolean {
const [keyPressed, setKeyPressed] = useState(false)

function downHandler({ key }) {
Expand Down

0 comments on commit 03c35dd

Please sign in to comment.