feat: initial

This commit is contained in:
unix
2020-03-19 01:15:58 +08:00
parent a37c630d54
commit 1a258b23d0
181 changed files with 17112 additions and 0 deletions

View File

@@ -0,0 +1,53 @@
import React, { ReactNode } from 'react'
export const hasChild = (
children: ReactNode | undefined,
child: React.ElementType
): Boolean => {
const types = React.Children.map(children, item => {
if (!React.isValidElement(item)) return null
return item.type
})
return (types || []).includes(child)
}
export const pickChild = (
children: ReactNode | undefined,
targetChild: React.ElementType
): [ReactNode | undefined, ReactNode | undefined] => {
let target: ReactNode[] = []
const withoutTargetChildren = React.Children.map(children, item => {
if (!React.isValidElement(item)) return null
if (item.type === targetChild) {
target.push(item)
return null
}
return item
})
const targetChildren = target.length >= 0 ? target : undefined
return [withoutTargetChildren, targetChildren]
}
export const pickChildByProps = (
children: ReactNode | undefined,
key: string,
value: any,
): [ReactNode | undefined, ReactNode | undefined] => {
let target: ReactNode[] = []
const withoutPropChildren = React.Children.map(children, item => {
if (!React.isValidElement(item)) return null
if (!item.props) return item
if (item.props[key] === value) {
target.push(item)
return null
}
return item
})
const targetChildren = target.length >= 0 ? target : undefined
return [withoutPropChildren, targetChildren]
}

View File

@@ -0,0 +1,40 @@
export const tuple = <T extends string[]>(...args: T) => args
const buttonTypes = tuple(
'default',
'secondary',
'success',
'warning',
'error',
'abort',
)
const normalSizes = tuple(
'mini',
'small',
'medium',
'large',
)
const normalTypes = tuple(
'default',
'secondary',
'success',
'warning',
'error',
)
const themeTypes = tuple(
'dark',
'light',
)
export type ButtonTypes = typeof buttonTypes[number]
export type NormalSizes = typeof normalSizes[number]
export type NormalTypes = typeof normalTypes[number]
export type ThemeTypes = typeof themeTypes[number]

View File

@@ -0,0 +1,23 @@
import { Dispatch, MutableRefObject, SetStateAction, useEffect, useRef, useState } from 'react'
export type CurrentStateType<S> = [
S, Dispatch<SetStateAction<S>>, MutableRefObject<S>
]
const useCurrentState = <S,>(initialState: S): CurrentStateType<S> => {
const [state, setState] = useState<S>(initialState)
const ref = useRef<S>(initialState)
useEffect(() => {
ref.current = state
}, [state])
const setValue = (val: S) => {
ref.current = val
setState(val)
}
return [state, setValue, ref]
}
export default useCurrentState

View File

@@ -0,0 +1,39 @@
import { useEffect, useState } from 'react'
import useSSR from '../utils/use-ssr'
const getId = () => {
return Math.random().toString(32).slice(2, 10)
}
const createElement = (id: string): HTMLElement => {
const el = document.createElement('div')
el.setAttribute('id', id)
return el
}
const usePortal = (selectId: string = getId()): Element | null => {
const id = `zeit-ui-${selectId}`
const { isBrowser } = useSSR()
const [elSnapshot, setElSnapshot] = useState<Element | null>(isBrowser ? createElement(id) : null)
useEffect(() => {
const hasElement = document.querySelector(`#${id}`)
const el = hasElement || createElement(id)
if (!hasElement) {
document.body.appendChild(el)
}
setElSnapshot(el)
return () => {
const node = document.getElementById(id)
if (node) {
// document.body.removeChild(node)
}
}
}, [])
return elSnapshot
}
export default usePortal

View File

@@ -0,0 +1,20 @@
const isBrowser = (): boolean => {
return Boolean(typeof window !== 'undefined' &&
window.document &&
window.document.createElement)
}
export type SSRState = {
isBrowser: boolean
isServer: boolean
}
const useSSR = (): SSRState => {
return {
isBrowser: isBrowser(),
isServer: !isBrowser(),
}
}
export default useSSR

View File

@@ -0,0 +1,22 @@
import React from 'react'
import { ToastWithID } from '../toast/toast-container'
export type UpdateToastsFunction<T> = (fn: (toasts: Array<T>) => Array<T>) => any
export interface ZeitUiContextParams {
toasts: Array<ToastWithID>
toastHovering: boolean
updateToasts: UpdateToastsFunction<ToastWithID>
updateToastHoverStatus: Function
}
const defaultParams: ZeitUiContextParams = {
toasts: [],
toastHovering: false,
updateToasts: t => t,
updateToastHoverStatus: () => {}
}
export const ZEITUIContent:React.Context<ZeitUiContextParams> = React.createContext<ZeitUiContextParams>(defaultParams)
export const useZEITUIContext = (): ZeitUiContextParams => React.useContext<ZeitUiContextParams>(ZEITUIContent)

View File

@@ -0,0 +1,13 @@
import React from 'react'
const withDefaults = <P, DP>(
component: React.ComponentType<P>,
defaultProps: DP,
) => {
type Props = Partial<DP> & Omit<P, keyof DP>
component.defaultProps = defaultProps
return (component as React.ComponentType<any>) as React.ComponentType<Props>
}
export default withDefaults