Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

util typescript #1328

Merged
merged 21 commits into from Oct 20, 2020
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
32cf0b0
refactor(util): move to ts files
danethurber Oct 12, 2020
7e20cef
refactor(util): convert a few files to ts
danethurber Oct 12, 2020
da359df
ci: lint ignore dist ts
danethurber Oct 13, 2020
324159e
fix(util): bad import path
danethurber Oct 13, 2020
04d8367
style(verticaltabs): update typing signature
danethurber Oct 13, 2020
b57e56a
fix(util): call canUseDom in portal creation fn
danethurber Oct 13, 2020
3faaa9a
Merge branch 'master' into refactor/util-ts
danethurber Oct 13, 2020
a5c10ad
test(util): also tsc when testing
danethurber Oct 14, 2020
784ce4c
test(util): fix ts error in snapshot config
danethurber Oct 14, 2020
9899684
feat(util): deprecate prop-type utils
danethurber Oct 14, 2020
811ee18
fix(util): update ref typings
danethurber Oct 14, 2020
8285652
feat(actionmenu): update failing ref typings
danethurber Oct 14, 2020
51703f8
feat(dropdown): update failing ref typings
danethurber Oct 14, 2020
adbef7a
Merge branch 'refactor/util-ts' of github.com:pluralsight/design-syst…
danethurber Oct 14, 2020
88e5e6e
Merge branch 'master' into refactor/util-ts
danethurber Oct 14, 2020
1cb1946
refactor(util): strict type ref hooks
danethurber Oct 14, 2020
96b7176
refactor(util): strict type menu keys
danethurber Oct 14, 2020
084dd98
refactor(util): strict ts
danethurber Oct 14, 2020
9c44d39
Merge branch 'master' into refactor/util-ts
danethurber Oct 19, 2020
c0eb3e6
style(radio): fix util typing
danethurber Oct 19, 2020
16d1442
Merge branch 'master' into refactor/util-ts
danethurber Oct 20, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions .eslintignore
Expand Up @@ -3,6 +3,8 @@ node_modules/*
**/.*
**/dist/*
*.dist.js
*.dist.ts
danethurber marked this conversation as resolved.
Show resolved Hide resolved
*.dist.tsx
.cache
.github
coverage/*
Expand Down
2 changes: 1 addition & 1 deletion packages/actionmenu/package.json
Expand Up @@ -15,7 +15,7 @@
"build:esm": "tsc --project tsconfig.build.json --module es2015 --target es5 --outDir dist/esm",
"build:watch": "yarn build:esm -- --watch",
"storybook": "start-storybook -p 6006",
"test": "jest",
"test": "tsc --noEmit --project ./tsconfig.json && jest",
"test:watch": "yarn test -- --watchAll"
},
"style": "dist/index.css",
Expand Down
8 changes: 5 additions & 3 deletions packages/actionmenu/src/react/index.tsx
Expand Up @@ -2,7 +2,8 @@ import React, {
HTMLAttributes,
KeyboardEventHandler,
MouseEvent,
ReactText
ReactText,
useImperativeHandle
} from 'react'
import { css, compose, keyframes } from 'glamor'
import {
Expand Down Expand Up @@ -52,8 +53,9 @@ interface ActionMenuComponent

export const ActionMenu = React.forwardRef<HTMLUListElement, Props>(
({ onClick, onClose, children, origin, ...props }, forwardedRef) => {
const fallbackRef = React.useRef()
const ref = forwardedRef || fallbackRef
const ref = React.useRef<HTMLUListElement>()
useImperativeHandle(forwardedRef, () => ref.current)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not null problem for you like mine, eh? 🤷


useCloseOnDocumentEvents(ref, onClose)

const handleKeyDown: KeyboardEventHandler<HTMLUListElement> = evt => {
Expand Down
2 changes: 1 addition & 1 deletion packages/dropdown/package.json
Expand Up @@ -15,7 +15,7 @@
"build:esm": "tsc --project tsconfig.build.json --module es2015 --target es5 --outDir dist/esm",
"build:watch": "yarn build:esm -- --watch",
"storybook": "start-storybook -p 6006",
"test": "jest",
"test": "tsc --noEmit --project ./tsconfig.json && jest",
"test:watch": "yarn test -- --watchAll"
},
"gitHead": "7418883d96a76c59a99f86c2b16516ec752bf913",
Expand Down
40 changes: 22 additions & 18 deletions packages/dropdown/src/js/index.ts
@@ -1,20 +1,17 @@
import {
Children,
Ref,
HTMLAttributes,
createContext,
createRef,
useEffect,
useImperativeHandle,
useLayoutEffect,
useMemo,
useState,
MutableRefObject,
HTMLAttributes
useRef,
useState
} from 'react'
import { canUseDOM } from 'exenv'
import {
useCombinedRefs,
useMenuRef,
ValueOf
} from '@pluralsight/ps-design-system-util'
import { useMenuRef, ValueOf } from '@pluralsight/ps-design-system-util'

import * as vars from '../vars'

Expand Down Expand Up @@ -88,7 +85,10 @@ const sortDropdownProps = ({
}
})

export const useDropdown = (props: UseDropdownProps, forwardedRef) => {
export const useDropdown = (
props: UseDropdownProps,
forwardedRef: Ref<HTMLButtonElement>
) => {
const { hook, ...rest } = sortDropdownProps(props)
const [isOpen, setOpen] = useState(false)

Expand Down Expand Up @@ -179,21 +179,25 @@ export const useDropdown = (props: UseDropdownProps, forwardedRef) => {

const longestMenuItemState = getLongestMenuLabelState()
const [width, setWidth] = useState<React.ReactText>('auto')
const innerRef = createRef()
const combinedRef = useCombinedRefs(
forwardedRef,
innerRef
) as MutableRefObject<HTMLButtonElement>

const ref = useRef<HTMLButtonElement>()
useImperativeHandle(forwardedRef, () => ref.current)

useLayoutEffect(() => {
setWidth(combinedRef.current.getBoundingClientRect().width)
}, [combinedRef, forwardedRef])
const { current } = ref

if (!current) return

setWidth(current.getBoundingClientRect().width)
}, [])

const inNode = canUseDOM ? document.body : null
const [menuPosition, setMenuPosition] = useState({ left: 0, top: 0 })

return {
button: {
...rest.button,
ref: combinedRef,
ref,
isOpen,
onClick: handleToggleOpen,
setMenuPosition
Expand Down
1 change: 1 addition & 0 deletions packages/dropdown/src/react/__stories__/index.story.tsx
Expand Up @@ -593,6 +593,7 @@ interface DropdownWithIconProps
const DropdownWithIcon = forwardRef<HTMLButtonElement, DropdownWithIconProps>(
({ icon, ...props }, forwardedRef) => {
const allProps = useDropdown(props, forwardedRef)

return (
<Dropdown.Layout
{...allProps.layout}
Expand Down
2 changes: 1 addition & 1 deletion packages/util/package.json
Expand Up @@ -14,7 +14,7 @@
"build:esm": "tsc --project tsconfig.build.json --module es2015 --target es5 --outDir dist/esm",
"build:watch": "yarn build:esm -- --watch",
"storybook": "start-storybook -p 6006",
"test": "jest",
"test": "tsc --noEmit --project ./tsconfig.json && jest",
"test:watch": "yarn test -- --watch"
},
"types": "dist/esm/index.d.ts",
Expand Down
Expand Up @@ -6,7 +6,9 @@ test('combineFns()', () => {
const second = undefined
const third = null
const fourth = jest.fn()

danethurber marked this conversation as resolved.
Show resolved Hide resolved
combineFns(first, second, third, fourth)(expected)

expect(first).toHaveBeenCalledWith(expected)
expect(fourth).toHaveBeenCalledWith(expected)
})
12 changes: 0 additions & 12 deletions packages/util/src/__specs__/storyshots.spec.js

This file was deleted.

7 changes: 7 additions & 0 deletions packages/util/src/__specs__/storyshots.spec.ts
@@ -0,0 +1,7 @@
import path from 'path'
import initStoryshots from '@storybook/addon-storyshots'

initStoryshots({
configPath: path.resolve(__dirname, '../../.storybook'),
framework: 'react'
})
Expand Up @@ -2,7 +2,7 @@ import { capitalize } from '..'

describe('#capitalize', () => {
test('empty', () => {
expect(capitalize()).toEqual()
expect(capitalize(undefined)).toEqual(undefined)
expect(capitalize('')).toEqual('')
})

Expand Down
@@ -1,11 +1,11 @@
import { stylesFor } from '../styles'

it('returns empty object by default', () => {
expect(stylesFor()).toEqual({})
expect(stylesFor('', {})).toEqual({})
})

it('returns empty object without props', () => {
expect(stylesFor('someKey')).toEqual({})
expect(stylesFor('someKey', {})).toEqual({})
})

it('returns empty object without selectorKey', () => {
Expand Down
@@ -1,62 +1,68 @@
/* eslint-disable react/prop-types */
import { renderHook } from '@testing-library/react-hooks'
import { createRef, useImperativeHandle, useCallback, useState } from 'react'
import { useRef, useImperativeHandle, useCallback, useState } from 'react'

