Skip to content

Commit

Permalink
feat(ConfigProvider): add icons config
Browse files Browse the repository at this point in the history
  • Loading branch information
guoyunhe committed Apr 11, 2024
1 parent ad988cf commit 9f3cd52
Show file tree
Hide file tree
Showing 45 changed files with 452 additions and 185 deletions.
7 changes: 4 additions & 3 deletions src/components/center-popup/center-popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import classNames from 'classnames'
import { NativeProps, withNativeProps } from '../../utils/native-props'
import { ShouldRender } from '../../utils/should-render'
import { useLockScroll } from '../../utils/use-lock-scroll'
import { CloseOutline } from 'antd-mobile-icons'
import {
defaultPopupBaseProps,
PopupBaseProps,
} from '../popup/popup-base-props'
import { useConfig } from '../config-provider'

const classPrefix = 'adm-center-popup'

Expand All @@ -38,7 +38,8 @@ const defaultProps = {
}

export const CenterPopup: FC<CenterPopupProps> = p => {
const props = mergeProps(defaultProps, p)
const { popup: componentConfig = {} } = useConfig()
const props = mergeProps(defaultProps, componentConfig, p)

const unmountedRef = useUnmountedRef()
const style = useSpring({
Expand Down Expand Up @@ -134,7 +135,7 @@ export const CenterPopup: FC<CenterPopupProps> = p => {
props.onClose?.()
}}
>
<CloseOutline />
{props.closeIcon}
</a>
)}
{body}
Expand Down
12 changes: 9 additions & 3 deletions src/components/check-list/check-list.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from 'react'
import type { FC, ReactNode } from 'react'
import { CheckOutline } from 'antd-mobile-icons'
import { NativeProps, withNativeProps } from '../../utils/native-props'
import List, { ListProps } from '../list'
import { mergeProps } from '../../utils/with-default-props'
import { CheckListContext } from './context'
import { usePropsValue } from '../../utils/use-props-value'
import { CheckOutline } from 'antd-mobile-icons'
import { useConfig } from '../config-provider'

const classPrefix = 'adm-check-list'

