mirror of
https://github.com/zhigang1992/react.git
synced 2026-02-02 09:08:52 +08:00
feat: export all types related to components (#562)
* feat: export all types related to components fix(tooltip): fix the vertical offset of the arrow * refactor: optimize events of all popup related components * test: append testcases for popup base component * test: add testcase for visible events * test: update snapshots
This commit is contained in:
@@ -18,6 +18,8 @@ import { pickChild } from '../utils/collections'
|
||||
import useCurrentState from '../utils/use-current-state'
|
||||
import useScaleable, { filterScaleableProps, withScaleable } from '../use-scaleable'
|
||||
|
||||
export type AutoCompleteTypes = NormalTypes
|
||||
|
||||
export type AutoCompleteOption = {
|
||||
label: string
|
||||
value: string
|
||||
@@ -29,7 +31,7 @@ export type AutoCompleteOptions = Array<
|
||||
|
||||
interface Props {
|
||||
options?: AutoCompleteOptions
|
||||
type?: NormalTypes
|
||||
type?: AutoCompleteTypes
|
||||
initialValue?: string
|
||||
value?: string
|
||||
onChange?: (value: string) => void
|
||||
@@ -50,7 +52,7 @@ const defaultProps = {
|
||||
initialValue: '',
|
||||
disabled: false,
|
||||
clearable: false,
|
||||
type: 'default' as NormalTypes,
|
||||
type: 'default' as AutoCompleteTypes,
|
||||
disableMatchWidth: false,
|
||||
disableFreeSolo: false,
|
||||
className: '',
|
||||
@@ -135,10 +137,10 @@ const AutoCompleteComponent = React.forwardRef<
|
||||
}
|
||||
return childrenToOptionsNode(options as Array<AutoCompleteOption>)
|
||||
}, [searching, options])
|
||||
const showClearIcon = useMemo(() => clearable && searching === undefined, [
|
||||
clearable,
|
||||
searching,
|
||||
])
|
||||
const showClearIcon = useMemo(
|
||||
() => clearable && searching === undefined,
|
||||
[clearable, searching],
|
||||
)
|
||||
|
||||
const updateValue = (val: string) => {
|
||||
if (disabled) return
|
||||
|
||||
@@ -14,4 +14,10 @@ export type AutoCompleteComponentType = typeof AutoComplete & {
|
||||
;(AutoComplete as AutoCompleteComponentType).Searching = AutoCompleteSearching
|
||||
;(AutoComplete as AutoCompleteComponentType).Empty = AutoCompleteEmpty
|
||||
|
||||
export type {
|
||||
AutoCompleteOption,
|
||||
AutoCompleteOptions,
|
||||
AutoCompleteProps,
|
||||
AutoCompleteTypes,
|
||||
} from './auto-complete'
|
||||
export default AutoComplete as AutoCompleteComponentType
|
||||
|
||||
@@ -6,4 +6,7 @@ export type AvatarComponentType = typeof Avatar & {
|
||||
}
|
||||
;(Avatar as AvatarComponentType).Group = AvatarGroup
|
||||
|
||||
export type { AvatarProps } from './avatar'
|
||||
export type { AvatarGroupProps } from './avatar-group'
|
||||
|
||||
export default Avatar as AvatarComponentType
|
||||
|
||||
@@ -5,7 +5,7 @@ import Badge from './badge'
|
||||
|
||||
const placement = tuple('topLeft', 'topRight', 'bottomLeft', 'bottomRight')
|
||||
|
||||
type BadgeAnchorPlacement = typeof placement[number]
|
||||
export type BadgeAnchorPlacement = typeof placement[number]
|
||||
|
||||
interface Props {
|
||||
placement?: BadgeAnchorPlacement
|
||||
|
||||
@@ -4,14 +4,16 @@ import { NormalTypes } from '../utils/prop-types'
|
||||
import { GeistUIThemesPalette } from '../themes/presets'
|
||||
import useScaleable, { withScaleable } from '../use-scaleable'
|
||||
|
||||
export type BadgeTypes = NormalTypes
|
||||
|
||||
interface Props {
|
||||
type?: NormalTypes
|
||||
type?: BadgeTypes
|
||||
dot?: boolean
|
||||
className?: string
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
type: 'default' as NormalTypes,
|
||||
type: 'default' as BadgeTypes,
|
||||
dot: false,
|
||||
className: '',
|
||||
}
|
||||
|
||||
@@ -6,4 +6,6 @@ export type BadgeComponentType = typeof Badge & {
|
||||
}
|
||||
;(Badge as BadgeComponentType).Anchor = BadgeAnchor
|
||||
|
||||
export type { BadgeProps, BadgeTypes } from './badge'
|
||||
export type { BadgeAnchorProps, BadgeAnchorPlacement } from './badge-anchor'
|
||||
export default Badge as BadgeComponentType
|
||||
|
||||
@@ -9,4 +9,7 @@ export type BreadcrumbsComponentType = typeof Breadcrumbs & {
|
||||
;(Breadcrumbs as BreadcrumbsComponentType).Item = BreadcrumbsItem
|
||||
;(Breadcrumbs as BreadcrumbsComponentType).Separator = BreadcrumbsSeparator
|
||||
|
||||
export type { BreadcrumbsProps } from './breadcrumbs'
|
||||
export type { BreadcrumbsItemProps } from './breadcrumbs-item'
|
||||
export type { BreadcrumbsSeparatorProps } from './breadcrumbs-separator'
|
||||
export default Breadcrumbs as BreadcrumbsComponentType
|
||||
|
||||
@@ -5,16 +5,18 @@ import { useButtonDropdown } from './button-dropdown-context'
|
||||
import Loading from '../loading'
|
||||
import { NormalTypes } from '../utils/prop-types'
|
||||
|
||||
export type ButtonDropdownItemTypes = NormalTypes
|
||||
|
||||
interface Props {
|
||||
main?: boolean
|
||||
type?: NormalTypes
|
||||
type?: ButtonDropdownItemTypes
|
||||
onClick?: React.MouseEventHandler<HTMLElement>
|
||||
className?: string
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
main: false,
|
||||
type: 'default' as NormalTypes,
|
||||
type: 'default' as ButtonDropdownItemTypes,
|
||||
onClick: () => {},
|
||||
className: '',
|
||||
}
|
||||
|
||||
@@ -9,8 +9,10 @@ import { NormalTypes } from '../utils/prop-types'
|
||||
import { pickChild, pickChildByProps } from '../utils/collections'
|
||||
import useScaleable, { withScaleable } from '../use-scaleable'
|
||||
|
||||
export type ButtonDropdownTypes = NormalTypes
|
||||
|
||||
interface Props {
|
||||
type?: NormalTypes
|
||||
type?: ButtonDropdownTypes
|
||||
auto?: boolean
|
||||
loading?: boolean
|
||||
disabled?: boolean
|
||||
@@ -18,7 +20,7 @@ interface Props {
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
type: 'default' as NormalTypes,
|
||||
type: 'default' as ButtonDropdownTypes,
|
||||
auto: false,
|
||||
loading: false,
|
||||
disabled: false,
|
||||
|
||||
@@ -6,4 +6,9 @@ type ButtonDropdownType = typeof ButtonDropdown & {
|
||||
}
|
||||
;(ButtonDropdown as ButtonDropdownType).Item = ButtonDropdownItem
|
||||
|
||||
export type { ButtonDropdownProps, ButtonDropdownTypes } from './button-dropdown'
|
||||
export type {
|
||||
ButtonDropdownItemProps,
|
||||
ButtonDropdownItemTypes,
|
||||
} from './button-dropdown-item'
|
||||
export default ButtonDropdown as ButtonDropdownType
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import ButtonGroup from './button-group'
|
||||
|
||||
export type { ButtonGroupProps } from './button-group'
|
||||
export type { ButtonTypes } from '../utils/prop-types'
|
||||
export default ButtonGroup
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import Button from './button'
|
||||
|
||||
export type { ButtonProps } from './button'
|
||||
export type { ButtonTypes } from '../utils/prop-types'
|
||||
export default Button
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Capacity from './capacity'
|
||||
|
||||
export type { CapacityProps } from './capacity'
|
||||
export default Capacity
|
||||
|
||||
@@ -13,4 +13,8 @@ export type CardComponentType = typeof Card & {
|
||||
;(Card as CardComponentType).Content = CardContent
|
||||
;(Card as CardComponentType).Body = CardContent
|
||||
|
||||
export type { CardProps } from './card'
|
||||
export type { CardContentProps } from './card-content'
|
||||
export type { CardFooterProps } from './card-footer'
|
||||
export type { CardTypes } from '../utils/prop-types'
|
||||
export default Card as CardComponentType
|
||||
|
||||
@@ -7,10 +7,10 @@ import { getColors } from './styles'
|
||||
import useTheme from '../use-theme'
|
||||
import useScaleable, { withScaleable } from '../use-scaleable'
|
||||
|
||||
interface CheckboxEventTarget {
|
||||
export type CheckboxTypes = NormalTypes
|
||||
export interface CheckboxEventTarget {
|
||||
checked: boolean
|
||||
}
|
||||
|
||||
export interface CheckboxEvent {
|
||||
target: CheckboxEventTarget
|
||||
stopPropagation: () => void
|
||||
@@ -21,7 +21,7 @@ export interface CheckboxEvent {
|
||||
interface Props {
|
||||
checked?: boolean
|
||||
disabled?: boolean
|
||||
type?: NormalTypes
|
||||
type?: CheckboxTypes
|
||||
initialChecked?: boolean
|
||||
onChange?: (e: CheckboxEvent) => void
|
||||
className?: string
|
||||
@@ -30,7 +30,7 @@ interface Props {
|
||||
|
||||
const defaultProps = {
|
||||
disabled: false,
|
||||
type: 'default' as NormalTypes,
|
||||
type: 'default' as CheckboxTypes,
|
||||
initialChecked: false,
|
||||
className: '',
|
||||
value: '',
|
||||
@@ -70,10 +70,10 @@ const CheckboxComponent: React.FC<CheckboxProps> = ({
|
||||
}, [values.join(',')])
|
||||
}
|
||||
|
||||
const { fill, bg } = useMemo(() => getColors(theme.palette, type), [
|
||||
theme.palette,
|
||||
type,
|
||||
])
|
||||
const { fill, bg } = useMemo(
|
||||
() => getColors(theme.palette, type),
|
||||
[theme.palette, type],
|
||||
)
|
||||
|
||||
const changeHandle = useCallback(
|
||||
(ev: React.ChangeEvent) => {
|
||||
|
||||
@@ -6,4 +6,11 @@ export type CheckboxComponentType = typeof Checkbox & {
|
||||
}
|
||||
;(Checkbox as CheckboxComponentType).Group = CheckboxGroup
|
||||
|
||||
export type {
|
||||
CheckboxProps,
|
||||
CheckboxEvent,
|
||||
CheckboxEventTarget,
|
||||
CheckboxTypes,
|
||||
} from './checkbox'
|
||||
export type { CheckboxGroupProps } from './checkbox-group'
|
||||
export default Checkbox as CheckboxComponentType
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import Code from './code'
|
||||
import { CodeProps } from './code'
|
||||
|
||||
export type Props = CodeProps
|
||||
export type { CodeProps } from './code'
|
||||
export default Code
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import Col from './col'
|
||||
import { ColProps } from './col'
|
||||
|
||||
export type Props = ColProps
|
||||
export type { ColProps } from './col'
|
||||
export default Col
|
||||
|
||||
@@ -6,4 +6,6 @@ export type CollapseComponentType = typeof Collapse & {
|
||||
}
|
||||
;(Collapse as CollapseComponentType).Group = CollapseGroup
|
||||
|
||||
export default Collapse
|
||||
export type { CollapseProps } from './collapse'
|
||||
export type { CollapseGroupProps } from './collapse-group'
|
||||
export default Collapse as CollapseComponentType
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import Description from './description'
|
||||
import { DescriptionProps } from './description'
|
||||
|
||||
export type Props = DescriptionProps
|
||||
export type { DescriptionProps } from './description'
|
||||
export default Description
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import Display from './display'
|
||||
import { DisplayProps } from './display'
|
||||
|
||||
export type Props = DisplayProps
|
||||
export type { DisplayProps } from './display'
|
||||
export default Display
|
||||
|
||||
@@ -549,8 +549,8 @@ initialize {
|
||||
"next": Node {
|
||||
"attribs": Object {
|
||||
"class": "divider ",
|
||||
"h": "2",
|
||||
"role": "separator",
|
||||
"volume": "2",
|
||||
},
|
||||
"children": Array [
|
||||
Node {
|
||||
@@ -579,7 +579,7 @@ initialize {
|
||||
position: relative;
|
||||
font-size: calc(1 * 16px);
|
||||
width: auto;
|
||||
height: calc(0.0625 * 16px);
|
||||
height: calc(0.125 * 16px);
|
||||
padding: 0 0 0 0;
|
||||
margin: calc(0.5 * 16px) 0 calc(0.5 * 16px) 0;
|
||||
}
|
||||
@@ -649,7 +649,7 @@ initialize {
|
||||
position: relative;
|
||||
font-size: calc(1 * 16px);
|
||||
width: auto;
|
||||
height: calc(0.0625 * 16px);
|
||||
height: calc(0.125 * 16px);
|
||||
padding: 0 0 0 0;
|
||||
margin: calc(0.5 * 16px) 0 calc(0.5 * 16px) 0;
|
||||
}
|
||||
@@ -732,13 +732,13 @@ initialize {
|
||||
"type": "tag",
|
||||
"x-attribsNamespace": Object {
|
||||
"class": undefined,
|
||||
"h": undefined,
|
||||
"role": undefined,
|
||||
"volume": undefined,
|
||||
},
|
||||
"x-attribsPrefix": Object {
|
||||
"class": undefined,
|
||||
"h": undefined,
|
||||
"role": undefined,
|
||||
"volume": undefined,
|
||||
},
|
||||
},
|
||||
"parent": [Circular],
|
||||
@@ -1138,8 +1138,8 @@ initialize {
|
||||
"next": Node {
|
||||
"attribs": Object {
|
||||
"class": "divider ",
|
||||
"h": "2",
|
||||
"role": "separator",
|
||||
"volume": "2",
|
||||
},
|
||||
"children": Array [
|
||||
Node {
|
||||
@@ -1168,7 +1168,7 @@ initialize {
|
||||
position: relative;
|
||||
font-size: calc(1 * 16px);
|
||||
width: auto;
|
||||
height: calc(0.0625 * 16px);
|
||||
height: calc(0.125 * 16px);
|
||||
padding: 0 0 0 0;
|
||||
margin: calc(0.5 * 16px) 0 calc(0.5 * 16px) 0;
|
||||
}
|
||||
@@ -1238,7 +1238,7 @@ initialize {
|
||||
position: relative;
|
||||
font-size: calc(1 * 16px);
|
||||
width: auto;
|
||||
height: calc(0.0625 * 16px);
|
||||
height: calc(0.125 * 16px);
|
||||
padding: 0 0 0 0;
|
||||
margin: calc(0.5 * 16px) 0 calc(0.5 * 16px) 0;
|
||||
}
|
||||
@@ -1321,13 +1321,13 @@ initialize {
|
||||
"type": "tag",
|
||||
"x-attribsNamespace": Object {
|
||||
"class": undefined,
|
||||
"h": undefined,
|
||||
"role": undefined,
|
||||
"volume": undefined,
|
||||
},
|
||||
"x-attribsPrefix": Object {
|
||||
"class": undefined,
|
||||
"h": undefined,
|
||||
"role": undefined,
|
||||
"volume": undefined,
|
||||
},
|
||||
},
|
||||
"parent": [Circular],
|
||||
@@ -1727,8 +1727,8 @@ initialize {
|
||||
"next": Node {
|
||||
"attribs": Object {
|
||||
"class": "divider ",
|
||||
"h": "2",
|
||||
"role": "separator",
|
||||
"volume": "2",
|
||||
},
|
||||
"children": Array [
|
||||
Node {
|
||||
@@ -1757,7 +1757,7 @@ initialize {
|
||||
position: relative;
|
||||
font-size: calc(1 * 16px);
|
||||
width: auto;
|
||||
height: calc(0.0625 * 16px);
|
||||
height: calc(0.125 * 16px);
|
||||
padding: 0 0 0 0;
|
||||
margin: calc(0.5 * 16px) 0 calc(0.5 * 16px) 0;
|
||||
}
|
||||
@@ -1827,7 +1827,7 @@ initialize {
|
||||
position: relative;
|
||||
font-size: calc(1 * 16px);
|
||||
width: auto;
|
||||
height: calc(0.0625 * 16px);
|
||||
height: calc(0.125 * 16px);
|
||||
padding: 0 0 0 0;
|
||||
margin: calc(0.5 * 16px) 0 calc(0.5 * 16px) 0;
|
||||
}
|
||||
@@ -1910,13 +1910,13 @@ initialize {
|
||||
"type": "tag",
|
||||
"x-attribsNamespace": Object {
|
||||
"class": undefined,
|
||||
"h": undefined,
|
||||
"role": undefined,
|
||||
"volume": undefined,
|
||||
},
|
||||
"x-attribsPrefix": Object {
|
||||
"class": undefined,
|
||||
"h": undefined,
|
||||
"role": undefined,
|
||||
"volume": undefined,
|
||||
},
|
||||
},
|
||||
"parent": [Circular],
|
||||
@@ -2316,8 +2316,8 @@ initialize {
|
||||
Node {
|
||||
"attribs": Object {
|
||||
"class": "divider ",
|
||||
"h": "2",
|
||||
"role": "separator",
|
||||
"volume": "2",
|
||||
},
|
||||
"children": Array [
|
||||
Node {
|
||||
@@ -2346,7 +2346,7 @@ initialize {
|
||||
position: relative;
|
||||
font-size: calc(1 * 16px);
|
||||
width: auto;
|
||||
height: calc(0.0625 * 16px);
|
||||
height: calc(0.125 * 16px);
|
||||
padding: 0 0 0 0;
|
||||
margin: calc(0.5 * 16px) 0 calc(0.5 * 16px) 0;
|
||||
}
|
||||
@@ -2416,7 +2416,7 @@ initialize {
|
||||
position: relative;
|
||||
font-size: calc(1 * 16px);
|
||||
width: auto;
|
||||
height: calc(0.0625 * 16px);
|
||||
height: calc(0.125 * 16px);
|
||||
padding: 0 0 0 0;
|
||||
margin: calc(0.5 * 16px) 0 calc(0.5 * 16px) 0;
|
||||
}
|
||||
@@ -3072,13 +3072,13 @@ initialize {
|
||||
"type": "tag",
|
||||
"x-attribsNamespace": Object {
|
||||
"class": undefined,
|
||||
"h": undefined,
|
||||
"role": undefined,
|
||||
"volume": undefined,
|
||||
},
|
||||
"x-attribsPrefix": Object {
|
||||
"class": undefined,
|
||||
"h": undefined,
|
||||
"role": undefined,
|
||||
"volume": undefined,
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -3874,7 +3874,7 @@ initialize {
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Divider should work with x and y 1`] = `
|
||||
exports[`Divider should work with w and h 1`] = `
|
||||
initialize {
|
||||
"0": Node {
|
||||
"attribs": Object {},
|
||||
@@ -3883,7 +3883,7 @@ initialize {
|
||||
"attribs": Object {
|
||||
"class": "divider ",
|
||||
"role": "separator",
|
||||
"x": "3",
|
||||
"w": "3",
|
||||
},
|
||||
"children": Array [
|
||||
Node {
|
||||
@@ -3896,7 +3896,7 @@ initialize {
|
||||
background-color: #eaeaea;
|
||||
position: relative;
|
||||
font-size: calc(1 * 16px);
|
||||
width: auto;
|
||||
width: calc(3 * 16px);
|
||||
height: calc(0.0625 * 16px);
|
||||
padding: 0 0 0 0;
|
||||
margin: calc(0.5 * 16px) 0 calc(0.5 * 16px) 0;
|
||||
@@ -3952,8 +3952,8 @@ initialize {
|
||||
"next": Node {
|
||||
"attribs": Object {
|
||||
"class": "divider ",
|
||||
"h": "3",
|
||||
"role": "separator",
|
||||
"y": "3",
|
||||
},
|
||||
"children": Array [
|
||||
Node {
|
||||
@@ -3967,7 +3967,7 @@ initialize {
|
||||
position: relative;
|
||||
font-size: calc(1 * 16px);
|
||||
width: auto;
|
||||
height: calc(0.0625 * 16px);
|
||||
height: calc(0.1875 * 16px);
|
||||
padding: 0 0 0 0;
|
||||
margin: calc(0.5 * 16px) 0 calc(0.5 * 16px) 0;
|
||||
}
|
||||
@@ -4025,13 +4025,13 @@ initialize {
|
||||
"type": "tag",
|
||||
"x-attribsNamespace": Object {
|
||||
"class": undefined,
|
||||
"h": undefined,
|
||||
"role": undefined,
|
||||
"y": undefined,
|
||||
},
|
||||
"x-attribsPrefix": Object {
|
||||
"class": undefined,
|
||||
"h": undefined,
|
||||
"role": undefined,
|
||||
"y": undefined,
|
||||
},
|
||||
},
|
||||
"parent": [Circular],
|
||||
@@ -4040,19 +4040,19 @@ initialize {
|
||||
"x-attribsNamespace": Object {
|
||||
"class": undefined,
|
||||
"role": undefined,
|
||||
"x": undefined,
|
||||
"w": undefined,
|
||||
},
|
||||
"x-attribsPrefix": Object {
|
||||
"class": undefined,
|
||||
"role": undefined,
|
||||
"x": undefined,
|
||||
"w": undefined,
|
||||
},
|
||||
},
|
||||
Node {
|
||||
"attribs": Object {
|
||||
"class": "divider ",
|
||||
"h": "3",
|
||||
"role": "separator",
|
||||
"y": "3",
|
||||
},
|
||||
"children": Array [
|
||||
Node {
|
||||
@@ -4066,7 +4066,7 @@ initialize {
|
||||
position: relative;
|
||||
font-size: calc(1 * 16px);
|
||||
width: auto;
|
||||
height: calc(0.0625 * 16px);
|
||||
height: calc(0.1875 * 16px);
|
||||
padding: 0 0 0 0;
|
||||
margin: calc(0.5 * 16px) 0 calc(0.5 * 16px) 0;
|
||||
}
|
||||
@@ -4124,7 +4124,7 @@ initialize {
|
||||
"attribs": Object {
|
||||
"class": "divider ",
|
||||
"role": "separator",
|
||||
"x": "3",
|
||||
"w": "3",
|
||||
},
|
||||
"children": Array [
|
||||
Node {
|
||||
@@ -4137,7 +4137,7 @@ initialize {
|
||||
background-color: #eaeaea;
|
||||
position: relative;
|
||||
font-size: calc(1 * 16px);
|
||||
width: auto;
|
||||
width: calc(3 * 16px);
|
||||
height: calc(0.0625 * 16px);
|
||||
padding: 0 0 0 0;
|
||||
margin: calc(0.5 * 16px) 0 calc(0.5 * 16px) 0;
|
||||
@@ -4197,24 +4197,24 @@ initialize {
|
||||
"x-attribsNamespace": Object {
|
||||
"class": undefined,
|
||||
"role": undefined,
|
||||
"x": undefined,
|
||||
"w": undefined,
|
||||
},
|
||||
"x-attribsPrefix": Object {
|
||||
"class": undefined,
|
||||
"role": undefined,
|
||||
"x": undefined,
|
||||
"w": undefined,
|
||||
},
|
||||
},
|
||||
"type": "tag",
|
||||
"x-attribsNamespace": Object {
|
||||
"class": undefined,
|
||||
"h": undefined,
|
||||
"role": undefined,
|
||||
"y": undefined,
|
||||
},
|
||||
"x-attribsPrefix": Object {
|
||||
"class": undefined,
|
||||
"h": undefined,
|
||||
"role": undefined,
|
||||
"y": undefined,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -9,11 +9,11 @@ describe('Divider', () => {
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
|
||||
it('should work with x and y', () => {
|
||||
it('should work with w and h', () => {
|
||||
const wrapper = render(
|
||||
<div>
|
||||
<Divider x={3} />
|
||||
<Divider y={3} />
|
||||
<Divider w={3} />
|
||||
<Divider h={3} />
|
||||
</div>,
|
||||
)
|
||||
expect(wrapper).toMatchSnapshot()
|
||||
@@ -36,7 +36,7 @@ describe('Divider', () => {
|
||||
<Divider align="start">start</Divider>
|
||||
<Divider align="left">left</Divider>
|
||||
<Divider align="end">end</Divider>
|
||||
<Divider align="start" volume={2}>
|
||||
<Divider align="start" h={2}>
|
||||
start
|
||||
</Divider>
|
||||
</div>,
|
||||
@@ -47,8 +47,8 @@ describe('Divider', () => {
|
||||
it('should support float', () => {
|
||||
const wrapper = mount(
|
||||
<div>
|
||||
<Divider x={1.1} y={2.5} />
|
||||
<Divider volume={2.5} />
|
||||
<Divider w={1.1} h={2.5} />
|
||||
<Divider h={2.5} />
|
||||
</div>,
|
||||
)
|
||||
expect(wrapper).toMatchSnapshot()
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import Divider from './divider'
|
||||
|
||||
export type { DividerProps, DividerTypes } from './divider'
|
||||
export type { DividerAlign } from '../utils/prop-types'
|
||||
export default Divider
|
||||
|
||||
@@ -4,21 +4,22 @@ import { NormalTypes } from '../utils/prop-types'
|
||||
import { GeistUIThemes } from '../themes/presets'
|
||||
import useScaleable, { withScaleable } from '../use-scaleable'
|
||||
|
||||
export type DotTypes = NormalTypes
|
||||
interface Props {
|
||||
type?: NormalTypes
|
||||
type?: DotTypes
|
||||
className?: string
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
type: 'default' as NormalTypes,
|
||||
type: 'default' as DotTypes,
|
||||
className: '',
|
||||
}
|
||||
|
||||
type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
|
||||
export type DotProps = Props & NativeAttrs
|
||||
|
||||
const getColor = (type: NormalTypes, theme: GeistUIThemes): string => {
|
||||
const colors: { [key in NormalTypes]?: string } = {
|
||||
const getColor = (type: DotTypes, theme: GeistUIThemes): string => {
|
||||
const colors: { [key in DotTypes]?: string } = {
|
||||
default: theme.palette.accents_2,
|
||||
success: theme.palette.success,
|
||||
warning: theme.palette.warning,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import Dot from './dot'
|
||||
import { DotProps } from './dot'
|
||||
|
||||
export type Props = DotProps
|
||||
export type { DotProps, DotTypes } from './dot'
|
||||
export default Dot
|
||||
|
||||
@@ -20,4 +20,10 @@ export type FieldsetComponentType = typeof Fieldset & {
|
||||
;(Fieldset as FieldsetComponentType).Content = FieldsetContent
|
||||
;(Fieldset as FieldsetComponentType).Body = FieldsetContent
|
||||
|
||||
export type { FieldsetProps } from './fieldset'
|
||||
export type { FieldsetTitleProps } from './fieldset-title'
|
||||
export type { FieldsetSubtitleProps } from './fieldset-subtitle'
|
||||
export type { FieldsetGroupProps } from './fieldset-group'
|
||||
export type { FieldsetFooterProps } from './fieldset-footer'
|
||||
export type { FieldsetContentProps } from './fieldset-content'
|
||||
export default Fieldset as FieldsetComponentType
|
||||
|
||||
@@ -9,12 +9,12 @@ import useCurrentState from '../utils/use-current-state'
|
||||
import ToastContainer, { ToastWithID } from '../use-toasts/toast-container'
|
||||
import { GeistUIThemes } from '../themes/presets'
|
||||
|
||||
export interface Props {
|
||||
export type GeistProviderProps = {
|
||||
themes?: Array<GeistUIThemes>
|
||||
themeType?: string | 'dark' | 'light'
|
||||
}
|
||||
|
||||
const GeistProvider: React.FC<PropsWithChildren<Props>> = ({
|
||||
const GeistProvider: React.FC<PropsWithChildren<GeistProviderProps>> = ({
|
||||
themes,
|
||||
themeType,
|
||||
children,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import GeistProvider from './geist-provider'
|
||||
|
||||
export type { GeistProviderProps } from './geist-provider'
|
||||
export default GeistProvider
|
||||
|
||||
@@ -1,28 +1,33 @@
|
||||
import React, { useMemo } from 'react'
|
||||
import useTheme from '../use-theme'
|
||||
import { Justify, Direction, AlignItems, AlignContent } from './grid-types'
|
||||
import {
|
||||
GridJustify,
|
||||
GridDirection,
|
||||
GridAlignItems,
|
||||
GridAlignContent,
|
||||
} from './grid-types'
|
||||
import useScaleable from '../use-scaleable'
|
||||
|
||||
type BreakpointsValue = number | boolean
|
||||
export type GridBreakpointsValue = number | boolean
|
||||
export interface GridBasicComponentProps {
|
||||
xs?: BreakpointsValue
|
||||
sm?: BreakpointsValue
|
||||
md?: BreakpointsValue
|
||||
lg?: BreakpointsValue
|
||||
xl?: BreakpointsValue
|
||||
justify?: Justify
|
||||
direction?: Direction
|
||||
alignItems?: AlignItems
|
||||
alignContent?: AlignContent
|
||||
xs?: GridBreakpointsValue
|
||||
sm?: GridBreakpointsValue
|
||||
md?: GridBreakpointsValue
|
||||
lg?: GridBreakpointsValue
|
||||
xl?: GridBreakpointsValue
|
||||
justify?: GridJustify
|
||||
direction?: GridDirection
|
||||
alignItems?: GridAlignItems
|
||||
alignContent?: GridAlignContent
|
||||
className?: string
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
xs: false as BreakpointsValue,
|
||||
sm: false as BreakpointsValue,
|
||||
md: false as BreakpointsValue,
|
||||
lg: false as BreakpointsValue,
|
||||
xl: false as BreakpointsValue,
|
||||
xs: false as GridBreakpointsValue,
|
||||
sm: false as GridBreakpointsValue,
|
||||
md: false as GridBreakpointsValue,
|
||||
lg: false as GridBreakpointsValue,
|
||||
xl: false as GridBreakpointsValue,
|
||||
className: '',
|
||||
}
|
||||
|
||||
@@ -35,7 +40,7 @@ type ItemLayoutValue = {
|
||||
basis: string
|
||||
display: string
|
||||
}
|
||||
const getItemLayout = (val: BreakpointsValue): ItemLayoutValue => {
|
||||
const getItemLayout = (val: GridBreakpointsValue): ItemLayoutValue => {
|
||||
const display = val === 0 ? 'display: none;' : 'display: inherit;'
|
||||
if (typeof val === 'number') {
|
||||
const width = (100 / 24) * val
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import React, { useMemo } from 'react'
|
||||
import GridBasicItem, { GridBasicItemProps } from './basic-item'
|
||||
import { Wrap } from './grid-types'
|
||||
import { GridWrap } from './grid-types'
|
||||
import { css } from 'styled-jsx/css'
|
||||
import useScaleable, { withScaleable } from '../use-scaleable'
|
||||
|
||||
interface Props {
|
||||
gap?: number
|
||||
wrap?: Wrap
|
||||
wrap?: GridWrap
|
||||
className?: string
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
gap: 0,
|
||||
wrap: 'wrap' as Wrap,
|
||||
wrap: 'wrap' as GridWrap,
|
||||
className: '',
|
||||
}
|
||||
|
||||
|
||||
@@ -9,11 +9,11 @@ const justify = tuple(
|
||||
'space-evenly',
|
||||
)
|
||||
|
||||
export type Justify = typeof justify[number]
|
||||
export type GridJustify = typeof justify[number]
|
||||
|
||||
const alignItems = tuple('flex-start', 'center', 'flex-end', 'stretch', 'baseline')
|
||||
|
||||
export type AlignItems = typeof alignItems[number]
|
||||
export type GridAlignItems = typeof alignItems[number]
|
||||
|
||||
const alignContent = tuple(
|
||||
'stretch',
|
||||
@@ -24,12 +24,12 @@ const alignContent = tuple(
|
||||
'space-around',
|
||||
)
|
||||
|
||||
export type AlignContent = typeof alignContent[number]
|
||||
export type GridAlignContent = typeof alignContent[number]
|
||||
|
||||
const direction = tuple('row', 'row-reverse', 'column', 'column-reverse')
|
||||
|
||||
export type Direction = typeof direction[number]
|
||||
export type GridDirection = typeof direction[number]
|
||||
|
||||
const wrap = tuple('nowrap', 'wrap', 'wrap-reverse')
|
||||
|
||||
export type Wrap = typeof wrap[number]
|
||||
export type GridWrap = typeof wrap[number]
|
||||
|
||||
@@ -6,4 +6,14 @@ export type GridComponentType = typeof Grid & {
|
||||
}
|
||||
;(Grid as GridComponentType).Container = GridContainer
|
||||
|
||||
export type { GridContainerProps } from './grid-container'
|
||||
export type { GridProps } from './grid'
|
||||
export type { GridBreakpointsValue } from './basic-item'
|
||||
export type {
|
||||
GridAlignContent,
|
||||
GridAlignItems,
|
||||
GridDirection,
|
||||
GridJustify,
|
||||
GridWrap,
|
||||
} from './grid-types'
|
||||
export default Grid as GridComponentType
|
||||
|
||||
@@ -6,21 +6,21 @@ import ImageBrowserHttpsIcon from './image-browser-https-icon'
|
||||
import { getBrowserColors, BrowserColors } from './styles'
|
||||
import useScaleable, { withScaleable } from '../use-scaleable'
|
||||
|
||||
type AnchorProps = Omit<React.AnchorHTMLAttributes<any>, keyof LinkProps>
|
||||
export type ImageAnchorProps = Omit<React.AnchorHTMLAttributes<any>, keyof LinkProps>
|
||||
|
||||
interface Props {
|
||||
title?: string
|
||||
url?: string
|
||||
showFullLink?: boolean
|
||||
invert?: boolean
|
||||
anchorProps?: AnchorProps
|
||||
anchorProps?: ImageAnchorProps
|
||||
className?: string
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
className: '',
|
||||
showFullLink: false,
|
||||
anchorProps: {} as AnchorProps,
|
||||
anchorProps: {} as ImageAnchorProps,
|
||||
invert: false,
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ const getAddressInput = (
|
||||
url: string,
|
||||
showFullLink: boolean,
|
||||
colors: BrowserColors,
|
||||
anchorProps: AnchorProps,
|
||||
anchorProps: ImageAnchorProps,
|
||||
) => (
|
||||
<div className="address-input">
|
||||
<span className="https">
|
||||
@@ -124,10 +124,10 @@ const ImageBrowserComponent = React.forwardRef<
|
||||
) => {
|
||||
const theme = useTheme()
|
||||
const { SCALES } = useScaleable()
|
||||
const colors = useMemo(() => getBrowserColors(invert, theme.palette), [
|
||||
invert,
|
||||
theme.palette,
|
||||
])
|
||||
const colors = useMemo(
|
||||
() => getBrowserColors(invert, theme.palette),
|
||||
[invert, theme.palette],
|
||||
)
|
||||
const input = useMemo(() => {
|
||||
if (url) return getAddressInput(url, showFullLink, colors, anchorProps)
|
||||
if (title) return getTitle(title, colors)
|
||||
|
||||
@@ -6,4 +6,6 @@ export type ImageComponentType = typeof Image & {
|
||||
}
|
||||
;(Image as ImageComponentType).Browser = ImageBrowser
|
||||
|
||||
export type { ImageProps } from './image'
|
||||
export type { ImageBrowserProps, ImageAnchorProps } from './image-browser'
|
||||
export default Image as ImageComponentType
|
||||
|
||||
@@ -1,61 +1,190 @@
|
||||
/// <reference types="styled-jsx" />
|
||||
export * from './themes/presets'
|
||||
export { default as Themes } from './themes'
|
||||
export { default as useTheme } from './use-theme'
|
||||
export { default as useAllThemes } from './use-all-themes'
|
||||
export { default as AutoComplete } from './auto-complete'
|
||||
export type { AutoCompleteProps } from './auto-complete'
|
||||
|
||||
export { default as Avatar } from './avatar'
|
||||
export type { AvatarProps, AvatarGroupProps } from './avatar'
|
||||
|
||||
export { default as Badge } from './badge'
|
||||
export type { BadgeProps, BadgeAnchorProps } from './badge'
|
||||
|
||||
export { default as Breadcrumbs } from './breadcrumbs'
|
||||
export type {
|
||||
BreadcrumbsProps,
|
||||
BreadcrumbsItemProps,
|
||||
BreadcrumbsSeparatorProps,
|
||||
} from './breadcrumbs'
|
||||
|
||||
export { default as Button } from './button'
|
||||
export type { ButtonProps } from './button'
|
||||
|
||||
export { default as ButtonDropdown } from './button-dropdown'
|
||||
export type { ButtonDropdownProps, ButtonDropdownItemProps } from './button-dropdown'
|
||||
|
||||
export { default as ButtonGroup } from './button-group'
|
||||
export type { ButtonGroupProps } from './button-group'
|
||||
|
||||
export { default as Capacity } from './capacity'
|
||||
export type { CapacityProps } from './capacity'
|
||||
|
||||
export { default as Card } from './card'
|
||||
export type { CardProps, CardContentProps, CardFooterProps } from './card'
|
||||
|
||||
export { default as Checkbox } from './checkbox'
|
||||
export type { CheckboxProps, CheckboxGroupProps } from './checkbox'
|
||||
|
||||
export { default as Code } from './code'
|
||||
export type { CodeProps } from './code'
|
||||
|
||||
export { default as Collapse } from './collapse'
|
||||
export type { CollapseProps, CollapseGroupProps } from './collapse'
|
||||
|
||||
export { default as Description } from './description'
|
||||
export type { DescriptionProps } from './description'
|
||||
|
||||
export { default as Display } from './display'
|
||||
export type { DisplayProps } from './display'
|
||||
|
||||
export { default as Divider } from './divider'
|
||||
export type { DividerProps } from './divider'
|
||||
|
||||
export { default as Dot } from './dot'
|
||||
export type { DotProps } from './dot'
|
||||
|
||||
export { default as Fieldset } from './fieldset'
|
||||
export type {
|
||||
FieldsetProps,
|
||||
FieldsetTitleProps,
|
||||
FieldsetSubtitleProps,
|
||||
FieldsetGroupProps,
|
||||
FieldsetFooterProps,
|
||||
FieldsetContentProps,
|
||||
} from './fieldset'
|
||||
|
||||
export { default as GeistProvider } from './geist-provider'
|
||||
export { default as CssBaseline } from './css-baseline'
|
||||
export type { GeistProviderProps } from './geist-provider'
|
||||
|
||||
export { default as Grid } from './grid'
|
||||
export type { GridProps, GridContainerProps } from './grid'
|
||||
|
||||
export { default as Image } from './image'
|
||||
export type { ImageProps, ImageBrowserProps } from './image'
|
||||
|
||||
export { default as Input } from './input'
|
||||
export type { InputProps, InputPasswordProps } from './input'
|
||||
|
||||
export { default as Keyboard } from './keyboard'
|
||||
export type { KeyboardProps } from './keyboard'
|
||||
|
||||
export { default as Link } from './link'
|
||||
export type { LinkProps } from './link'
|
||||
|
||||
export { default as Loading } from './loading'
|
||||
export type { LoadingProps } from './loading'
|
||||
|
||||
export { default as Modal } from './modal'
|
||||
export type {
|
||||
ModalProps,
|
||||
ModalTitleProps,
|
||||
ModalSubtitleProps,
|
||||
ModalContentProps,
|
||||
ModalActionProps,
|
||||
} from './modal'
|
||||
|
||||
export { default as Note } from './note'
|
||||
export type { NoteProps } from './note'
|
||||
|
||||
export { default as Page } from './page'
|
||||
export type {
|
||||
PageProps,
|
||||
PageHeaderProps,
|
||||
PageContentProps,
|
||||
PageFooterProps,
|
||||
} from './page'
|
||||
|
||||
export { default as Pagination } from './pagination'
|
||||
export type {
|
||||
PaginationProps,
|
||||
PaginationNextProps,
|
||||
PaginationPreviousProps,
|
||||
} from './pagination'
|
||||
|
||||
export { default as Popover } from './popover'
|
||||
export type { PopoverProps, PopoverItemProps } from './popover'
|
||||
|
||||
export { default as Progress } from './progress'
|
||||
export type { ProgressProps } from './progress'
|
||||
|
||||
export { default as Radio } from './radio'
|
||||
export type { RadioProps, RadioGroupProps, RadioDescriptionProps } from './radio'
|
||||
|
||||
export { default as Select } from './select'
|
||||
export type { SelectProps, SelectOptionProps } from './select'
|
||||
|
||||
export { default as Slider } from './slider'
|
||||
export type { SliderProps } from './slider'
|
||||
|
||||
export { default as Snippet } from './snippet'
|
||||
export type { SnippetProps } from './snippet'
|
||||
|
||||
export { default as Spacer } from './spacer'
|
||||
export type { SpacerProps } from './spacer'
|
||||
|
||||
export { default as Spinner } from './spinner'
|
||||
export type { SpinnerProps } from './spinner'
|
||||
|
||||
export { default as Table } from './table'
|
||||
export type { TableProps, TableColumnProps } from './table'
|
||||
|
||||
export { default as Tabs } from './tabs'
|
||||
export type { TabsProps } from './tabs'
|
||||
|
||||
export { default as Tag } from './tag'
|
||||
export type { TagProps } from './tag'
|
||||
|
||||
export { default as Text } from './text'
|
||||
export type { TextProps } from './text'
|
||||
|
||||
export { default as Textarea } from './textarea'
|
||||
export type { TextareaProps } from './textarea'
|
||||
|
||||
export { default as Themes } from './themes'
|
||||
export type { GeistUIThemes, GeistUserTheme } from './themes'
|
||||
|
||||
export { default as Toggle } from './toggle'
|
||||
export type { ToggleProps } from './toggle'
|
||||
|
||||
export { default as Tooltip } from './tooltip'
|
||||
export type { TooltipProps } from './tooltip'
|
||||
|
||||
export { default as Tree } from './tree'
|
||||
export type { TreeProps } from './tree'
|
||||
|
||||
export { default as useAllThemes } from './use-all-themes'
|
||||
export type { AllThemesConfig } from './use-all-themes'
|
||||
|
||||
export { default as useToasts } from './use-toasts'
|
||||
export type { Toast } from './use-toasts'
|
||||
|
||||
export { default as User } from './user'
|
||||
export type { UserProps } from './user'
|
||||
|
||||
export { default as useBodyScroll } from './use-body-scroll'
|
||||
export type { BodyScrollOptions } from './use-body-scroll'
|
||||
|
||||
export { default as useClipboard } from './use-clipboard'
|
||||
export type { UseClipboardOptions } from './use-clipboard'
|
||||
|
||||
export { default as useMediaQuery } from './use-media-query'
|
||||
export type { ResponsiveOptions, ResponsiveBreakpoint } from './use-media-query'
|
||||
|
||||
export { default as useKeyboard, KeyMod, KeyCode } from './use-keyboard'
|
||||
export type { KeyboardOptions, UseKeyboardHandler } from './use-keyboard'
|
||||
|
||||
export { default as useInput } from './input/use-input'
|
||||
export { default as useModal } from './modal/use-modal'
|
||||
export { default as useTabs } from './tabs/use-tabs'
|
||||
export { default as useBodyScroll } from './use-body-scroll'
|
||||
export { default as useClickAway } from './use-click-away'
|
||||
export { default as useClipboard } from './use-clipboard'
|
||||
export { default as useCurrentState } from './use-current-state'
|
||||
export { default as useMediaQuery } from './use-media-query'
|
||||
export { default as useKeyboard, KeyMod, KeyCode } from './use-keyboard'
|
||||
export { default as Avatar } from './avatar'
|
||||
export { default as Text } from './text'
|
||||
export { default as Note } from './note'
|
||||
export { default as Link } from './link'
|
||||
export { default as Button } from './button'
|
||||
export { default as Card } from './card'
|
||||
export { default as Code } from './code'
|
||||
export { default as Display } from './display'
|
||||
export { default as Description } from './description'
|
||||
export { default as Image } from './image'
|
||||
export { default as Spacer } from './spacer'
|
||||
export { default as Tag } from './tag'
|
||||
export { default as Dot } from './dot'
|
||||
export { default as Keyboard } from './keyboard'
|
||||
export { default as Checkbox } from './checkbox'
|
||||
export { default as Fieldset } from './fieldset'
|
||||
export { default as Modal } from './modal'
|
||||
export { default as Spinner } from './spinner'
|
||||
export { default as ButtonDropdown } from './button-dropdown'
|
||||
export { default as Capacity } from './capacity'
|
||||
export { default as Input } from './input'
|
||||
export { default as Radio } from './radio'
|
||||
export { default as Select } from './select'
|
||||
export { default as Tabs } from './tabs'
|
||||
export { default as Progress } from './progress'
|
||||
export { default as Tree } from './tree'
|
||||
export { default as Badge } from './badge'
|
||||
export { default as AutoComplete } from './auto-complete'
|
||||
export { default as Collapse } from './collapse'
|
||||
export { default as Loading } from './loading'
|
||||
export { default as Textarea } from './textarea'
|
||||
export { default as Table } from './table'
|
||||
export { default as Toggle } from './toggle'
|
||||
export { default as Snippet } from './snippet'
|
||||
export { default as Tooltip } from './tooltip'
|
||||
export { default as Popover } from './popover'
|
||||
export { default as Slider } from './slider'
|
||||
export { default as Divider } from './divider'
|
||||
export { default as User } from './user'
|
||||
export { default as Page } from './page'
|
||||
export { default as Grid } from './grid'
|
||||
export { default as ButtonGroup } from './button-group'
|
||||
export { default as Breadcrumbs } from './breadcrumbs'
|
||||
export { default as Pagination } from './pagination'
|
||||
export { default as CssBaseline } from './css-baseline'
|
||||
export { default as useTheme } from './use-theme'
|
||||
|
||||
@@ -9,4 +9,9 @@ export type InputComponentType = typeof Input & {
|
||||
;(Input as InputComponentType).Textarea = Textarea
|
||||
;(Input as InputComponentType).Password = InputPassword
|
||||
|
||||
export type { InputProps } from './input'
|
||||
export type { InputTypes } from './input-props'
|
||||
export type { InputPasswordProps } from './password'
|
||||
export type { TextareaProps } from '../textarea/textarea'
|
||||
export type { BindingsChangeTarget } from './use-input'
|
||||
export default Input as InputComponentType
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import React from 'react'
|
||||
import { NormalTypes } from '../utils/prop-types'
|
||||
|
||||
export type InputTypes = NormalTypes
|
||||
export interface Props {
|
||||
value?: string
|
||||
initialValue?: string
|
||||
placeholder?: string
|
||||
type?: NormalTypes
|
||||
type?: InputTypes
|
||||
hymlType?: string
|
||||
readOnly?: boolean
|
||||
disabled?: boolean
|
||||
@@ -29,7 +30,7 @@ export const defaultProps = {
|
||||
readOnly: false,
|
||||
clearable: false,
|
||||
iconClickable: false,
|
||||
type: 'default' as NormalTypes,
|
||||
type: 'default' as InputTypes,
|
||||
htmlType: 'text',
|
||||
autoComplete: 'off',
|
||||
className: '',
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Keyboard from './keyboard'
|
||||
|
||||
export type { KeyboardProps } from './keyboard'
|
||||
export default Keyboard
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Link from './link'
|
||||
|
||||
export type { LinkProps } from './link'
|
||||
export default Link
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Loading from './loading'
|
||||
|
||||
export type { LoadingProps, LoadingTypes } from './loading'
|
||||
export default Loading
|
||||
|
||||
@@ -4,15 +4,16 @@ import { NormalTypes } from '../utils/prop-types'
|
||||
import { GeistUIThemesPalette } from '../themes/presets'
|
||||
import useScaleable, { withScaleable } from '../use-scaleable'
|
||||
|
||||
export type LoadingTypes = NormalTypes
|
||||
interface Props {
|
||||
type?: NormalTypes
|
||||
type?: LoadingTypes
|
||||
color?: string
|
||||
className?: string
|
||||
spaceRatio?: number
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
type: 'default' as NormalTypes,
|
||||
type: 'default' as LoadingTypes,
|
||||
className: '',
|
||||
spaceRatio: 1,
|
||||
}
|
||||
@@ -21,11 +22,11 @@ type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
|
||||
export type LoadingProps = Props & NativeAttrs
|
||||
|
||||
const getIconBgColor = (
|
||||
type: NormalTypes,
|
||||
type: LoadingTypes,
|
||||
palette: GeistUIThemesPalette,
|
||||
color?: string,
|
||||
) => {
|
||||
const colors: { [key in NormalTypes]: string } = {
|
||||
const colors: { [key in LoadingTypes]: string } = {
|
||||
default: palette.accents_6,
|
||||
secondary: palette.secondary,
|
||||
success: palette.success,
|
||||
@@ -46,11 +47,10 @@ const LoadingComponent: React.FC<React.PropsWithChildren<LoadingProps>> = ({
|
||||
}: React.PropsWithChildren<LoadingProps> & typeof defaultProps) => {
|
||||
const theme = useTheme()
|
||||
const { SCALES } = useScaleable()
|
||||
const bgColor = useMemo(() => getIconBgColor(type, theme.palette, color), [
|
||||
type,
|
||||
theme.palette,
|
||||
color,
|
||||
])
|
||||
const bgColor = useMemo(
|
||||
() => getIconBgColor(type, theme.palette, color),
|
||||
[type, theme.palette, color],
|
||||
)
|
||||
|
||||
return (
|
||||
<div className={`loading-container ${className}`} {...props}>
|
||||
|
||||
@@ -15,4 +15,9 @@ export type ModalComponentType = typeof Modal & {
|
||||
;(Modal as ModalComponentType).Content = ModalContent
|
||||
;(Modal as ModalComponentType).Action = ModalAction
|
||||
|
||||
export type { ModalProps } from './modal'
|
||||
export type { ModalTitleProps } from './modal-title'
|
||||
export type { ModalSubtitleProps } from './modal-subtitle'
|
||||
export type { ModalActionProps } from './modal-action'
|
||||
export type { ModalContentProps } from './modal-content'
|
||||
export default Modal as ModalComponentType
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useMemo } from 'react'
|
||||
import React, { MouseEvent, useEffect, useMemo } from 'react'
|
||||
import { createPortal } from 'react-dom'
|
||||
import usePortal from '../utils/use-portal'
|
||||
import ModalWrapper from './modal-wrapper'
|
||||
@@ -15,6 +15,7 @@ interface Props {
|
||||
disableBackdropClick?: boolean
|
||||
onClose?: () => void
|
||||
onOpen?: () => void
|
||||
onContentClick?: (event: MouseEvent<HTMLElement>) => void
|
||||
open?: boolean
|
||||
wrapClassName?: string
|
||||
}
|
||||
@@ -28,12 +29,13 @@ type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
|
||||
export type ModalProps = Props & NativeAttrs
|
||||
|
||||
const ModalComponent: React.FC<React.PropsWithChildren<ModalProps>> = ({
|
||||
children,
|
||||
disableBackdropClick,
|
||||
onClose,
|
||||
onOpen,
|
||||
open,
|
||||
onOpen,
|
||||
onClose,
|
||||
children,
|
||||
wrapClassName,
|
||||
onContentClick,
|
||||
disableBackdropClick,
|
||||
}: React.PropsWithChildren<ModalProps> & typeof defaultProps) => {
|
||||
const portal = usePortal('modal')
|
||||
const { SCALES } = useScaleable()
|
||||
@@ -76,7 +78,11 @@ const ModalComponent: React.FC<React.PropsWithChildren<ModalProps>> = ({
|
||||
if (!portal) return null
|
||||
return createPortal(
|
||||
<ModalContext.Provider value={modalConfig}>
|
||||
<Backdrop onClick={closeFromBackdrop} visible={visible} width={SCALES.width(26)}>
|
||||
<Backdrop
|
||||
onClick={closeFromBackdrop}
|
||||
onContentClick={onContentClick}
|
||||
visible={visible}
|
||||
width={SCALES.width(26)}>
|
||||
<ModalWrapper visible={visible} className={wrapClassName}>
|
||||
{withoutActionsChildren}
|
||||
{hasActions && <ModalActions>{ActionsChildren}</ModalActions>}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import Note from './note'
|
||||
import { NoteProps } from './note'
|
||||
|
||||
export type Props = NoteProps
|
||||
export type { NoteProps, NoteTypes } from './note'
|
||||
export default Note
|
||||
|
||||
@@ -4,15 +4,16 @@ import { NormalTypes } from '../utils/prop-types'
|
||||
import { GeistUIThemes } from '../themes/presets'
|
||||
import useScaleable, { withScaleable } from '../use-scaleable'
|
||||
|
||||
export type NoteTypes = NormalTypes
|
||||
interface Props {
|
||||
type?: NormalTypes
|
||||
type?: NoteTypes
|
||||
label?: string | boolean
|
||||
filled?: boolean
|
||||
className?: string
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
type: 'default' as NormalTypes,
|
||||
type: 'default' as NoteTypes,
|
||||
label: 'note' as string | boolean,
|
||||
filled: false,
|
||||
className: '',
|
||||
@@ -21,8 +22,8 @@ const defaultProps = {
|
||||
type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
|
||||
export type NoteProps = Props & NativeAttrs
|
||||
|
||||
const getStatusColor = (type: NormalTypes, filled: boolean, theme: GeistUIThemes) => {
|
||||
const colors: { [key in NormalTypes]?: string } = {
|
||||
const getStatusColor = (type: NoteTypes, filled: boolean, theme: GeistUIThemes) => {
|
||||
const colors: { [key in NoteTypes]?: string } = {
|
||||
secondary: theme.palette.secondary,
|
||||
success: theme.palette.success,
|
||||
warning: theme.palette.warning,
|
||||
|
||||
@@ -14,4 +14,8 @@ export type PageComponentType = typeof Page & {
|
||||
;(Page as PageComponentType).Body = PageContent
|
||||
;(Page as PageComponentType).Footer = PageFooter
|
||||
|
||||
export type { PageProps, PageRenderMode } from './page'
|
||||
export type { PageHeaderProps } from './page-header'
|
||||
export type { PageContentProps } from './page-content'
|
||||
export type { PageFooterProps } from './page-footer'
|
||||
export default Page as PageComponentType
|
||||
|
||||
@@ -10,12 +10,12 @@ const defaultProps = {
|
||||
}
|
||||
|
||||
type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
|
||||
export type PageHeaderProps = Props & NativeAttrs
|
||||
export type PageFooterProps = Props & NativeAttrs
|
||||
|
||||
const PageFooterComponent: React.FC<React.PropsWithChildren<PageHeaderProps>> = ({
|
||||
const PageFooterComponent: React.FC<React.PropsWithChildren<PageFooterProps>> = ({
|
||||
children,
|
||||
...props
|
||||
}: React.PropsWithChildren<PageHeaderProps> & typeof defaultProps) => {
|
||||
}: React.PropsWithChildren<PageFooterProps> & typeof defaultProps) => {
|
||||
const { SCALES } = useScaleable()
|
||||
|
||||
return (
|
||||
|
||||
@@ -34,15 +34,15 @@ const DotStyles: React.FC<unknown> = () => (
|
||||
)
|
||||
|
||||
type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
|
||||
export type NoteProps = Props & NativeAttrs
|
||||
export type PageProps = Props & NativeAttrs
|
||||
|
||||
const PageComponent: React.FC<React.PropsWithChildren<NoteProps>> = ({
|
||||
const PageComponent: React.FC<React.PropsWithChildren<PageProps>> = ({
|
||||
children,
|
||||
render,
|
||||
dotBackdrop,
|
||||
className,
|
||||
...props
|
||||
}: React.PropsWithChildren<NoteProps> & typeof defaultProps) => {
|
||||
}: React.PropsWithChildren<PageProps> & typeof defaultProps) => {
|
||||
const theme = useTheme()
|
||||
const { SCALES } = useScaleable()
|
||||
const showDot = useMemo<boolean>(() => {
|
||||
|
||||
@@ -9,4 +9,7 @@ export type PaginationComponentType = typeof Pagination & {
|
||||
;(Pagination as PaginationComponentType).Previous = PaginationPrevious
|
||||
;(Pagination as PaginationComponentType).Next = PaginationNext
|
||||
|
||||
export type { PaginationProps } from './pagination'
|
||||
export type { PaginationPreviousProps } from './pagination-previous'
|
||||
export type { PaginationNextProps } from './pagination-next'
|
||||
export default Pagination as PaginationComponentType
|
||||
|
||||
@@ -2,9 +2,9 @@ import React from 'react'
|
||||
import PaginationItem from './pagination-item'
|
||||
import { usePaginationContext } from './pagination-context'
|
||||
|
||||
export type PaginationNextProps = React.ButtonHTMLAttributes<any>
|
||||
export type PaginationPreviousProps = React.ButtonHTMLAttributes<any>
|
||||
|
||||
const PaginationPrevious: React.FC<React.PropsWithChildren<PaginationNextProps>> = ({
|
||||
const PaginationPrevious: React.FC<React.PropsWithChildren<PaginationPreviousProps>> = ({
|
||||
children,
|
||||
...props
|
||||
}) => {
|
||||
|
||||
@@ -2,11 +2,10 @@
|
||||
|
||||
exports[`Popover should render react-node 1`] = `
|
||||
"<div class=\\"tooltip \\"><div></div><style>
|
||||
:global(.tooltip-content.popover > .inner) {
|
||||
padding: 8pt 0;
|
||||
text-align: center;
|
||||
}
|
||||
</style><style>
|
||||
:global(.tooltip-content.popover > .inner) {
|
||||
padding: calc(0.9 * 16px) 0 calc(0.9 * 16px) 0;
|
||||
}
|
||||
</style><style>
|
||||
.tooltip {
|
||||
width: max-content;
|
||||
display: inline-block;
|
||||
@@ -16,11 +15,10 @@ exports[`Popover should render react-node 1`] = `
|
||||
|
||||
exports[`Popover should work with different placement 1`] = `
|
||||
"<div class=\\"tooltip \\"><div></div><style>
|
||||
:global(.tooltip-content.popover > .inner) {
|
||||
padding: 8pt 0;
|
||||
text-align: center;
|
||||
}
|
||||
</style><style>
|
||||
:global(.tooltip-content.popover > .inner) {
|
||||
padding: calc(0.9 * 16px) 0 calc(0.9 * 16px) 0;
|
||||
}
|
||||
</style><style>
|
||||
.tooltip {
|
||||
width: max-content;
|
||||
display: inline-block;
|
||||
|
||||
@@ -31,6 +31,30 @@ describe('Popover', () => {
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
|
||||
it('should work correctly with props', async () => {
|
||||
const handler = jest.fn()
|
||||
const Demos: React.FC<{ visible?: boolean }> = ({ visible }) => {
|
||||
return (
|
||||
<Popover visible={visible} onVisibleChange={handler} content="test">
|
||||
<div />
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
const wrapper = mount(<Demos />)
|
||||
expectPopoverIsHidden(wrapper)
|
||||
|
||||
wrapper.setProps({ visible: true })
|
||||
await updateWrapper(wrapper, 350)
|
||||
expectPopoverIsShow(wrapper)
|
||||
expect(handler).toBeCalled()
|
||||
|
||||
wrapper.setProps({ visible: false })
|
||||
await updateWrapper(wrapper, 350)
|
||||
expectPopoverIsHidden(wrapper)
|
||||
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
|
||||
it('should render react-node', async () => {
|
||||
const wrapper = mount(
|
||||
<Popover content={<p id="test">custom-content</p>}>
|
||||
@@ -98,4 +122,75 @@ describe('Popover', () => {
|
||||
expect(line.length).not.toBe(0)
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
|
||||
it('should close popover when item clicked', async () => {
|
||||
const wrapper = mount(
|
||||
<Popover content="test">
|
||||
<Popover.Item id="item" />
|
||||
</Popover>,
|
||||
)
|
||||
expectPopoverIsHidden(wrapper)
|
||||
|
||||
wrapper.find('.tooltip').simulate('click', nativeEvent)
|
||||
await updateWrapper(wrapper, 350)
|
||||
expectPopoverIsShow(wrapper)
|
||||
|
||||
const item = wrapper.find('#item').at(0)
|
||||
|
||||
item.simulate('click', nativeEvent)
|
||||
await updateWrapper(wrapper, 350)
|
||||
expectPopoverIsHidden(wrapper)
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
|
||||
it('should prevent close popover when item clicked', async () => {
|
||||
const wrapper = mount(
|
||||
<Popover content="test">
|
||||
<Popover.Item id="item" disableAutoClose />
|
||||
<Popover.Item id="item2" />
|
||||
</Popover>,
|
||||
)
|
||||
expectPopoverIsHidden(wrapper)
|
||||
|
||||
wrapper.find('.tooltip').simulate('click', nativeEvent)
|
||||
await updateWrapper(wrapper, 350)
|
||||
expectPopoverIsShow(wrapper)
|
||||
|
||||
const item = wrapper.find('#item').at(0)
|
||||
const item2 = wrapper.find('#item2').at(0)
|
||||
|
||||
item.simulate('click', nativeEvent)
|
||||
await updateWrapper(wrapper, 350)
|
||||
expectPopoverIsShow(wrapper)
|
||||
|
||||
item2.simulate('click', nativeEvent)
|
||||
await updateWrapper(wrapper, 350)
|
||||
expectPopoverIsHidden(wrapper)
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
|
||||
it('should prevent all items', async () => {
|
||||
const wrapper = mount(
|
||||
<Popover content="test" disableItemsAutoClose>
|
||||
<Popover.Item id="item" />
|
||||
<Popover.Item id="item2" />
|
||||
</Popover>,
|
||||
)
|
||||
expectPopoverIsHidden(wrapper)
|
||||
|
||||
wrapper.find('.tooltip').simulate('click', nativeEvent)
|
||||
await updateWrapper(wrapper, 350)
|
||||
expectPopoverIsShow(wrapper)
|
||||
|
||||
const item = wrapper.find('#item').at(0)
|
||||
const item2 = wrapper.find('#item2').at(0)
|
||||
|
||||
item.simulate('click', nativeEvent)
|
||||
await updateWrapper(wrapper, 350)
|
||||
expectPopoverIsShow(wrapper)
|
||||
item2.simulate('click', nativeEvent)
|
||||
await updateWrapper(wrapper, 350)
|
||||
expectPopoverIsShow(wrapper)
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import Popover from './popover'
|
||||
import PopoverItem from './popover-item'
|
||||
|
||||
Popover.Item = PopoverItem
|
||||
Popover.Option = PopoverItem
|
||||
export type PopoverComponentType = typeof Popover & {
|
||||
Item: typeof PopoverItem
|
||||
Option: typeof PopoverItem
|
||||
}
|
||||
;(Popover as PopoverComponentType).Item = PopoverItem
|
||||
;(Popover as PopoverComponentType).Option = PopoverItem
|
||||
|
||||
export default Popover
|
||||
export type { PopoverProps, PopoverTriggerTypes, PopoverPlacement } from './popover'
|
||||
export type { PopoverItemProps } from './popover-item'
|
||||
export default Popover as PopoverComponentType
|
||||
|
||||
15
components/popover/popover-context.ts
Normal file
15
components/popover/popover-context.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import React, { useContext } from 'react'
|
||||
|
||||
export type PopoverConfig = {
|
||||
disableItemsAutoClose: boolean
|
||||
onItemClick: (e: React.MouseEvent<HTMLDivElement>) => void
|
||||
}
|
||||
|
||||
const defaultContext = {
|
||||
disableItemsAutoClose: false,
|
||||
onItemClick: () => {},
|
||||
}
|
||||
|
||||
export const PopoverContext = React.createContext<PopoverConfig>(defaultContext)
|
||||
|
||||
export const usePopoverContext = () => useContext<PopoverConfig>(PopoverContext)
|
||||
@@ -1,88 +1,98 @@
|
||||
import React from 'react'
|
||||
import useTheme from '../use-theme'
|
||||
import useScaleable, { withScaleable } from '../use-scaleable'
|
||||
import { usePopoverContext } from './popover-context'
|
||||
|
||||
interface Props {
|
||||
line?: boolean
|
||||
title?: boolean
|
||||
disableAutoClose?: boolean
|
||||
onClick?: (e: React.MouseEvent<HTMLDivElement>) => void
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
line: false,
|
||||
title: false,
|
||||
disableAutoClose: false,
|
||||
className: '',
|
||||
}
|
||||
|
||||
type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
|
||||
export type PopoverItemProps = Props & NativeAttrs
|
||||
|
||||
const PopoverItem: React.FC<React.PropsWithChildren<PopoverItemProps>> = ({
|
||||
const PopoverItemComponent: React.FC<React.PropsWithChildren<PopoverItemProps>> = ({
|
||||
children,
|
||||
line,
|
||||
title,
|
||||
className,
|
||||
onClick,
|
||||
disableAutoClose,
|
||||
...props
|
||||
}: React.PropsWithChildren<PopoverItemProps> & typeof defaultProps) => {
|
||||
const theme = useTheme()
|
||||
const { SCALES } = useScaleable()
|
||||
const { disableItemsAutoClose, onItemClick } = usePopoverContext()
|
||||
const hasHandler = Boolean(onClick)
|
||||
const dontCloseByClick = disableAutoClose || disableItemsAutoClose || title || line
|
||||
const clickHandler = (event: React.MouseEvent<HTMLDivElement>) => {
|
||||
onClick && onClick(event)
|
||||
if (dontCloseByClick) {
|
||||
return event.stopPropagation()
|
||||
}
|
||||
onItemClick(event)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={`item ${line ? 'line' : ''} ${title ? 'title' : ''} ${className}`}
|
||||
onClick={clickHandler}
|
||||
{...props}>
|
||||
{children}
|
||||
<style jsx>{`
|
||||
.item {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
padding: 0.5rem ${theme.layout.gap};
|
||||
color: ${theme.palette.accents_5};
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
text-align: left;
|
||||
transition: color 0.1s ease 0s, background-color 0.1s ease 0s;
|
||||
transition: color, background-color 150ms linear;
|
||||
line-height: 1.25em;
|
||||
font-size: ${SCALES.font(0.875)};
|
||||
width: ${SCALES.width(1, 'auto')};
|
||||
height: ${SCALES.height(1, 'auto')};
|
||||
margin: ${SCALES.mt(0)} ${SCALES.mr(0)} ${SCALES.mb(0)} ${SCALES.ml(0)};
|
||||
padding: ${SCALES.pt(0.5)} ${SCALES.pr(0.75)} ${SCALES.pb(0.5)}
|
||||
${SCALES.pl(0.75)};
|
||||
cursor: ${hasHandler ? 'pointer' : 'default'};
|
||||
}
|
||||
|
||||
.item:hover {
|
||||
color: ${theme.palette.foreground};
|
||||
}
|
||||
|
||||
.item > :global(*) {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.item > :global(.link) {
|
||||
width: 100%;
|
||||
padding: 0.5rem ${theme.layout.gap};
|
||||
margin: -0.5rem -${theme.layout.gap};
|
||||
}
|
||||
|
||||
.item.line {
|
||||
line-height: 0;
|
||||
height: 0;
|
||||
padding: 0;
|
||||
border-top: 1px solid ${theme.palette.border};
|
||||
margin: 0.5rem 0;
|
||||
width: 100%;
|
||||
background-color: ${theme.palette.border};
|
||||
height: ${SCALES.height(0.0625)};
|
||||
margin: ${SCALES.mt(0.35)} ${SCALES.mr(0)} ${SCALES.mb(0.35)} ${SCALES.ml(0)};
|
||||
width: ${SCALES.width(1, '100%')};
|
||||
}
|
||||
|
||||
.item.title {
|
||||
padding: 1.15rem;
|
||||
font-weight: 500;
|
||||
font-size: 0.83rem;
|
||||
font-size: ${SCALES.font(0.925)};
|
||||
color: ${theme.palette.foreground};
|
||||
}
|
||||
|
||||
.item.title:first-of-type {
|
||||
padding-top: 0.6rem;
|
||||
padding-bottom: 0.6rem;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
{title && <PopoverItem line title={false} className="" />}
|
||||
{title && <PopoverItem line title={false} />}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
PopoverItem.defaultProps = defaultProps
|
||||
PopoverItem.displayName = 'GeistPopoverItem'
|
||||
PopoverItemComponent.defaultProps = defaultProps
|
||||
PopoverItemComponent.displayName = 'GeistPopoverItem'
|
||||
const PopoverItem = withScaleable(PopoverItemComponent)
|
||||
export default PopoverItem
|
||||
|
||||
@@ -1,20 +1,36 @@
|
||||
import React, { useMemo } from 'react'
|
||||
import useTheme from '../use-theme'
|
||||
import Tooltip, { TooltipProps } from '../tooltip/tooltip'
|
||||
import PopoverItem from '../popover/popover-item'
|
||||
import React, { useEffect, useMemo, useState } from 'react'
|
||||
import Tooltip, {
|
||||
TooltipOnVisibleChange,
|
||||
TooltipProps,
|
||||
TooltipTypes,
|
||||
} from '../tooltip/tooltip'
|
||||
import { Placement, TriggerTypes } from '../utils/prop-types'
|
||||
import { getReactNode } from '../utils/collections'
|
||||
import useScaleable, { withScaleable } from '../use-scaleable'
|
||||
import { PopoverContext, PopoverConfig } from './popover-context'
|
||||
|
||||
export type PopoverTriggerTypes = TriggerTypes
|
||||
export type PopoverPlacement = Placement
|
||||
interface Props {
|
||||
content?: React.ReactNode | (() => React.ReactNode)
|
||||
trigger?: TriggerTypes
|
||||
trigger?: PopoverTriggerTypes
|
||||
placement?: Placement
|
||||
disableItemsAutoClose?: boolean
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
trigger: 'click' as TriggerTypes,
|
||||
disableItemsAutoClose: false,
|
||||
trigger: 'click' as PopoverTriggerTypes,
|
||||
placement: 'bottom' as Placement,
|
||||
portalClassName: '',
|
||||
initialVisible: false,
|
||||
hideArrow: false,
|
||||
type: 'default' as TooltipTypes,
|
||||
enterDelay: 100,
|
||||
leaveDelay: 150,
|
||||
offset: 12,
|
||||
className: '',
|
||||
onVisibleChange: (() => {}) as TooltipOnVisibleChange,
|
||||
}
|
||||
|
||||
type ExcludeTooltipProps = {
|
||||
@@ -26,43 +42,62 @@ type ExcludeTooltipProps = {
|
||||
|
||||
export type PopoverProps = Props & Omit<TooltipProps, keyof ExcludeTooltipProps>
|
||||
|
||||
const Popover: React.FC<React.PropsWithChildren<PopoverProps>> = ({
|
||||
const PopoverComponent: React.FC<React.PropsWithChildren<PopoverProps>> = ({
|
||||
content,
|
||||
children,
|
||||
trigger,
|
||||
placement,
|
||||
initialVisible,
|
||||
portalClassName,
|
||||
disableItemsAutoClose,
|
||||
onVisibleChange,
|
||||
visible: customVisible,
|
||||
...props
|
||||
}) => {
|
||||
const theme = useTheme()
|
||||
}: React.PropsWithChildren<PopoverProps> & typeof defaultProps) => {
|
||||
const { SCALES } = useScaleable()
|
||||
const [visible, setVisible] = useState<boolean>(initialVisible)
|
||||
const textNode = useMemo(() => getReactNode(content), [content])
|
||||
const onChildClick = () => {
|
||||
onPopoverVisibleChange(false)
|
||||
}
|
||||
const value = useMemo<PopoverConfig>(
|
||||
() => ({
|
||||
onItemClick: onChildClick,
|
||||
disableItemsAutoClose,
|
||||
}),
|
||||
[disableItemsAutoClose],
|
||||
)
|
||||
const onPopoverVisibleChange = (next: boolean) => {
|
||||
setVisible(next)
|
||||
onVisibleChange(next)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (customVisible === undefined) return
|
||||
onPopoverVisibleChange(customVisible)
|
||||
}, [customVisible])
|
||||
return (
|
||||
<Tooltip
|
||||
text={textNode}
|
||||
trigger={trigger}
|
||||
placement={placement}
|
||||
portalClassName={`popover ${portalClassName}`}
|
||||
{...props}>
|
||||
{children}
|
||||
<style jsx>{`
|
||||
:global(.tooltip-content.popover > .inner) {
|
||||
padding: ${theme.layout.gapHalf} 0;
|
||||
text-align: center;
|
||||
}
|
||||
`}</style>
|
||||
</Tooltip>
|
||||
<PopoverContext.Provider value={value}>
|
||||
<Tooltip
|
||||
text={textNode}
|
||||
trigger={trigger}
|
||||
placement={placement}
|
||||
portalClassName={`popover ${portalClassName}`}
|
||||
visible={visible}
|
||||
onVisibleChange={onPopoverVisibleChange}
|
||||
{...props}>
|
||||
{children}
|
||||
<style jsx>{`
|
||||
:global(.tooltip-content.popover > .inner) {
|
||||
padding: ${SCALES.pt(0.9)} ${SCALES.pr(0)} ${SCALES.pb(0.9)} ${SCALES.pl(0)};
|
||||
}
|
||||
`}</style>
|
||||
</Tooltip>
|
||||
</PopoverContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
type PopoverComponent<P = {}> = React.FC<P> & {
|
||||
Item: typeof PopoverItem
|
||||
Option: typeof PopoverItem
|
||||
}
|
||||
type ComponentProps = Partial<typeof defaultProps> &
|
||||
Omit<Props, keyof typeof defaultProps> &
|
||||
Partial<Omit<TooltipProps, keyof ExcludeTooltipProps>>
|
||||
|
||||
Popover.defaultProps = defaultProps
|
||||
|
||||
export default Popover as PopoverComponent<ComponentProps>
|
||||
PopoverComponent.defaultProps = defaultProps
|
||||
PopoverComponent.displayName = 'GeistPopover'
|
||||
const Popover = withScaleable(PopoverComponent)
|
||||
export default Popover
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Progress from './progress'
|
||||
|
||||
export type { ProgressProps, ProgressColors, ProgressTypes } from './progress'
|
||||
export default Progress
|
||||
|
||||
@@ -8,6 +8,7 @@ import useScaleable, { withScaleable } from '../use-scaleable'
|
||||
export type ProgressColors = {
|
||||
[key: number]: string
|
||||
}
|
||||
export type ProgressTypes = NormalTypes
|
||||
|
||||
interface Props {
|
||||
value?: number
|
||||
@@ -15,14 +16,14 @@ interface Props {
|
||||
fixedTop?: boolean
|
||||
fixedBottom?: boolean
|
||||
colors?: ProgressColors
|
||||
type?: NormalTypes
|
||||
type?: ProgressTypes
|
||||
className?: string
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
value: 0,
|
||||
max: 100,
|
||||
type: 'default' as NormalTypes,
|
||||
type: 'default' as ProgressTypes,
|
||||
fixedTop: false,
|
||||
fixedBottom: false,
|
||||
className: '',
|
||||
@@ -34,10 +35,10 @@ export type ProgressProps = Props & NativeAttrs
|
||||
const getCurrentColor = (
|
||||
ratio: number,
|
||||
palette: GeistUIThemesPalette,
|
||||
type: NormalTypes,
|
||||
type: ProgressTypes,
|
||||
colors: ProgressColors = {},
|
||||
): string => {
|
||||
const defaultColors: { [key in NormalTypes]: string } = {
|
||||
const defaultColors: { [key in ProgressTypes]: string } = {
|
||||
default: palette.foreground,
|
||||
success: palette.success,
|
||||
secondary: palette.secondary,
|
||||
|
||||
@@ -11,4 +11,7 @@ export type RadioComponentType = typeof Radio & {
|
||||
;(Radio as RadioComponentType).Description = RadioDescription
|
||||
;(Radio as RadioComponentType).Desc = RadioDescription
|
||||
|
||||
export type { RadioProps, RadioEvent, RadioEventTarget, RadioTypes } from './radio'
|
||||
export type { RadioGroupProps } from './radio-group'
|
||||
export type { RadioDescriptionProps } from './radio-description'
|
||||
export default Radio as RadioComponentType
|
||||
|
||||
@@ -8,10 +8,10 @@ import { NormalTypes } from '../utils/prop-types'
|
||||
import { getColors } from './styles'
|
||||
import useScaleable, { withScaleable } from '../use-scaleable'
|
||||
|
||||
interface RadioEventTarget {
|
||||
export type RadioTypes = NormalTypes
|
||||
export interface RadioEventTarget {
|
||||
checked: boolean
|
||||
}
|
||||
|
||||
export interface RadioEvent {
|
||||
target: RadioEventTarget
|
||||
stopPropagation: () => void
|
||||
@@ -22,14 +22,14 @@ export interface RadioEvent {
|
||||
interface Props {
|
||||
checked?: boolean
|
||||
value?: string | number
|
||||
type?: NormalTypes
|
||||
type?: RadioTypes
|
||||
className?: string
|
||||
disabled?: boolean
|
||||
onChange?: (e: RadioEvent) => void
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
type: 'default' as NormalTypes,
|
||||
type: 'default' as RadioTypes,
|
||||
disabled: false,
|
||||
className: '',
|
||||
}
|
||||
@@ -65,10 +65,10 @@ const RadioComponent: React.FC<React.PropsWithChildren<RadioProps>> = ({
|
||||
}, [groupValue, radioValue])
|
||||
}
|
||||
|
||||
const { label, border, bg } = useMemo(() => getColors(theme.palette, type), [
|
||||
theme.palette,
|
||||
type,
|
||||
])
|
||||
const { label, border, bg } = useMemo(
|
||||
() => getColors(theme.palette, type),
|
||||
[theme.palette, type],
|
||||
)
|
||||
|
||||
const isDisabled = useMemo(() => disabled || disabledAll, [disabled, disabledAll])
|
||||
const changeHandler = (event: React.ChangeEvent) => {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import Row from './row'
|
||||
import { RowProps } from './row'
|
||||
|
||||
export type Props = RowProps
|
||||
export type { RowProps } from './row'
|
||||
export default Row
|
||||
|
||||
@@ -6,4 +6,6 @@ export type SelectComponentType = typeof Select & {
|
||||
}
|
||||
;(Select as SelectComponentType).Option = SelectOption
|
||||
|
||||
export type { SelectProps, SelectTypes } from './select'
|
||||
export type { SelectOptionProps } from './select-option'
|
||||
export default Select as SelectComponentType
|
||||
|
||||
@@ -13,9 +13,10 @@ import { getColors } from './styles'
|
||||
import Ellipsis from '../shared/ellipsis'
|
||||
import useScaleable, { withScaleable } from '../use-scaleable'
|
||||
|
||||
export type SelectTypes = NormalTypes
|
||||
interface Props {
|
||||
disabled?: boolean
|
||||
type?: NormalTypes
|
||||
type?: SelectTypes
|
||||
value?: string | string[]
|
||||
initialValue?: string | string[]
|
||||
placeholder?: React.ReactNode | string
|
||||
@@ -33,7 +34,7 @@ interface Props {
|
||||
|
||||
const defaultProps = {
|
||||
disabled: false,
|
||||
type: 'default' as NormalTypes,
|
||||
type: 'default' as SelectTypes,
|
||||
icon: SelectIcon as React.ComponentType,
|
||||
pure: false,
|
||||
multiple: false,
|
||||
|
||||
@@ -48,15 +48,15 @@ describe('Backdrop', () => {
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
|
||||
it('should be prevent event from the container', () => {
|
||||
it('should be pass event from the container', () => {
|
||||
const handler = jest.fn()
|
||||
const wrapper = mount(
|
||||
<Backdrop onClick={handler} visible>
|
||||
<Backdrop visible onContentClick={handler}>
|
||||
<span>test-value</span>
|
||||
</Backdrop>,
|
||||
)
|
||||
wrapper.find('.content').simulate('click', nativeEvent)
|
||||
expect(handler).not.toHaveBeenCalled()
|
||||
expect(handler).toHaveBeenCalled()
|
||||
handler.mockRestore()
|
||||
})
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { MouseEvent, useCallback } from 'react'
|
||||
import React, { MouseEvent } from 'react'
|
||||
import useTheme from '../use-theme'
|
||||
import CssTransition from './css-transition'
|
||||
import useCurrentState from '../utils/use-current-state'
|
||||
@@ -7,11 +7,13 @@ interface Props {
|
||||
onClick?: (event: MouseEvent<HTMLElement>) => void
|
||||
visible?: boolean
|
||||
width?: string
|
||||
onContentClick?: (event: MouseEvent<HTMLElement>) => void
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
onClick: () => {},
|
||||
visible: false,
|
||||
onContentClick: () => {},
|
||||
}
|
||||
|
||||
type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
|
||||
@@ -23,6 +25,7 @@ const Backdrop: React.FC<React.PropsWithChildren<BackdropProps>> = React.memo(
|
||||
onClick,
|
||||
visible,
|
||||
width,
|
||||
onContentClick,
|
||||
...props
|
||||
}: React.PropsWithChildren<BackdropProps> & typeof defaultProps) => {
|
||||
const theme = useTheme()
|
||||
@@ -31,9 +34,6 @@ const Backdrop: React.FC<React.PropsWithChildren<BackdropProps>> = React.memo(
|
||||
if (IsContentMouseDownRef.current) return
|
||||
onClick && onClick(event)
|
||||
}
|
||||
const childrenClickHandler = useCallback((event: MouseEvent<HTMLElement>) => {
|
||||
event.stopPropagation()
|
||||
}, [])
|
||||
const mouseUpHandler = () => {
|
||||
if (!IsContentMouseDownRef.current) return
|
||||
const timer = setTimeout(() => {
|
||||
@@ -51,7 +51,7 @@ const Backdrop: React.FC<React.PropsWithChildren<BackdropProps>> = React.memo(
|
||||
{...props}>
|
||||
<div className="layer" />
|
||||
<div
|
||||
onClick={childrenClickHandler}
|
||||
onClick={onContentClick}
|
||||
className="content"
|
||||
onMouseDown={() => setIsContentMouseDown(true)}>
|
||||
{children}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Slider from './slider'
|
||||
|
||||
export type { SliderProps, SliderTypes } from './slider'
|
||||
export default Slider
|
||||
|
||||
@@ -15,10 +15,11 @@ import { getColors } from './styles'
|
||||
import { NormalTypes } from '../utils/prop-types'
|
||||
import useScaleable, { withScaleable } from '../use-scaleable'
|
||||
|
||||
export type SliderTypes = NormalTypes
|
||||
interface Props {
|
||||
hideValue?: boolean
|
||||
value?: number
|
||||
type?: NormalTypes
|
||||
type?: SliderTypes
|
||||
initialValue?: number
|
||||
step?: number
|
||||
max?: number
|
||||
@@ -31,7 +32,7 @@ interface Props {
|
||||
|
||||
const defaultProps = {
|
||||
hideValue: false,
|
||||
type: 'default' as NormalTypes,
|
||||
type: 'default' as SliderTypes,
|
||||
initialValue: 0,
|
||||
step: 1,
|
||||
min: 0,
|
||||
@@ -92,11 +93,10 @@ const SliderComponent: React.FC<React.PropsWithChildren<SliderProps>> = ({
|
||||
const sliderRef = useRef<HTMLDivElement>(null)
|
||||
const dotRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const currentRatio = useMemo(() => ((value - min) / (max - min)) * 100, [
|
||||
value,
|
||||
max,
|
||||
min,
|
||||
])
|
||||
const currentRatio = useMemo(
|
||||
() => ((value - min) / (max - min)) * 100,
|
||||
[value, max, min],
|
||||
)
|
||||
|
||||
const setLastOffsetManually = (val: number) => {
|
||||
const width = getRefWidth(sliderRef)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import Snippet from './snippet'
|
||||
|
||||
export type { SnippetProps, ToastTypes } from './snippet'
|
||||
export type { CopyTypes, SnippetTypes } from '../utils/prop-types'
|
||||
export default Snippet
|
||||
|
||||
@@ -7,11 +7,12 @@ import useClipboard from '../utils/use-clipboard'
|
||||
import useToasts from '../use-toasts'
|
||||
import useScaleable, { withScaleable } from '../use-scaleable'
|
||||
|
||||
export type ToastTypes = NormalTypes
|
||||
interface Props {
|
||||
text?: string | string[]
|
||||
symbol?: string
|
||||
toastText?: string
|
||||
toastType?: NormalTypes
|
||||
toastType?: ToastTypes
|
||||
filled?: boolean
|
||||
copy?: CopyTypes
|
||||
type?: SnippetTypes
|
||||
@@ -22,7 +23,7 @@ const defaultProps = {
|
||||
filled: false,
|
||||
symbol: '$',
|
||||
toastText: 'Copied to clipboard!',
|
||||
toastType: 'success' as NormalTypes,
|
||||
toastType: 'success' as ToastTypes,
|
||||
copy: 'default' as CopyTypes,
|
||||
type: 'default' as SnippetTypes,
|
||||
className: '',
|
||||
@@ -57,11 +58,10 @@ const SnippetComponent: React.FC<React.PropsWithChildren<SnippetProps>> = ({
|
||||
const ref = useRef<HTMLPreElement>(null)
|
||||
const isMultiLine = text && Array.isArray(text)
|
||||
|
||||
const style = useMemo(() => getStyles(type, theme.palette, filled), [
|
||||
type,
|
||||
theme.palette,
|
||||
filled,
|
||||
])
|
||||
const style = useMemo(
|
||||
() => getStyles(type, theme.palette, filled),
|
||||
[type, theme.palette, filled],
|
||||
)
|
||||
const showCopyIcon = useMemo(() => copyType !== 'prevent', [copyType])
|
||||
const childText = useMemo<string | undefined | null>(() => {
|
||||
if (isMultiLine) return textArrayToString(text as string[])
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import Spacer from './spacer'
|
||||
import { SpacerProps } from './spacer'
|
||||
|
||||
export type Props = SpacerProps
|
||||
export type { SpacerProps } from './spacer'
|
||||
export default Spacer
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Spinner from './spinner'
|
||||
|
||||
export type { SpinnerProps } from './spinner'
|
||||
export default Spinner
|
||||
|
||||
@@ -6,4 +6,19 @@ export type TableComponentType = typeof Table & {
|
||||
}
|
||||
;(Table as TableComponentType).Column = TableColumn
|
||||
|
||||
export type {
|
||||
TableProps,
|
||||
TableOnRow,
|
||||
TableOnChange,
|
||||
TableOnCell,
|
||||
TableDataSource,
|
||||
} from './table'
|
||||
export type { TableColumnProps } from './table-column'
|
||||
export type {
|
||||
TableOperation,
|
||||
TableCellActions,
|
||||
TableCellActionRemove,
|
||||
TableCellActionUpdate,
|
||||
TableCellData,
|
||||
} from './table-cell'
|
||||
export default Table as TableComponentType
|
||||
|
||||
@@ -8,4 +8,5 @@ export type TabsComponentType = typeof Tabs & {
|
||||
;(Tabs as TabsComponentType).Item = TabsItem
|
||||
;(Tabs as TabsComponentType).Tab = TabsItem
|
||||
|
||||
export type { TabsProps } from './tabs'
|
||||
export default Tabs as TabsComponentType
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import Tag from './tag'
|
||||
import { TagProps } from './tag'
|
||||
|
||||
export type Props = TagProps
|
||||
export type { TagProps, TagColors, TagTypes } from './tag'
|
||||
export default Tag
|
||||
|
||||
@@ -4,14 +4,15 @@ import { SnippetTypes } from '../utils/prop-types'
|
||||
import { GeistUIThemesPalette } from '../themes/presets'
|
||||
import useScaleable, { withScaleable } from '../use-scaleable'
|
||||
|
||||
export type TagTypes = SnippetTypes
|
||||
interface Props {
|
||||
type?: SnippetTypes
|
||||
type?: TagTypes
|
||||
invert?: boolean
|
||||
className?: string
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
type: 'default' as SnippetTypes,
|
||||
type: 'default' as TagTypes,
|
||||
invert: false,
|
||||
className: '',
|
||||
}
|
||||
@@ -25,13 +26,9 @@ export type TagColors = {
|
||||
borderColor: string
|
||||
}
|
||||
|
||||
const getColors = (
|
||||
type: SnippetTypes,
|
||||
palette: GeistUIThemesPalette,
|
||||
invert: boolean,
|
||||
) => {
|
||||
const getColors = (type: TagTypes, palette: GeistUIThemesPalette, invert: boolean) => {
|
||||
const colors: {
|
||||
[key in SnippetTypes]: Pick<TagColors, 'color'> & Partial<TagColors>
|
||||
[key in TagTypes]: Pick<TagColors, 'color'> & Partial<TagColors>
|
||||
} = {
|
||||
default: {
|
||||
color: palette.foreground,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Text from './text'
|
||||
|
||||
export type { TextProps, TextTypes } from './text'
|
||||
export default Text
|
||||
|
||||
@@ -3,6 +3,7 @@ import { NormalTypes } from '../utils/prop-types'
|
||||
import TextChild from './child'
|
||||
import { withScaleable } from '../use-scaleable'
|
||||
|
||||
export type TextTypes = NormalTypes
|
||||
interface Props {
|
||||
h1?: boolean
|
||||
h2?: boolean
|
||||
@@ -19,7 +20,7 @@ interface Props {
|
||||
em?: boolean
|
||||
blockquote?: boolean
|
||||
className?: string
|
||||
type?: NormalTypes
|
||||
type?: TextTypes
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
@@ -38,7 +39,7 @@ const defaultProps = {
|
||||
em: false,
|
||||
blockquote: false,
|
||||
className: '',
|
||||
type: 'default' as NormalTypes,
|
||||
type: 'default' as TextTypes,
|
||||
}
|
||||
|
||||
type ElementMap = { [key in keyof JSX.IntrinsicElements]?: boolean }
|
||||
|
||||
@@ -37,7 +37,6 @@ exports[`Textarea should render correctly 1`] = `
|
||||
font-size: var(--textarea-font-size);
|
||||
width: 100%;
|
||||
height: var(--textarea-height);
|
||||
resize: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: calc(0.5 * 16px) calc(0.5 * 16px) calc(0.5 * 16px)
|
||||
@@ -95,7 +94,6 @@ exports[`Textarea should work with different styles 1`] = `
|
||||
font-size: var(--textarea-font-size);
|
||||
width: 100%;
|
||||
height: var(--textarea-height);
|
||||
resize: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: calc(0.5 * 16px) calc(0.5 * 16px) calc(0.5 * 16px)
|
||||
@@ -149,7 +147,6 @@ exports[`Textarea should work with different styles 1`] = `
|
||||
font-size: var(--textarea-font-size);
|
||||
width: 100%;
|
||||
height: var(--textarea-height);
|
||||
resize: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: calc(0.5 * 16px) calc(0.5 * 16px) calc(0.5 * 16px)
|
||||
@@ -167,7 +164,7 @@ exports[`Textarea should work with different styles 1`] = `
|
||||
textarea:-webkit-autofill:focus {
|
||||
-webkit-box-shadow: 0 0 0 30px #fff inset !important;
|
||||
}
|
||||
</style></div><div class=\\"wrapper \\"><textarea minheight=\\"100px\\"></textarea><style>
|
||||
</style></div><div class=\\"wrapper \\"><textarea height=\\"100px\\"></textarea><style>
|
||||
.wrapper {
|
||||
display: inline-flex;
|
||||
box-sizing: border-box;
|
||||
@@ -179,7 +176,7 @@ exports[`Textarea should work with different styles 1`] = `
|
||||
min-width: 12.5rem;
|
||||
max-width: 95vw;
|
||||
--textarea-font-size: calc(0.875 * 16px);
|
||||
--textarea-height: auto;
|
||||
--textarea-height: 100px;
|
||||
width: initial;
|
||||
height: var(--textarea-height);
|
||||
margin: 0 0 0 0;
|
||||
@@ -203,7 +200,6 @@ exports[`Textarea should work with different styles 1`] = `
|
||||
font-size: var(--textarea-font-size);
|
||||
width: 100%;
|
||||
height: var(--textarea-height);
|
||||
resize: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: calc(0.5 * 16px) calc(0.5 * 16px) calc(0.5 * 16px)
|
||||
|
||||
@@ -15,7 +15,7 @@ describe('Textarea', () => {
|
||||
<div>
|
||||
<Textarea type="secondary" />
|
||||
<Textarea width="20%" />
|
||||
<Textarea minHeight="100px" />
|
||||
<Textarea height="100px" />
|
||||
</div>,
|
||||
)
|
||||
expect(wrapper.html()).toMatchSnapshot()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Textarea from './textarea'
|
||||
|
||||
export type { TextareaProps, TextareaResizes, TextareaTypes } from './textarea'
|
||||
export default Textarea
|
||||
|
||||
@@ -5,29 +5,29 @@ import { getColors } from '../input/styles'
|
||||
import useScaleable, { withScaleable } from '../use-scaleable'
|
||||
|
||||
const resizeTypes = tuple('none', 'both', 'horizontal', 'vertical', 'initial', 'inherit')
|
||||
type ResizeTypes = typeof resizeTypes[number]
|
||||
|
||||
export type TextareaResizes = typeof resizeTypes[number]
|
||||
export type TextareaTypes = NormalTypes
|
||||
interface Props {
|
||||
value?: string
|
||||
initialValue?: string
|
||||
placeholder?: string
|
||||
type?: NormalTypes
|
||||
type?: TextareaTypes
|
||||
disabled?: boolean
|
||||
readOnly?: boolean
|
||||
onChange?: (e: React.ChangeEvent<HTMLTextAreaElement>) => void
|
||||
onFocus?: (e: React.FocusEvent<HTMLTextAreaElement>) => void
|
||||
onBlur?: (e: React.FocusEvent<HTMLTextAreaElement>) => void
|
||||
className?: string
|
||||
resize?: ResizeTypes
|
||||
resize?: TextareaResizes
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
initialValue: '',
|
||||
type: 'default' as NormalTypes,
|
||||
type: 'default' as TextareaTypes,
|
||||
disabled: false,
|
||||
readOnly: false,
|
||||
className: '',
|
||||
resize: 'none' as ResizeTypes,
|
||||
resize: 'none' as TextareaResizes,
|
||||
}
|
||||
|
||||
type NativeAttrs = Omit<React.TextareaHTMLAttributes<any>, keyof Props>
|
||||
@@ -145,7 +145,6 @@ const TextareaComponent = React.forwardRef<
|
||||
font-size: var(--textarea-font-size);
|
||||
width: 100%;
|
||||
height: var(--textarea-height);
|
||||
resize: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: ${SCALES.pt(0.5)} ${SCALES.pr(0.5)} ${SCALES.pb(0.5)}
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
import Themes from './themes'
|
||||
|
||||
export type { GeistUserTheme } from './themes'
|
||||
export type {
|
||||
GeistUIThemes,
|
||||
GeistUIThemesBreakpoints,
|
||||
BreakpointsItem,
|
||||
GeistUIThemesExpressiveness,
|
||||
GeistUIThemesFont,
|
||||
GeistUIThemesLayout,
|
||||
GeistUIThemesPalette,
|
||||
} from './presets'
|
||||
export default Themes
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
import Toggle from './toggle'
|
||||
|
||||
export type {
|
||||
ToggleProps,
|
||||
ToggleSize,
|
||||
ToggleEvent,
|
||||
ToggleEventTarget,
|
||||
ToggleTypes,
|
||||
} from './toggle'
|
||||
export default Toggle
|
||||
|
||||
@@ -4,10 +4,10 @@ import { NormalTypes } from '../utils/prop-types'
|
||||
import { getColors } from './styles'
|
||||
import useScaleable, { withScaleable } from '../use-scaleable'
|
||||
|
||||
interface ToggleEventTarget {
|
||||
export type ToggleTypes = NormalTypes
|
||||
export interface ToggleEventTarget {
|
||||
checked: boolean
|
||||
}
|
||||
|
||||
export interface ToggleEvent {
|
||||
target: ToggleEventTarget
|
||||
stopPropagation: () => void
|
||||
@@ -20,12 +20,12 @@ interface Props {
|
||||
initialChecked?: boolean
|
||||
onChange?: (ev: ToggleEvent) => void
|
||||
disabled?: boolean
|
||||
type?: NormalTypes
|
||||
type?: ToggleTypes
|
||||
className?: string
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
type: 'default' as NormalTypes,
|
||||
type: 'default' as ToggleTypes,
|
||||
disabled: false,
|
||||
initialChecked: false,
|
||||
className: '',
|
||||
|
||||
@@ -29,7 +29,7 @@ describe('Tooltip', () => {
|
||||
|
||||
await updateWrapper(wrapper, 150)
|
||||
wrapper.find('.tooltip').simulate('mouseLeave', nativeEvent)
|
||||
await updateWrapper(wrapper, 150)
|
||||
await updateWrapper(wrapper, 350)
|
||||
expectTooltipIsHidden(wrapper)
|
||||
})
|
||||
|
||||
@@ -40,11 +40,11 @@ describe('Tooltip', () => {
|
||||
</div>,
|
||||
)
|
||||
wrapper.find('.tooltip').simulate('mouseEnter', nativeEvent)
|
||||
await updateWrapper(wrapper, 150)
|
||||
await updateWrapper(wrapper, 350)
|
||||
expectTooltipIsShow(wrapper)
|
||||
|
||||
wrapper.find('.tooltip').simulate('mouseLeave', nativeEvent)
|
||||
await updateWrapper(wrapper, 150)
|
||||
await updateWrapper(wrapper, 350)
|
||||
expectTooltipIsHidden(wrapper)
|
||||
})
|
||||
|
||||
|
||||
33
components/tooltip/helper.ts
Normal file
33
components/tooltip/helper.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { MutableRefObject } from 'react'
|
||||
|
||||
export interface ReactiveDomReact {
|
||||
top: number
|
||||
bottom: number
|
||||
left: number
|
||||
right: number
|
||||
width: number
|
||||
height: number
|
||||
}
|
||||
|
||||
const defaultRect: ReactiveDomReact = {
|
||||
top: -1000,
|
||||
left: -1000,
|
||||
right: -1000,
|
||||
bottom: -1000,
|
||||
width: 0,
|
||||
height: 0,
|
||||
}
|
||||
|
||||
export const getRect = (ref: MutableRefObject<HTMLElement | null>): ReactiveDomReact => {
|
||||
if (!ref || !ref.current) return defaultRect
|
||||
const rect = ref.current.getBoundingClientRect()
|
||||
return {
|
||||
...rect,
|
||||
width: rect.width || rect.right - rect.left,
|
||||
height: rect.height || rect.bottom - rect.top,
|
||||
top: rect.top + document.documentElement.scrollTop,
|
||||
bottom: rect.bottom + document.documentElement.scrollTop,
|
||||
left: rect.left + document.documentElement.scrollLeft,
|
||||
right: rect.right + document.documentElement.scrollLeft,
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,10 @@
|
||||
import Tooltip from './tooltip'
|
||||
|
||||
export type {
|
||||
TooltipProps,
|
||||
TooltipOnVisibleChange,
|
||||
TooltipTypes,
|
||||
TooltipTriggers,
|
||||
TooltipPlacement,
|
||||
} from './tooltip'
|
||||
export default Tooltip
|
||||
|
||||
@@ -101,47 +101,49 @@ export const getPosition = (
|
||||
|
||||
export const getIconPosition = (
|
||||
placement: Placement,
|
||||
offset: number,
|
||||
offsetX: string,
|
||||
offsetY: string,
|
||||
offsetAbsolute: string = '3px',
|
||||
): TooltipIconPosition => {
|
||||
const positions: { [key in Placement]?: TooltipIconPosition } = {
|
||||
top: {
|
||||
top: 'auto',
|
||||
right: 'auto',
|
||||
left: '50%',
|
||||
bottom: `${offset}px`,
|
||||
bottom: `${offsetAbsolute}`,
|
||||
transform: 'translate(-50%, 100%) rotate(-90deg)',
|
||||
},
|
||||
topStart: {
|
||||
top: 'auto',
|
||||
right: 'auto',
|
||||
left: '5%',
|
||||
bottom: `${offset}px`,
|
||||
left: `${offsetX}`,
|
||||
bottom: `${offsetAbsolute}`,
|
||||
transform: 'translate(0, 100%) rotate(-90deg)',
|
||||
},
|
||||
topEnd: {
|
||||
top: 'auto',
|
||||
right: '5%',
|
||||
right: `${offsetX}`,
|
||||
left: 'auto',
|
||||
bottom: `${offset}px`,
|
||||
bottom: `${offsetAbsolute}`,
|
||||
transform: 'translate(0, 100%) rotate(-90deg)',
|
||||
},
|
||||
bottom: {
|
||||
top: `${offset}px`,
|
||||
top: `${offsetAbsolute}`,
|
||||
right: 'auto',
|
||||
left: '50%',
|
||||
bottom: 'auto',
|
||||
transform: 'translate(-50%, -100%) rotate(90deg)',
|
||||
},
|
||||
bottomStart: {
|
||||
top: `${offset}px`,
|
||||
top: `${offsetAbsolute}`,
|
||||
right: 'auto',
|
||||
left: '5%',
|
||||
left: `${offsetX}`,
|
||||
bottom: 'auto',
|
||||
transform: 'translate(0, -100%) rotate(90deg)',
|
||||
},
|
||||
bottomEnd: {
|
||||
top: `${offset}px`,
|
||||
right: '5%',
|
||||
top: `${offsetAbsolute}`,
|
||||
right: `${offsetX}`,
|
||||
left: 'auto',
|
||||
bottom: 'auto',
|
||||
transform: 'translate(0, -100%) rotate(90deg)',
|
||||
@@ -154,18 +156,18 @@ export const getIconPosition = (
|
||||
transform: 'translate(100%, -50%) rotate(180deg)',
|
||||
},
|
||||
leftStart: {
|
||||
top: '10%',
|
||||
top: `${offsetY}`,
|
||||
right: '0',
|
||||
left: 'auto',
|
||||
bottom: 'auto',
|
||||
transform: 'translate(100%, 0) rotate(180deg)',
|
||||
transform: 'translate(100%, -50%) rotate(180deg)',
|
||||
},
|
||||
leftEnd: {
|
||||
top: 'auto',
|
||||
right: '0',
|
||||
left: 'auto',
|
||||
bottom: '10%',
|
||||
transform: 'translate(100%, 0) rotate(180deg)',
|
||||
bottom: `${offsetY}`,
|
||||
transform: 'translate(100%, 50%) rotate(180deg)',
|
||||
},
|
||||
right: {
|
||||
top: '50%',
|
||||
@@ -175,18 +177,18 @@ export const getIconPosition = (
|
||||
transform: 'translate(-100%, -50%) rotate(0deg)',
|
||||
},
|
||||
rightStart: {
|
||||
top: '10%',
|
||||
top: `${offsetY}`,
|
||||
right: 'auto',
|
||||
left: '0',
|
||||
bottom: 'auto',
|
||||
transform: 'translate(-100%, 0) rotate(0deg)',
|
||||
transform: 'translate(-100%, -50%) rotate(0deg)',
|
||||
},
|
||||
rightEnd: {
|
||||
top: 'auto',
|
||||
right: 'auto',
|
||||
left: '0',
|
||||
bottom: '10%',
|
||||
transform: 'translate(-100%, 0) rotate(0deg)',
|
||||
bottom: `${offsetY}`,
|
||||
transform: 'translate(-100%, 50%) rotate(0deg)',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ import { getColors } from './styles'
|
||||
import { getPosition, TooltipPosition, defaultTooltipPosition } from './placement'
|
||||
import TooltipIcon from './tooltip-icon'
|
||||
import { Placement, SnippetTypes } from '../utils/prop-types'
|
||||
import useScaleable from '../use-scaleable'
|
||||
import { getRect } from './helper'
|
||||
|
||||
interface Props {
|
||||
parent?: MutableRefObject<HTMLElement | null> | undefined
|
||||
@@ -18,38 +20,11 @@ interface Props {
|
||||
hideArrow: boolean
|
||||
offset: number
|
||||
className?: string
|
||||
iconOffset: TooltipIconOffset
|
||||
}
|
||||
|
||||
interface ReactiveDomReact {
|
||||
top: number
|
||||
bottom: number
|
||||
left: number
|
||||
right: number
|
||||
width: number
|
||||
height: number
|
||||
}
|
||||
|
||||
const defaultRect: ReactiveDomReact = {
|
||||
top: -1000,
|
||||
left: -1000,
|
||||
right: -1000,
|
||||
bottom: -1000,
|
||||
width: 0,
|
||||
height: 0,
|
||||
}
|
||||
|
||||
const getRect = (ref: MutableRefObject<HTMLElement | null>): ReactiveDomReact => {
|
||||
if (!ref || !ref.current) return defaultRect
|
||||
const rect = ref.current.getBoundingClientRect()
|
||||
return {
|
||||
...rect,
|
||||
width: rect.width || rect.right - rect.left,
|
||||
height: rect.height || rect.bottom - rect.top,
|
||||
top: rect.top + document.documentElement.scrollTop,
|
||||
bottom: rect.bottom + document.documentElement.scrollTop,
|
||||
left: rect.left + document.documentElement.scrollLeft,
|
||||
right: rect.right + document.documentElement.scrollLeft,
|
||||
}
|
||||
export type TooltipIconOffset = {
|
||||
x: string
|
||||
y: string
|
||||
}
|
||||
|
||||
const TooltipContent: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
@@ -57,12 +32,14 @@ const TooltipContent: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
parent,
|
||||
visible,
|
||||
offset,
|
||||
iconOffset,
|
||||
placement,
|
||||
type,
|
||||
className,
|
||||
hideArrow,
|
||||
}) => {
|
||||
const theme = useTheme()
|
||||
const { SCALES } = useScaleable()
|
||||
const el = usePortal('tooltip')
|
||||
const selfRef = useRef<HTMLDivElement>(null)
|
||||
const [rect, setRect] = useState<TooltipPosition>(defaultTooltipPosition)
|
||||
@@ -95,33 +72,36 @@ const TooltipContent: React.FC<React.PropsWithChildren<Props>> = ({
|
||||
ref={selfRef}
|
||||
onClick={preventHandler}>
|
||||
<div className="inner">
|
||||
{!hideArrow && (
|
||||
<TooltipIcon
|
||||
placement={placement}
|
||||
bgColor={colors.bgColor}
|
||||
shadow={hasShadow}
|
||||
/>
|
||||
)}
|
||||
{!hideArrow && <TooltipIcon placement={placement} shadow={hasShadow} />}
|
||||
{children}
|
||||
</div>
|
||||
<style jsx>{`
|
||||
.tooltip-content {
|
||||
--tooltip-icon-offset-x: ${iconOffset.x};
|
||||
--tooltip-icon-offset-y: ${iconOffset.y};
|
||||
--tooltip-content-bg: ${colors.bgColor};
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
width: auto;
|
||||
top: ${rect.top};
|
||||
left: ${rect.left};
|
||||
transform: ${rect.transform};
|
||||
background-color: ${colors.bgColor};
|
||||
background-color: var(--tooltip-content-bg);
|
||||
color: ${colors.color};
|
||||
border-radius: ${theme.layout.radius};
|
||||
padding: 0;
|
||||
z-index: 1000;
|
||||
box-shadow: ${hasShadow ? theme.expressiveness.shadowMedium : 'none'};
|
||||
width: ${SCALES.width(1, 'auto')};
|
||||
height: ${SCALES.height(1, 'auto')};
|
||||
}
|
||||
|
||||
.inner {
|
||||
padding: ${theme.layout.gapHalf} ${theme.layout.gap};
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
font-size: ${SCALES.font(1)};
|
||||
padding: ${SCALES.pt(0.65)} ${SCALES.pr(0.9)} ${SCALES.pb(0.65)}
|
||||
${SCALES.pl(0.9)};
|
||||
height: 100%;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
|
||||
@@ -5,20 +5,24 @@ import useTheme from '../use-theme'
|
||||
|
||||
interface Props {
|
||||
placement: Placement
|
||||
bgColor: string
|
||||
shadow: boolean
|
||||
}
|
||||
|
||||
const TooltipIcon: React.FC<Props> = ({ placement, bgColor, shadow }) => {
|
||||
const TooltipIcon: React.FC<Props> = ({ placement, shadow }) => {
|
||||
const theme = useTheme()
|
||||
const { transform, top, left, right, bottom } = useMemo(
|
||||
() => getIconPosition(placement, 3),
|
||||
() =>
|
||||
getIconPosition(
|
||||
placement,
|
||||
'var(--tooltip-icon-offset-x)',
|
||||
'var(--tooltip-icon-offset-y)',
|
||||
),
|
||||
[placement],
|
||||
)
|
||||
const bgColorWithDark = useMemo(() => {
|
||||
if (!shadow || theme.type !== 'dark') return bgColor
|
||||
if (!shadow || theme.type !== 'dark') return 'var(--tooltip-content-bg)'
|
||||
return theme.palette.accents_2
|
||||
}, [theme.type, bgColor, shadow])
|
||||
}, [theme.type, shadow])
|
||||
|
||||
return (
|
||||
<span>
|
||||
@@ -41,4 +45,4 @@ const TooltipIcon: React.FC<Props> = ({ placement, bgColor, shadow }) => {
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(TooltipIcon)
|
||||
export default TooltipIcon
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import TooltipContent from './tooltip-content'
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import TooltipContent, { TooltipIconOffset } from './tooltip-content'
|
||||
import useClickAway from '../utils/use-click-away'
|
||||
import { TriggerTypes, Placement, SnippetTypes } from '../utils/prop-types'
|
||||
import { withScaleable } from '../use-scaleable'
|
||||
import { getRect } from './helper'
|
||||
|
||||
export type TooltipOnVisibleChange = (visible: boolean) => void
|
||||
|
||||
export type TooltipTypes = SnippetTypes
|
||||
export type TooltipTriggers = TriggerTypes
|
||||
export type TooltipPlacement = Placement
|
||||
interface Props {
|
||||
text: string | React.ReactNode
|
||||
type?: SnippetTypes
|
||||
placement?: Placement
|
||||
type?: TooltipTypes
|
||||
placement?: TooltipPlacement
|
||||
visible?: boolean
|
||||
initialVisible?: boolean
|
||||
hideArrow?: boolean
|
||||
trigger?: TriggerTypes
|
||||
trigger?: TooltipTriggers
|
||||
enterDelay?: number
|
||||
leaveDelay?: number
|
||||
offset?: number
|
||||
@@ -24,11 +28,11 @@ interface Props {
|
||||
const defaultProps = {
|
||||
initialVisible: false,
|
||||
hideArrow: false,
|
||||
type: 'default' as SnippetTypes,
|
||||
trigger: 'hover' as TriggerTypes,
|
||||
placement: 'top' as Placement,
|
||||
type: 'default' as TooltipTypes,
|
||||
trigger: 'hover' as TooltipTriggers,
|
||||
placement: 'top' as TooltipPlacement,
|
||||
enterDelay: 100,
|
||||
leaveDelay: 0,
|
||||
leaveDelay: 150,
|
||||
offset: 12,
|
||||
className: '',
|
||||
portalClassName: '',
|
||||
@@ -38,7 +42,7 @@ const defaultProps = {
|
||||
type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
|
||||
export type TooltipProps = Props & NativeAttrs
|
||||
|
||||
const Tooltip: React.FC<React.PropsWithChildren<TooltipProps>> = ({
|
||||
const TooltipComponent: React.FC<React.PropsWithChildren<TooltipProps>> = ({
|
||||
children,
|
||||
initialVisible,
|
||||
text,
|
||||
@@ -58,12 +62,21 @@ const Tooltip: React.FC<React.PropsWithChildren<TooltipProps>> = ({
|
||||
const timer = useRef<number>()
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
const [visible, setVisible] = useState<boolean>(initialVisible)
|
||||
const iconOffset = useMemo<TooltipIconOffset>(() => {
|
||||
if (!ref?.current) return { x: '0.75em', y: '0.75em' }
|
||||
const rect = getRect(ref)
|
||||
return {
|
||||
x: `${rect.width ? rect.width / 2 : 0}px`,
|
||||
y: `${rect.height ? rect.height / 2 : 0}px`,
|
||||
}
|
||||
}, [ref?.current])
|
||||
const contentProps = {
|
||||
type,
|
||||
visible,
|
||||
offset,
|
||||
placement,
|
||||
hideArrow,
|
||||
iconOffset,
|
||||
parent: ref,
|
||||
className: portalClassName,
|
||||
}
|
||||
@@ -83,14 +96,14 @@ const Tooltip: React.FC<React.PropsWithChildren<TooltipProps>> = ({
|
||||
timer.current = window.setTimeout(() => handler(true), enterDelay)
|
||||
return
|
||||
}
|
||||
timer.current = window.setTimeout(() => handler(false), leaveDelay)
|
||||
const leaveDelayWithoutClick = trigger === 'click' ? 0 : leaveDelay
|
||||
timer.current = window.setTimeout(() => handler(false), leaveDelayWithoutClick)
|
||||
}
|
||||
|
||||
const mouseEventHandler = (next: boolean) => trigger === 'hover' && changeVisible(next)
|
||||
const clickEventHandler = () => trigger === 'click' && changeVisible(!visible)
|
||||
|
||||
useClickAway(ref, () => trigger === 'click' && changeVisible(false))
|
||||
|
||||
useEffect(() => {
|
||||
if (customVisible === undefined) return
|
||||
changeVisible(customVisible)
|
||||
@@ -116,6 +129,7 @@ const Tooltip: React.FC<React.PropsWithChildren<TooltipProps>> = ({
|
||||
)
|
||||
}
|
||||
|
||||
Tooltip.defaultProps = defaultProps
|
||||
Tooltip.displayName = 'GiestTooltip'
|
||||
TooltipComponent.defaultProps = defaultProps
|
||||
TooltipComponent.displayName = 'GiestTooltip'
|
||||
const Tooltip = withScaleable(TooltipComponent)
|
||||
export default Tooltip
|
||||
|
||||
@@ -2,9 +2,9 @@ import React from 'react'
|
||||
import { mount } from 'enzyme'
|
||||
import { Tree } from 'components'
|
||||
import { nativeEvent } from 'tests/utils'
|
||||
import { FileTreeValue } from '../tree'
|
||||
import { TreeFile } from '../tree'
|
||||
|
||||
const mockFiles: Array<FileTreeValue> = [
|
||||
const mockFiles: Array<TreeFile> = [
|
||||
{
|
||||
type: 'file',
|
||||
name: 'cs.js',
|
||||
|
||||
@@ -9,4 +9,5 @@ export type TreeComponentType = typeof Tree & {
|
||||
;(Tree as TreeComponentType).File = TreeFile
|
||||
;(Tree as TreeComponentType).Folder = TreeFolder
|
||||
|
||||
export type { TreeProps, TreeFile } from './tree'
|
||||
export default Tree as TreeComponentType
|
||||
|
||||
@@ -3,21 +3,21 @@ import TreeFile from './tree-file'
|
||||
import TreeFolder from './tree-folder'
|
||||
import { TreeContext } from './tree-context'
|
||||
import { tuple } from '../utils/prop-types'
|
||||
import { sortChildren } from './/tree-help'
|
||||
import { sortChildren } from './tree-help'
|
||||
|
||||
const FileTreeValueType = tuple('directory', 'file')
|
||||
|
||||
const directoryType = FileTreeValueType[0]
|
||||
|
||||
export type FileTreeValue = {
|
||||
export type TreeFile = {
|
||||
type: typeof FileTreeValueType[number]
|
||||
name: string
|
||||
extra?: string
|
||||
files?: Array<FileTreeValue>
|
||||
files?: Array<TreeFile>
|
||||
}
|
||||
|
||||
interface Props {
|
||||
value?: Array<FileTreeValue>
|
||||
value?: Array<TreeFile>
|
||||
initialExpand?: boolean
|
||||
onClick?: (path: string) => void
|
||||
className?: string
|
||||
@@ -31,7 +31,7 @@ const defaultProps = {
|
||||
type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
|
||||
export type TreeProps = Props & NativeAttrs
|
||||
|
||||
const makeChildren = (value: Array<FileTreeValue> = []) => {
|
||||
const makeChildren = (value: Array<TreeFile> = []) => {
|
||||
if (!value || !value.length) return null
|
||||
return value
|
||||
.sort((a, b) => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useAllThemes } from './all-themes-context'
|
||||
|
||||
export type { AllThemesConfig } from './all-themes-context'
|
||||
export default useAllThemes
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import useBodyScroll from './use-body-scroll'
|
||||
|
||||
export type { BodyScrollOptions } from './use-body-scroll'
|
||||
export default useBodyScroll
|
||||
|
||||
@@ -1,19 +1,26 @@
|
||||
import { MutableRefObject, useEffect } from 'react'
|
||||
import { MutableRefObject, useEffect, useRef } from 'react'
|
||||
|
||||
export type ClickAwayGetContainer = () => HTMLElement | null
|
||||
|
||||
const useClickAway = (
|
||||
ref: MutableRefObject<HTMLElement | null>,
|
||||
handler: (event: Event) => void,
|
||||
) => {
|
||||
const handlerRef = useRef(handler)
|
||||
useEffect(() => {
|
||||
handlerRef.current = handler
|
||||
}, [handlerRef])
|
||||
|
||||
useEffect(() => {
|
||||
const callback = (event: Event) => {
|
||||
const el = ref.current
|
||||
if (!event || !el || el.contains((event as any).target)) return
|
||||
handler(event)
|
||||
handlerRef.current(event)
|
||||
}
|
||||
|
||||
document.addEventListener('click', callback, { capture: true })
|
||||
return () => document.removeEventListener('click', callback, { capture: true })
|
||||
}, [ref, handler])
|
||||
document.addEventListener('click', callback)
|
||||
return () => document.removeEventListener('click', callback)
|
||||
}, [ref])
|
||||
}
|
||||
|
||||
export default useClickAway
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import useClipboard from './use-clipboard'
|
||||
|
||||
export type { UseClipboardOptions, UseClipboardResult } from './use-clipboard'
|
||||
export default useClipboard
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import useKeyboard from './use-keyboard'
|
||||
import { KeyMod, KeyCode } from './codes'
|
||||
|
||||
export default useKeyboard
|
||||
export { KeyMod, KeyCode }
|
||||
export type {
|
||||
UseKeyboardHandler,
|
||||
KeyboardOptions,
|
||||
KeyboardResult,
|
||||
UseKeyboard,
|
||||
} from './use-keyboard'
|
||||
export default useKeyboard
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user