feat(scaleable): add scaleable props to each component (#531)

* feat(scaleable): add scaleable props to each component

* chore(scaleable): update the exported type

* feat: apply scaleable to components

chore: remove with-default

test: improve testcase for scaleable

chore: resolve test warning

ci: upgrade nodejs to latest lts

docs: fix type error in document site

* docs: update documents to be compatible with scaleable

chore: fix build errors

* chore: remove all size-related attributes

docs: improve guide document

* docs: add scaleable documentation

test: update snapshots

chore: remove unused

* feat: add scaleable to grid components

* docs: improve docs

* test: update snapshots

* fix(grid): fix basic component props
This commit is contained in:
witt
2021-06-23 10:53:30 +08:00
committed by unix
parent c3708c1948
commit 7facec3849
382 changed files with 15046 additions and 27916 deletions

View File

@@ -1,221 +1,629 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Text should be able to specify the size of text 1`] = `
"<p class=\\"custom-size \\">test-value</p><style>
"<p class=\\"font\\" font=\\"14\\">test-value<style>
p {
color: inherit;
width: auto;
height: auto;
}
.custom-size {
font-size: 14px;
.font {
font-size: calc(14 * 16px);
}
</style>"
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></p>"
`;
exports[`Text should be able to specify the size of text 2`] = `
"<p class=\\"custom-size \\">test-value</p><style>
"<p class=\\"font\\" font=\\"12rem\\">test-value<style>
p {
color: inherit;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: 12rem;
}
</style>"
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></p>"
`;
exports[`Text should render P element in the default 1`] = `
"<p class=\\" \\">test-value</p><style>
"<p class=\\"\\">test-value<style>
p {
color: inherit;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style>"
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></p>"
`;
exports[`Text should render default color when type missing 1`] = `
"<p class=\\" \\">test-value</p><style>
"<p class=\\"\\">test-value<style>
p {
color: inherit;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style>"
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></p>"
`;
exports[`Text should work with different styles 1`] = `
"<div><p class=\\" \\">test-value</p><style>
"<div><p class=\\"\\">test-value<style>
p {
color: #666;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style><p class=\\" \\">test-value</p><style>
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></p><p class=\\"\\">test-value<style>
p {
color: #0070f3;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style><p class=\\" \\">test-value</p><style>
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></p><p class=\\"\\">test-value<style>
p {
color: #f5a623;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style><p class=\\" \\">test-value</p><style>
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></p><p class=\\"\\">test-value<style>
p {
color: #e00;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style></div>"
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></p></div>"
`;
exports[`Text the combined style should be rendered 1`] = `
"<p class=\\" \\"><b class=\\" \\"><del class=\\" \\">test-value</del><style>
"<p class=\\"\\"><b class=\\"\\"><del class=\\"\\">test-value<style>
del {
color: inherit;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style></b><style>
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></del><style>
b {
color: inherit;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style></p><style>
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></b><style>
p {
color: inherit;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style>"
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></p>"
`;
exports[`Text the specified element should be rendered 1`] = `
"<div><h1 class=\\" \\">test-value</h1><style>
"<div><h1 class=\\"\\">test-value<style>
h1 {
color: inherit;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style><h2 class=\\" \\">test-value</h2><style>
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></h1><h2 class=\\"\\">test-value<style>
h2 {
color: inherit;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style><h3 class=\\" \\">test-value</h3><style>
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></h2><h3 class=\\"\\">test-value<style>
h3 {
color: inherit;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style><h4 class=\\" \\">test-value</h4><style>
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></h3><h4 class=\\"\\">test-value<style>
h4 {
color: inherit;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style><h5 class=\\" \\">test-value</h5><style>
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></h4><h5 class=\\"\\">test-value<style>
h5 {
color: inherit;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style><h6 class=\\" \\">test-value</h6><style>
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></h5><h6 class=\\"\\">test-value<style>
h6 {
color: inherit;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style><p class=\\" \\">test-value</p><style>
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></h6><p class=\\"\\">test-value<style>
p {
color: inherit;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style><small class=\\" \\">test-value</small><style>
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></p><small class=\\"\\">test-value<style>
small {
color: inherit;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style><span class=\\" \\">test-value</span><style>
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></small><span class=\\"\\">test-value<style>
span {
color: inherit;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style><del class=\\" \\">test-value</del><style>
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></span><del class=\\"\\">test-value<style>
del {
color: inherit;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style><i class=\\" \\">test-value</i><style>
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></del><i class=\\"\\">test-value<style>
i {
color: inherit;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style><em class=\\" \\">test-value</em><style>
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></i><em class=\\"\\">test-value<style>
em {
color: inherit;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style><b class=\\" \\">test-value</b><style>
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></em><b class=\\"\\">test-value<style>
b {
color: inherit;
width: auto;
height: auto;
}
.custom-size {
.font {
font-size: inherit;
}
</style></div>"
.mx {
margin-left: revert;
margin-right: revert;
}
.my {
margin-top: revert;
margin-bottom: revert;
}
.px {
padding-left: revert;
padding-right: revert;
}
.py {
padding-top: revert;
padding-bottom: revert;
}
</style></b></div>"
`;

View File

@@ -73,10 +73,10 @@ describe('Text', () => {
})
it('should be able to specify the size of text', () => {
let wrapper = mount(<Text size={14}>test-value</Text>)
let wrapper = mount(<Text font={14}>test-value</Text>)
expect(wrapper.html()).toMatchSnapshot()
wrapper = mount(<Text size="12rem">test-value</Text>)
wrapper = mount(<Text font="12rem">test-value</Text>)
expect(wrapper.html()).toMatchSnapshot()
expect(() => wrapper.unmount()).not.toThrow()
})

View File

@@ -1,14 +1,13 @@
import React, { useMemo } from 'react'
import withDefaults from '../utils/with-defaults'
import useTheme from '../use-theme'
import { NormalTypes } from '../utils/prop-types'
import { GeistUIThemesPalette } from '../themes/presets'
import useScaleable from '../use-scaleable'
export interface Props {
tag: keyof JSX.IntrinsicElements
type?: NormalTypes
size?: string | number
className?: ''
className?: string
}
const defaultProps = {
@@ -29,43 +28,86 @@ const getTypeColor = (type: NormalTypes, palette: GeistUIThemesPalette) => {
}
type NativeAttrs = Omit<React.DetailsHTMLAttributes<any>, keyof Props>
export type TextChildProps = Props & typeof defaultProps & NativeAttrs
export type TextChildProps = Props & NativeAttrs
const TextChild: React.FC<React.PropsWithChildren<TextChildProps>> = ({
children,
tag,
className,
type,
size,
...props
}) => {
const theme = useTheme()
}: React.PropsWithChildren<TextChildProps> & typeof defaultProps) => {
const Component = tag
const theme = useTheme()
const { SCALES, getScaleableProps } = useScaleable()
const font = getScaleableProps('font')
const mx = getScaleableProps(['margin', 'marginLeft', 'marginRight', 'mx', 'ml', 'mr'])
const my = getScaleableProps(['margin', 'marginTop', 'marginBottom', 'my', 'mt', 'mb'])
const px = getScaleableProps([
'padding',
'paddingLeft',
'paddingRight',
'pl',
'pr',
'px',
])
const py = getScaleableProps([
'padding',
'paddingTop',
'paddingBottom',
'pt',
'pb',
'py',
])
const color = useMemo(() => getTypeColor(type, theme.palette), [type, theme.palette])
const fontSize = useMemo<string>(() => {
if (!size) return 'inherit'
if (typeof size === 'number') return `${size}px`
return size
}, [size])
const classNames = useMemo<string>(() => {
const keys = [
{ value: mx, className: 'mx' },
{ value: my, className: 'my' },
{ value: px, className: 'px' },
{ value: py, className: 'py' },
{ value: font, className: 'font' },
]
const scaleClassNames = keys.reduce((pre, next) => {
if (typeof next.value === 'undefined') return pre
return `${pre} ${next.className}`
}, '')
return `${scaleClassNames} ${className}`.trim()
}, [mx, my, px, py, font, className])
return (
<>
<Component className={`${size ? 'custom-size' : ''} ${className}`} {...props}>
{children}
</Component>
<Component className={classNames} {...props}>
{children}
<style jsx>{`
${tag} {
color: ${color};
width: ${SCALES.width(1, 'auto')};
height: ${SCALES.height(1, 'auto')};
}
.custom-size {
font-size: ${fontSize};
.font {
font-size: ${SCALES.font(1, 'inherit')};
}
.mx {
margin-left: ${SCALES.ml(0, 'revert')};
margin-right: ${SCALES.mr(0, 'revert')};
}
.my {
margin-top: ${SCALES.mt(0, 'revert')};
margin-bottom: ${SCALES.mb(0, 'revert')};
}
.px {
padding-left: ${SCALES.pl(0, 'revert')};
padding-right: ${SCALES.pr(0, 'revert')};
}
.py {
padding-top: ${SCALES.pt(0, 'revert')};
padding-bottom: ${SCALES.pb(0, 'revert')};
}
`}</style>
</>
</Component>
)
}
const MemoTextChild = React.memo(TextChild)
export default withDefaults(MemoTextChild, defaultProps)
TextChild.defaultProps = defaultProps
TextChild.displayName = 'GeistTextChild'
export default TextChild

View File

@@ -1,5 +1,3 @@
import Text from './text'
import { TextProps } from './text'
export type Props = TextProps
export default Text

View File

@@ -1,7 +1,7 @@
import React, { ReactNode, useMemo } from 'react'
import withDefaults from '../utils/with-defaults'
import { NormalTypes } from '../utils/prop-types'
import TextChild from './child'
import { withScaleable } from '../use-scaleable'
interface Props {
h1?: boolean
@@ -19,7 +19,6 @@ interface Props {
em?: boolean
blockquote?: boolean
className?: string
size?: string | number
type?: NormalTypes
}
@@ -45,25 +44,17 @@ const defaultProps = {
type ElementMap = { [key in keyof JSX.IntrinsicElements]?: boolean }
type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
export type TextProps = Props & typeof defaultProps & NativeAttrs
export type TextProps = Props & NativeAttrs
type TextRenderableElements = Array<keyof JSX.IntrinsicElements>
const getModifierChild = (
tags: TextRenderableElements,
children: ReactNode,
size?: string | number,
) => {
const getModifierChild = (tags: TextRenderableElements, children: ReactNode) => {
if (!tags.length) return children
const nextTag = tags.slice(1, tags.length)
return (
<TextChild tag={tags[0]} size={size}>
{getModifierChild(nextTag, children, size)}
</TextChild>
)
return <TextChild tag={tags[0]}>{getModifierChild(nextTag, children)}</TextChild>
}
const Text: React.FC<React.PropsWithChildren<TextProps>> = ({
const TextComponent: React.FC<React.PropsWithChildren<TextProps>> = ({
h1,
h2,
h3,
@@ -78,11 +69,10 @@ const Text: React.FC<React.PropsWithChildren<TextProps>> = ({
del,
em,
blockquote,
size,
children,
className,
...props
}) => {
}: React.PropsWithChildren<TextProps> & typeof defaultProps) => {
const elements: ElementMap = { h1, h2, h3, h4, h5, h6, p, blockquote }
const inlineElements: ElementMap = { span, small, b, em, i, del }
const names = Object.keys(elements).filter(
@@ -114,16 +104,17 @@ const Text: React.FC<React.PropsWithChildren<TextProps>> = ({
const modifers = useMemo(() => {
if (!renderableChildElements.length) return children
return getModifierChild(renderableChildElements, children, size)
}, [renderableChildElements, children, size])
return getModifierChild(renderableChildElements, children)
}, [renderableChildElements, children])
return (
<TextChild className={className} tag={tag} size={size} {...props}>
<TextChild className={className} tag={tag} {...props}>
{modifers}
</TextChild>
)
}
const MemoText = React.memo(Text)
export default withDefaults(MemoText, defaultProps)
TextComponent.defaultProps = defaultProps
TextComponent.displayName = 'GeistText'
const Text = withScaleable(TextComponent)
export default Text