Expand All @@ -26,11 +27,16 @@ export type CheckListProps = Pick<ListProps, 'mode' | 'style'> & {
const defaultProps = {
multiple: false,
defaultValue: [],
activeIcon: <CheckOutline />,
}

export const CheckList: FC<CheckListProps> = p => {
const props = mergeProps(defaultProps, p)
const { checkList: componentConfig = {} } = useConfig()
const props = mergeProps(
{ activeIcon: <CheckOutline /> },
componentConfig,
defaultProps,
p
)

const [value, setValue] = usePropsValue(props)

Expand Down
39 changes: 27 additions & 12 deletions src/components/collapse/collapse.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import React, { isValidElement, useRef } from 'react'
import type { FC, ReactNode, ReactElement } from 'react'
import { NativeProps, withNativeProps } from '../../utils/native-props'
import List from '../list'
import { animated, useSpring } from '@react-spring/web'
import { useMount } from 'ahooks'
import { DownOutline } from 'antd-mobile-icons'
import classNames from 'classnames'
import { useSpring, animated } from '@react-spring/web'
import { usePropsValue } from '../../utils/use-props-value'
import { useMount } from 'ahooks'
import type { FC, ReactElement, ReactNode } from 'react'
import React, { isValidElement, useRef } from 'react'
import { NativeProps, withNativeProps } from '../../utils/native-props'
import { useShouldRender } from '../../utils/should-render'
import { useIsomorphicUpdateLayoutEffect } from '../../utils/use-isomorphic-update-layout-effect'
import { traverseReactNode } from '../../utils/traverse-react-node'
import { useIsomorphicUpdateLayoutEffect } from '../../utils/use-isomorphic-update-layout-effect'
import { usePropsValue } from '../../utils/use-props-value'
import { useConfig } from '../config-provider'
import List from '../list'

const classPrefix = `adm-collapse`

Expand All @@ -20,8 +21,12 @@ export type CollapsePanelProps = {
forceRender?: boolean
destroyOnClose?: boolean
onClick?: (event: React.MouseEvent<Element, MouseEvent>) => void
arrow?: ReactNode | ((active: boolean) => ReactNode)
arrowIcon?: ReactNode | ((active: boolean) => ReactNode)
children?: ReactNode
/**
* @deprecated use `arrowIcon` instead
*/
arrow?: ReactNode | ((active: boolean) => ReactNode)
} & NativeProps

export const CollapsePanel: FC<CollapsePanelProps> = () => {
Expand Down Expand Up @@ -106,6 +111,10 @@ type ValueProps<T> = {
activeKey?: T
defaultActiveKey?: T
onChange?: (activeKey: T) => void
arrowIcon?: ReactNode | ((active: boolean) => ReactNode)
/**
* @deprecated use `arrowIcon` instead
*/
arrow?: ReactNode | ((active: boolean) => ReactNode)
}

Expand All @@ -121,6 +130,7 @@ export type CollapseProps = (
} & NativeProps

export const Collapse: FC<CollapseProps> = props => {
const { collapse: componentConfig = {} } = useConfig()
const panels: ReactElement<CollapsePanelProps>[] = []
traverseReactNode(props.children, child => {
if (!isValidElement<CollapsePanelProps>(child)) return
Expand Down Expand Up @@ -197,11 +207,16 @@ export const Collapse: FC<CollapseProps> = props => {
}

const renderArrow = () => {
let arrow: CollapseProps['arrow'] = <DownOutline />
if (props.arrow !== undefined) {
let arrow: CollapseProps['arrowIcon'] =
componentConfig?.arrowIcon || <DownOutline />
if (props.arrowIcon !== undefined) {
arrow = props.arrowIcon
} else if (props.arrow !== undefined) {
arrow = props.arrow
}
if (panel.props.arrow !== undefined) {
if (panel.props.arrowIcon !== undefined) {
arrow = panel.props.arrowIcon
} else if (panel.props.arrow !== undefined) {
arrow = panel.props.arrow
}
return typeof arrow === 'function' ? (
Expand Down
4 changes: 2 additions & 2 deletions src/components/collapse/index.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ A content area that can be collapsed/expanded.
| --- | --- | --- | --- |
| accordion | Whether to enable accordion mode | `boolean` | `false` |
| activeKey | The `key` of the currently expanded panel | accordion mode: `string \| null` <br/>non-accordion mode: `string[]` | - |
| arrow | Custom arrow. if you pass a ReactNode, antd-mobile will add a rotate animation for you. | `React.ReactNode \| ((active: boolean) => React.ReactNode)` | - |
| arrowIcon | Custom arrow icon. if you pass a ReactNode, antd-mobile will add a rotate animation for you. | `React.ReactNode \| ((active: boolean) => React.ReactNode)` | - |
| defaultActiveKey | The `key` of the expanded panel by default | accordion mode: `string \| null` <br/>non-accordion mode: `string[]` | - |
| onChange | Triggered when the panel is switched | accordion mode: `(activeKey: string \| null) => void` <br /> non-accordion mode: `(activeKey: string[]) => void` | - |

Expand All @@ -31,7 +31,7 @@ A content area that can be collapsed/expanded.

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| arrow | Custom arrow | `React.ReactNode \| ((active: boolean) => React.ReactNode)` | - |
| arrowIcon | Custom arrow icon | `React.ReactNode \| ((active: boolean) => React.ReactNode)` | - |
| destroyOnClose | Destroy `dom` when not visible | `boolean` | `false` |
| disabled | Whether disabled or not | `boolean` | `false` |
| forceRender | Whether to render the `DOM` structure when hidden | `boolean` | `false` |
Expand Down
4 changes: 2 additions & 2 deletions src/components/collapse/index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
| --- | --- | --- | --- |
| accordion | 是否开启手风琴模式 | `boolean` | `false` |
| activeKey | 当前展开面板的 `key` | 手风琴模式:`string \| null` <br/>非手风琴模式:`string[]` | - |
| arrow | 自定义箭头,如果是 ReactNode,那么 antd-mobile 会自动为你增加旋转动画效果 | `ReactNode \| ((active: boolean) => React.ReactNode)` | - |
| arrowIcon | 自定义箭头图标,如果是 ReactNode,那么 antd-mobile 会自动为你增加旋转动画效果 | `ReactNode \| ((active: boolean) => React.ReactNode)` | - |
| defaultActiveKey | 默认展开面板的 `key` | 手风琴模式:`string \| null` <br/>非手风琴模式:`string[]` | - |
| onChange | 切换面板时触发 | 手风琴模式:`(activeKey: string \| null) => void` <br /> 非手风琴模式:`(activeKey: string[]) => void` | - |

Expand All @@ -31,7 +31,7 @@

| 属性 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| arrow | 自定义箭头 | `ReactNode \| ((active: boolean) => React.ReactNode)` | - |
| arrowIcon | 自定义箭头图标 | `ReactNode \| ((active: boolean) => React.ReactNode)` | - |
| destroyOnClose | 不可见时是否销毁 `DOM` 结构 | `boolean` | `false` |
| disabled | 是否为禁用状态 | `boolean` | `false` |
| forceRender | 被隐藏时是否渲染 `DOM` 结构 | `boolean` | `false` |
Expand Down
57 changes: 49 additions & 8 deletions src/components/config-provider/config-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,54 @@
import React, { useContext } from 'react'
import type { FC, ReactNode } from 'react'
import React, { useContext } from 'react'
import { Locale } from '../../locales/base'
import zhCN from '../../locales/zh-CN'
import { mergeProps } from '../../utils/with-default-props'

type Config = {
locale: Locale
checkList?: {
activeIcon?: ReactNode
}
collapse?: {
arrowIcon?: ReactNode | ((active: boolean) => ReactNode)
}
dropdown?: {
arrowIcon?: ReactNode
}
form?: {
helpIcon?: ReactNode
}
input?: {
clearIcon?: ReactNode
}
list?: {
arrowIcon?: ReactNode
}
navBar?: {
backIcon?: ReactNode
}
noticeBar?: {
icon?: ReactNode
closeIcon?: ReactNode
}
popup?: {
closeIcon?: ReactNode
}
result?: {
successIcon?: ReactNode
errorIcon?: ReactNode
infoIcon?: ReactNode
waitingIcon?: ReactNode
warningIcon?: ReactNode
}
searchBar?: {
searchIcon?: ReactNode
}
toast?: {
successIcon?: ReactNode
errorIcon?: ReactNode
loadingIcon?: ReactNode
}
}

export const defaultConfigRef: {
Expand All @@ -23,9 +67,9 @@ export function getDefaultConfig() {
return defaultConfigRef.current
}

const ConfigContext = React.createContext<Config | null>(null)
const ConfigContext = React.createContext<Config>(defaultConfigRef.current)

export type ConfigProviderProps = Config & {
export type ConfigProviderProps = Partial<Config> & {
children?: ReactNode
}

Expand All @@ -35,16 +79,13 @@ export const ConfigProvider: FC<ConfigProviderProps> = props => {

return (
<ConfigContext.Provider
value={{
...parentConfig,
...config,
}}
value={mergeProps(defaultConfigRef.current, parentConfig, config)}
>
{children}
</ConfigContext.Provider>
)
}

export function useConfig() {
return useContext(ConfigContext) ?? getDefaultConfig()
return useContext(ConfigContext)
}
29 changes: 29 additions & 0 deletions src/components/config-provider/index.en.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,36 @@
# ConfigProvider

Configure locale messages and custom icons globally.

## When to use

- You want to use other languages than English
- You want to use your own icon set instead of `antd-mobile-icons`

## Demos

<code src="./demos/demo1.tsx" ></code>

<code src="./demos/demo2.tsx" ></code>

## ConfigProvider

### Props

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| locale | Locale messages | `Locale` | [zh-CN] |
| checkList | CheckList config | `{ activeIcon?: ReactNode }` | - |
| collapse | Collapse config | `{ arrowIcon?: ReactNode \| ((active: boolean) => ReactNode) }` | - |
| dropdown | Dropdown config | `{ arrowIcon?: ReactNode }` | - |
| form | Form config | `{ helpIcon?: ReactNode }` | - |
| input | Input config | `{ clearIcon?: ReactNode }` | - |
| list | List config | `{ arrowIcon?: ReactNode }` | - |
| navBar | NavBar config | `{ backIcon?: ReactNode }` | - |
| noticeBar | NoticeBar config | `{ icon?: ReactNode, closeIcon?: ReactNode }` | - |
| popup | Popup config | `{ closeIcon?: ReactNode }` | - |
| result | Result config | `{ successIcon?: ReactNode, errorIcon?: ReactNode, infoIcon?: ReactNode, waitingIcon?: ReactNode, warningIcon?: ReactNode }` | - |
| searchBar | SearchBar config | `{ icon?: ReactNode }` | - |
| toast | Toast config | `{ successIcon?: ReactNode, failIcon?: ReactNode, loadingIcon?: ReactNode }` | - |

[zh-CN]: https://github.com/ant-design/ant-design-mobile/blob/master/src/locales/zh-CN.ts
29 changes: 29 additions & 0 deletions src/components/config-provider/index.zh.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,36 @@
# ConfigProvider 配置

用于全局配置本地化文案和个性化图标。

## 何时使用

- 您想使用除英文之外的语言。
- 您想使用自己的图标集,而不是内置的 `antd-mobile-icons`

## 示例

<code src="./demos/demo1.tsx" ></code>

<code src="./demos/demo2.tsx" ></code>

## ConfigProvider

### 属性

| 属性 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| locale | 本地化文案 | `Locale` | [zh-CN] |
| checkList | CheckList 配置 | `{ activeIcon?: ReactNode }` | - |
| collapse | Collapse 配置 | `{ arrowIcon?: ReactNode \| ((active: boolean) => ReactNode) }` | - |
| dropdown | Dropdown 配置 | `{ arrowIcon?: ReactNode }` | - |
| form | Form 配置 | `{ helpIcon?: ReactNode }` | - |
| input | Input 配置 | `{ clearIcon?: ReactNode }` | - |
| list | List 配置 | `{ arrowIcon?: ReactNode }` | - |
| navBar | NavBar 配置 | `{ backIcon?: ReactNode }` | - |
| noticeBar | NoticeBar 配置 | `{ icon?: ReactNode, closeIcon?: ReactNode }` | - |
| popup | Popup 配置 | `{ closeIcon?: ReactNode }` | - |
| result | Result 配置 | `{ successIcon?: ReactNode, errorIcon?: ReactNode, infoIcon?: ReactNode, waitingIcon?: ReactNode, warningIcon?: ReactNode }` | - |
| searchBar | SearchBar 配置 | `{ icon?: ReactNode }` | - |
| toast | Toast 配置 | `{ successIcon?: ReactNode, failIcon?: ReactNode, loadingIcon?: ReactNode }` | - |

[zh-CN]: https://github.com/ant-design/ant-design-mobile/blob/master/src/locales/zh-CN.ts
Loading

0 comments on commit 9f3cd52

Please sign in to comment.