mirror of
https://github.com/zhigang1992/react.git
synced 2026-02-10 22:45:11 +08:00
Merge pull request #143 from unix/blockquote
feat(text): add blockquote
This commit is contained in:
@@ -19,6 +19,7 @@ module.exports = {
|
||||
'!components/**/styles.{ts,tsx}',
|
||||
'!components/styles/*',
|
||||
'!components/index.ts',
|
||||
'!components/utils/*',
|
||||
],
|
||||
|
||||
"moduleNameMapper": {
|
||||
|
||||
@@ -248,6 +248,23 @@ initialize {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
padding: calc(.667 * 16pt) 16pt;
|
||||
color: #666;
|
||||
background-color: #fafafa;
|
||||
border-radius: 5px;
|
||||
margin: 1.5rem 0;
|
||||
border: 1px solid #eaeaea;
|
||||
}
|
||||
|
||||
blockquote :global(*:first-child) {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
blockquote :global(*:last-child) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background-color: #79ffe1;
|
||||
color: #000;
|
||||
@@ -541,6 +558,23 @@ initialize {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
padding: calc(.667 * 16pt) 16pt;
|
||||
color: #888;
|
||||
background-color: #111;
|
||||
border-radius: 5px;
|
||||
margin: 1.5rem 0;
|
||||
border: 1px solid #333;
|
||||
}
|
||||
|
||||
blockquote :global(*:first-child) {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
blockquote :global(*:last-child) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background-color: #f81ce5;
|
||||
color: #fff;
|
||||
|
||||
@@ -253,6 +253,23 @@ const CSSBaseline: React.FC<React.PropsWithChildren<{}>> = React.memo(({
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
padding: calc(.667 * ${theme.layout.gap}) ${theme.layout.gap};
|
||||
color: ${theme.palette.accents_5};
|
||||
background-color: ${theme.palette.accents_1};
|
||||
border-radius: ${theme.layout.radius};
|
||||
margin: 1.5rem 0;
|
||||
border: 1px solid ${theme.palette.border};
|
||||
}
|
||||
|
||||
blockquote :global(*:first-child) {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
blockquote :global(*:last-child) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background-color: ${theme.palette.selection};
|
||||
color: ${theme.palette.foreground};
|
||||
|
||||
@@ -81,11 +81,7 @@ exports[`Text the specified element should be rendered 1`] = `
|
||||
p {
|
||||
color: inherit;
|
||||
}
|
||||
</style><small class=\\"\\"><small class=\\"\\">test-value</small><style>
|
||||
small {
|
||||
color: inherit;
|
||||
}
|
||||
</style></small><style>
|
||||
</style><small class=\\"\\">test-value</small><style>
|
||||
small {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
@@ -4,20 +4,6 @@ import useTheme from '../styles/use-theme'
|
||||
import { NormalTypes } from '../utils/prop-types'
|
||||
import { ZeitUIThemesPalette } from '../styles/themes'
|
||||
|
||||
export const ComponentTypes: Array<keyof JSX.IntrinsicElements> = [
|
||||
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'small',
|
||||
]
|
||||
|
||||
export const ComponentModifiedElements: { [key: string]: string } = {
|
||||
bold: 'b',
|
||||
b: 'b',
|
||||
italic: 'i',
|
||||
i: 'i',
|
||||
desc: 'desc',
|
||||
description: 'desc',
|
||||
del: 'del',
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
tag: keyof JSX.IntrinsicElements
|
||||
type?: NormalTypes
|
||||
|
||||
@@ -17,6 +17,7 @@ interface Props {
|
||||
span?: boolean
|
||||
del?: boolean
|
||||
em?: boolean
|
||||
blockquote?: boolean
|
||||
className?: string
|
||||
type?: NormalTypes
|
||||
}
|
||||
@@ -35,6 +36,7 @@ const defaultProps = {
|
||||
span: false,
|
||||
del: false,
|
||||
em: false,
|
||||
blockquote: false,
|
||||
className: '',
|
||||
type: 'default' as NormalTypes,
|
||||
}
|
||||
@@ -44,7 +46,9 @@ type ElementMap = { [key in (keyof JSX.IntrinsicElements)]?: boolean }
|
||||
type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
|
||||
export type TextProps = Props & typeof defaultProps & NativeAttrs
|
||||
|
||||
const getModifierChild = (tags: Array<keyof JSX.IntrinsicElements>, children: ReactNode) => {
|
||||
type TextRenderableElements = Array<keyof JSX.IntrinsicElements>
|
||||
|
||||
const getModifierChild = (tags: TextRenderableElements, children: ReactNode) => {
|
||||
if (!tags.length) return children
|
||||
const nextTag = tags.slice(1, tags.length)
|
||||
return (
|
||||
@@ -54,23 +58,16 @@ const getModifierChild = (tags: Array<keyof JSX.IntrinsicElements>, children: Re
|
||||
)
|
||||
}
|
||||
|
||||
const getModifiers = (inlineElements: ElementMap, children: ReactNode) => {
|
||||
const names = Object.keys(inlineElements)
|
||||
.filter((name: keyof JSX.IntrinsicElements) => inlineElements[name])
|
||||
if (!names.length) return children
|
||||
|
||||
return getModifierChild(names as Array<keyof JSX.IntrinsicElements>, children)
|
||||
}
|
||||
|
||||
const Text: React.FC<React.PropsWithChildren<TextProps>> = React.memo(({
|
||||
h1, h2, h3, h4, h5, h6, p, b, small, i, span, del, em, children, className, ...props
|
||||
h1, h2, h3, h4, h5, h6, p, b, small, i, span, del, em, blockquote,
|
||||
children, className, ...props
|
||||
}) => {
|
||||
const elements: ElementMap = { h1, h2, h3, h4, h5, h6, p, small }
|
||||
const inlineElements: ElementMap = { b, small, i, span, del, em }
|
||||
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((name: keyof JSX.IntrinsicElements) => elements[name])
|
||||
.filter((name: keyof JSX.IntrinsicElements) => elements[name]) as TextRenderableElements
|
||||
const inlineNames = Object.keys(inlineElements)
|
||||
.filter((name: keyof JSX.IntrinsicElements) => inlineElements[name])
|
||||
.filter((name: keyof JSX.IntrinsicElements) => inlineElements[name]) as TextRenderableElements
|
||||
|
||||
/**
|
||||
* Render element "p" only if no element is found.
|
||||
@@ -82,16 +79,20 @@ const Text: React.FC<React.PropsWithChildren<TextProps>> = React.memo(({
|
||||
*
|
||||
*/
|
||||
|
||||
const notSpecialElement = !names[0]
|
||||
const defaultElement = (inlineNames[0] || 'p') as keyof JSX.IntrinsicElements
|
||||
const tag = notSpecialElement ? defaultElement : (names[0]) as keyof JSX.IntrinsicElements
|
||||
const modifers = useMemo(
|
||||
() => {
|
||||
if (notSpecialElement) return children
|
||||
return getModifiers(inlineElements, children)
|
||||
},
|
||||
[inlineElements, children],
|
||||
)
|
||||
const tag = useMemo(() => {
|
||||
if (names[0]) return names[0]
|
||||
if (inlineNames[0]) return inlineNames[0]
|
||||
return 'p' as keyof JSX.IntrinsicElements
|
||||
}, [names, inlineNames])
|
||||
|
||||
const renderableChildElements = inlineNames
|
||||
.filter((name: keyof JSX.IntrinsicElements) => name !== tag) as TextRenderableElements
|
||||
|
||||
const modifers = useMemo(() => {
|
||||
if (!renderableChildElements.length) return children
|
||||
return getModifierChild(renderableChildElements, children)
|
||||
}, [renderableChildElements, children])
|
||||
|
||||
return (
|
||||
<TextChild className={className} tag={tag} {...props}>{modifers}</TextChild>
|
||||
)
|
||||
|
||||
@@ -61,6 +61,38 @@ Display text using well-defined typographic styles.
|
||||
</>
|
||||
`} />
|
||||
|
||||
<Playground
|
||||
title="Blockquote"
|
||||
scope={{ Text }}
|
||||
code={`
|
||||
<Text blockquote>
|
||||
Our mission is to make cloud computing accessible to everyone.
|
||||
</Text>
|
||||
`} />
|
||||
|
||||
<Playground
|
||||
title="Types"
|
||||
scope={{ Text }}
|
||||
code={`
|
||||
<>
|
||||
<Text type="success">
|
||||
Our mission is to make cloud computing accessible to everyone.
|
||||
</Text>
|
||||
<Text type="warning">
|
||||
Our mission is to make cloud computing accessible to everyone.
|
||||
</Text>
|
||||
<Text type="secondary">
|
||||
Our mission is to make cloud computing accessible to everyone.
|
||||
</Text>
|
||||
<Text type="error">
|
||||
Our mission is to make cloud computing accessible to everyone.
|
||||
</Text>
|
||||
<Text style={{ color: '#ccc' }}>
|
||||
Our mission is to make cloud computing accessible to everyone.
|
||||
</Text>
|
||||
</>
|
||||
`} />
|
||||
|
||||
<Playground
|
||||
title="Compose"
|
||||
desc="Effect of multiple `Text` stacks"
|
||||
@@ -91,9 +123,20 @@ Display text using well-defined typographic styles.
|
||||
| **i** | component name | `boolean` | - | `false` |
|
||||
| **em** | component name | `boolean` | - | `false` |
|
||||
| **b** | component name | `boolean` | - | `false` |
|
||||
| **type** | text type | `NormalTypes` | `'default', 'secondary', 'success', 'warning', 'error'` | `default` |
|
||||
| **blockquote** | component name | `boolean` | - | `false` |
|
||||
| **type** | text type | `NormalTypes` | [TextTypes](#texttypes) | `default` |
|
||||
| ... | native props | `HTMLAttributes` | `'id', 'className', ...` | - |
|
||||
|
||||
<Attributes.Title>TextTypes</Attributes.Title>
|
||||
|
||||
```ts
|
||||
type TextTypes = 'default'
|
||||
| 'secondary'
|
||||
| 'success'
|
||||
| 'warning'
|
||||
| 'error'
|
||||
```
|
||||
|
||||
</Attributes>
|
||||
|
||||
export default ({ children }) => <Layout meta={meta}>{children}</Layout>
|
||||
|
||||
@@ -14,19 +14,14 @@ export const meta = {
|
||||
title="标题"
|
||||
scope={{ Text }}
|
||||
code={`
|
||||
() => {
|
||||
const text = 'JavaScript 是一门编程语言。'
|
||||
return (
|
||||
<>
|
||||
<Text h1>{text}</Text>
|
||||
<Text h2>{text}</Text>
|
||||
<Text h3>{text}</Text>
|
||||
<Text h4>{text}</Text>
|
||||
<Text h5>{text}</Text>
|
||||
<Text h6>{text}</Text>
|
||||
</>
|
||||
)
|
||||
}
|
||||
<>
|
||||
<Text h1>JavaScript 是一门编程语言。</Text>
|
||||
<Text h2>JavaScript 是一门编程语言。</Text>
|
||||
<Text h3>JavaScript 是一门编程语言。</Text>
|
||||
<Text h4>JavaScript 是一门编程语言。</Text>
|
||||
<Text h5>JavaScript 是一门编程语言。</Text>
|
||||
<Text h6>JavaScript 是一门编程语言。</Text>
|
||||
</>
|
||||
`} />
|
||||
|
||||
<Playground
|
||||
@@ -51,11 +46,44 @@ export const meta = {
|
||||
code={`
|
||||
<>
|
||||
<Text small>
|
||||
函数 用来封装可复用的功能。如果没有函数,一段特定的操作过程用几次就要重复写几次,而使用函数则只需写下函数名和一些简短的信息。
|
||||
函数用来封装可复用的功能。如果没有函数,一段特定的操作过程用几次就要重复写几次,而使用函数则只需写下函数名和一些简短的信息。
|
||||
</Text>
|
||||
|
||||
<Text small i>
|
||||
函数 用来封装可复用的功能。如果没有函数,一段特定的操作过程用几次就要重复写几次,而使用函数则只需写下函数名和一些简短的信息。
|
||||
函数用来封装可复用的功能。如果没有函数,一段特定的操作过程用几次就要重复写几次,而使用函数则只需写下函数名和一些简短的信息。
|
||||
</Text>
|
||||
</>
|
||||
`} />
|
||||
|
||||
<Playground
|
||||
title="引用"
|
||||
scope={{ Text }}
|
||||
code={`
|
||||
<Text blockquote>
|
||||
事件能为网页添加真实的交互能力。
|
||||
</Text>
|
||||
`} />
|
||||
|
||||
<Playground
|
||||
title="色彩"
|
||||
desc="以不同的色彩区分文字的状态。"
|
||||
scope={{ Text }}
|
||||
code={`
|
||||
<>
|
||||
<Text type="success">
|
||||
中间的代理服务器必须转发未经修改的端到端消息头,并且必须缓存它们。
|
||||
</Text>
|
||||
<Text type="warning">
|
||||
中间的代理服务器必须转发未经修改的端到端消息头,并且必须缓存它们。
|
||||
</Text>
|
||||
<Text type="secondary">
|
||||
中间的代理服务器必须转发未经修改的端到端消息头,并且必须缓存它们。
|
||||
</Text>
|
||||
<Text type="error">
|
||||
中间的代理服务器必须转发未经修改的端到端消息头,并且必须缓存它们。
|
||||
</Text>
|
||||
<Text style={{ color: '#ccc' }}>
|
||||
中间的代理服务器必须转发未经修改的端到端消息头,并且必须缓存它们。
|
||||
</Text>
|
||||
</>
|
||||
`} />
|
||||
@@ -67,12 +95,12 @@ export const meta = {
|
||||
code={`
|
||||
<>
|
||||
<Text p>
|
||||
函数 用来封装可复用的功能。如果没有函数,一段特定的操作过程用几次就要重复写几次,而使用函数则只需写下函数名和一些简短的信息。
|
||||
函数用来封装可复用的功能。如果没有函数,一段特定的操作过程用几次就要重复写几次,而使用函数则只需写下函数名和一些简短的信息。
|
||||
</Text>
|
||||
|
||||
<Text>
|
||||
<Text small del>函数 用来封装可复用的功能。如果没有函数,一段特定的操作过程用几次就要重复写几次,而使用函数则只需写下函数名和一些简短的信息。</Text>
|
||||
<Text small>函数 用来封装可复用的功能。如果没有函数,一段特定的操作过程用几次就要重复写几次,而使用函数则只需写下函数名和一些简短的信息。</Text>
|
||||
<Text small del>函数用来封装可复用的功能。如果没有函数,一段特定的操作过程用几次就要重复写几次,而使用函数则只需写下函数名和一些简短的信息。</Text>
|
||||
<Text small b>函数用来封装可复用的功能。如果没有函数,一段特定的操作过程用几次就要重复写几次,而使用函数则只需写下函数名和一些简短的信息。</Text>
|
||||
</Text>
|
||||
</>
|
||||
`} />
|
||||
@@ -95,17 +123,28 @@ export const meta = {
|
||||
|
||||
| 属性 | 描述 | 类型 | 推荐值 | 默认
|
||||
| ---------- | ---------- | ---- | -------------- | ------ |
|
||||
| **p** | component name | `boolean` | - | `true` |
|
||||
| **h1 - h6** | component name | `boolean` | - | `false` |
|
||||
| **small** | component name | `boolean` | - | `false` |
|
||||
| **span** | component name | `boolean` | - | `false` |
|
||||
| **del** | component name | `boolean` | - | `false` |
|
||||
| **i** | component name | `boolean` | - | `false` |
|
||||
| **em** | component name | `boolean` | - | `false` |
|
||||
| **b** | component name | `boolean` | - | `false` |
|
||||
| **type** | text type | `NormalTypes` | `'default', 'secondary', 'success', 'warning', 'error'` | `default` |
|
||||
| **p** | 渲染的组件名 | `boolean` | - | `true` |
|
||||
| **h1 - h6** | 渲染的组件名 | `boolean` | - | `false` |
|
||||
| **small** | 渲染的组件名 | `boolean` | - | `false` |
|
||||
| **span** | 渲染的组件名 | `boolean` | - | `false` |
|
||||
| **del** | 渲染的组件名 | `boolean` | - | `false` |
|
||||
| **i** | 渲染的组件名 | `boolean` | - | `false` |
|
||||
| **em** | 渲染的组件名 | `boolean` | - | `false` |
|
||||
| **b** | 渲染的组件名 | `boolean` | - | `false` |
|
||||
| **blockquote** | 渲染的组件名 | `boolean` | - | `false` |
|
||||
| **type** | 文字类型 | `NormalTypes` | [TextTypes](#texttypes) | `default` |
|
||||
| ... | 原生属性 | `HTMLAttributes` | `'id', 'className', ...` | - |
|
||||
|
||||
<Attributes.Title>TextTypes</Attributes.Title>
|
||||
|
||||
```ts
|
||||
type TextTypes = 'default'
|
||||
| 'secondary'
|
||||
| 'success'
|
||||
| 'warning'
|
||||
| 'error'
|
||||
```
|
||||
|
||||
</Attributes>
|
||||
|
||||
export default ({ children }) => <Layout meta={meta}>{children}</Layout>
|
||||
|
||||
Reference in New Issue
Block a user