import { useCombinedRefs } from '..'

describe('useCombinedRefs', () => {
test('multiple refs', () => {
const { result } = renderHook(() => {
const outer = createRef()
const inner = createRef()
const combinedRef = useCombinedRefs(outer, inner)
useImperativeHandle(combinedRef, () => ({
const outer = useRef<HTMLElement>(null)
const inner = useRef<HTMLElement>(null)
const combinedRef = useCombinedRefs(inner, outer)

useImperativeHandle<unknown, unknown>(combinedRef, () => ({
value: 'ref'
}))

return { outer, inner }
})
expect(result.current.outer).toEqual({ current: { value: 'ref' } })
expect(result.current.inner).toEqual({ current: { value: 'ref' } })
})

test('one ref', () => {
const { result } = renderHook(() => {
const outer = createRef()
const inner = createRef()
const outer = useRef<HTMLElement>(null)
const inner = useRef<HTMLElement>(null)
const combinedRef = useCombinedRefs(outer)
useImperativeHandle(combinedRef, () => ({

useImperativeHandle<unknown, unknown>(combinedRef, () => ({
value: 'ref'
}))

return { outer, inner }
})
expect(result.current.outer).toEqual({ current: { value: 'ref' } })
expect(result.current.inner).toEqual({ current: null })
})

test('no refs', () => {
const { result } = renderHook(() => {
const outer = createRef()
const inner = createRef()
const outer = useRef<HTMLElement>(null)
const inner = useRef<HTMLElement>(null)
const combinedRef = useCombinedRefs()
useImperativeHandle(combinedRef, () => ({

useImperativeHandle<unknown, unknown>(combinedRef, () => ({
value: 'ref'
}))

return { outer, inner }
})

expect(result.current.outer).toEqual({ current: null })
expect(result.current.inner).toEqual({ current: null })
})
test('callbackRef', () => {

test('with a callback ref', () => {
const { result } = renderHook(() => {
const [height, setHeight] = useState(0)
const outer = createRef()
const inner = useCallback(node => {
if (node !== null) {
setHeight(5)
}
}, [])
useCombinedRefs(inner, outer)
return { height, outer }
const cbRef = useCallback(() => setHeight(5), [])

useCombinedRefs(cbRef)

return { height }
})

expect(result.current.height).toEqual(5)
expect(result.current.outer).toEqual({ current: null })
})
})
Expand Up @@ -8,11 +8,14 @@ describe('useToggle', () => {
test('uncontrolled', () => {
const { result } = renderHook(() => useToggle())
expect(result.current.isOpen).toBe(false)

act(() => {
result.current.onToggle()
})

expect(result.current.isOpen).toBe(true)
})

test('controlled', () => {
let open = false
const mockCallback = jest.fn(() => (open = !open))
Expand Down
4 changes: 0 additions & 4 deletions packages/util/src/call-all.js

This file was deleted.

15 changes: 15 additions & 0 deletions packages/util/src/call-all.ts
@@ -0,0 +1,15 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

/**
* @description calls each function passed to it with the provided arguments
* @param {...*} args - arguments to be called with each function
*/
export const callAll = <Params extends any[]>(
...fns: (Callback<Params> | undefined)[]
) => (...args: Params) => {
return fns.forEach(fn => fn && fn(...args))
}

interface Callback<Params extends any[]> {
(...args: Params): void
}
17 changes: 0 additions & 17 deletions packages/util/src/clone-element-with-ref.js

This file was deleted.

31 changes: 31 additions & 0 deletions packages/util/src/clone-element-with-ref.ts
@@ -0,0 +1,31 @@
import {
RefCallback,
HTMLAttributes,
ReactHTMLElement,
MutableRefObject,
cloneElement
} from 'react'

import { isCallbackRef, isRef } from '.'

export const cloneElementWithRef = <
P extends HTMLAttributes<T>,
T extends HTMLElement
>(
el: ReactHTMLElement<T>,
outerRef: MutableRefObject<T>,
props: P
) => {
const { ref: innerRef } = el

const combine: RefCallback<T> = node => {
if (!node) return

if (isRef<T>(outerRef)) outerRef.current = node

if (isCallbackRef<T>(innerRef)) innerRef(node)
else if (isRef<T>(innerRef)) innerRef.current = node
}

return cloneElement<P, T>(el, { ...props, ref: combine })
}
6 changes: 3 additions & 3 deletions packages/util/src/color.js → packages/util/src/color.ts
@@ -1,15 +1,15 @@
export function transparentize(amount, hex) {
export function transparentize(amount: number, hex: string) {
return rgba({
...parseToRgb(hex),
a: (100 - amount * 100) / 100
})
}

function rgba(color) {
function rgba(color: { r: number; g: number; b: number; a: number }) {
return `rgba(${color.r},${color.g},${color.b},${color.a})`
}

function parseToRgb(hex) {
function parseToRgb(hex: string) {
return {
r: parseInt(`${hex[1]}${hex[2]}`, 16),
g: parseInt(`${hex[3]}${hex[4]}`, 16),
Expand Down
5 changes: 0 additions & 5 deletions packages/util/src/combine-fns.js

This file was deleted.