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 4, 2024
1 parent cf550e4 commit 8573e82
Show file tree
Hide file tree
Showing 22 changed files with 232 additions and 81 deletions.
6 changes: 5 additions & 1 deletion src/components/center-popup/center-popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
defaultPopupBaseProps,
PopupBaseProps,
} from '../popup/popup-base-props'
import { useConfig } from '../config-provider'

const classPrefix = 'adm-center-popup'

Expand All @@ -39,6 +40,9 @@ const defaultProps = {

export const CenterPopup: FC<CenterPopupProps> = p => {
const props = mergeProps(defaultProps, p)
const {
icons: { CenterPopupClose = CloseOutline },
} = useConfig()

const unmountedRef = useUnmountedRef()
const style = useSpring({
Expand Down Expand Up @@ -134,7 +138,7 @@ export const CenterPopup: FC<CenterPopupProps> = p => {
props.onClose?.()
}}
>
<CloseOutline />
<CenterPopupClose />
</a>
)}
{body}
Expand Down
9 changes: 6 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,13 @@ 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 {
icons: { CheckListActive = CheckOutline },
} = useConfig()
const props = mergeProps({ activeIcon: <CheckListActive /> }, defaultProps, p)

const [value, setValue] = usePropsValue(props)

Expand Down
6 changes: 5 additions & 1 deletion src/components/collapse/collapse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { useMount } from 'ahooks'
import { useShouldRender } from '../../utils/should-render'
import { useIsomorphicUpdateLayoutEffect } from '../../utils/use-isomorphic-update-layout-effect'
import { traverseReactNode } from '../../utils/traverse-react-node'
import { useConfig } from '../config-provider'

const classPrefix = `adm-collapse`

Expand Down Expand Up @@ -121,6 +122,9 @@ export type CollapseProps = (
} & NativeProps

export const Collapse: FC<CollapseProps> = props => {
const {
icons: { CollapseArrow = DownOutline },
} = useConfig()
const panels: ReactElement<CollapsePanelProps>[] = []
traverseReactNode(props.children, child => {
if (!isValidElement<CollapsePanelProps>(child)) return
Expand Down Expand Up @@ -197,7 +201,7 @@ export const Collapse: FC<CollapseProps> = props => {
}

const renderArrow = () => {
let arrow: CollapseProps['arrow'] = <DownOutline />
let arrow: CollapseProps['arrow'] = <CollapseArrow />
if (props.arrow !== undefined) {
arrow = props.arrow
}
Expand Down
50 changes: 42 additions & 8 deletions src/components/config-provider/config-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,54 @@
import React, { useContext } from 'react'
import type { FC, ReactNode } from 'react'
import type { ComponentType, FC, ReactNode } from 'react'
import { Locale } from '../../locales/base'
import zhCN from '../../locales/zh-CN'
import { mergeProps } from '../../utils/with-default-props'

export type IconMap = Partial<
Record<
| 'CenterPopupClose'
| 'CheckListActive'
| 'CollapseArrow'
| 'DropdownItemArrow'
| 'FormItemHelp'
| 'ImageUploaderUpload'
| 'ImageUploaderDelete'
| 'InputClear'
| 'ListItemArrow'
| 'NavBarBackArrow'
| 'NoticeBarClose'
| 'NoticeBarNotice'
| 'NumberKeyboardClose'
| 'NumberKeyboardDelete'
| 'PopupClose'
| 'ResultSuccess'
| 'ResultError'
| 'ResultInfo'
| 'ResultWaiting'
| 'ResultWarning'
| 'SearchBarSearch'
| 'StepperPlus'
| 'StepperMinus'
| 'ToastSuccess'
| 'ToastFail'
| 'ToastLoading',
ComponentType<{ className?: string }>
>
>

const defaultIcons: IconMap = {}

type Config = {
locale: Locale
icons: IconMap
}

export const defaultConfigRef: {
current: Config
} = {
current: {
locale: zhCN,
icons: defaultIcons,
},
}

Expand All @@ -23,9 +60,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 +72,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)
}
4 changes: 2 additions & 2 deletions src/components/config-provider/tests/config-provider.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ describe('ConfigProvider', () => {
})
})

test('useConfig should only has `locale`', () => {
test('useConfig should only has `locale` and `icons`', () => {
let config: ReturnType<typeof useConfig>

const Demo = () => {
Expand All @@ -109,6 +109,6 @@ describe('ConfigProvider', () => {
}
render(<Demo />)

expect(Object.keys(config!)).toEqual(['locale'])
expect(Object.keys(config!)).toEqual(['locale', 'icons'])

Check warning on line 112 in src/components/config-provider/tests/config-provider.test.tsx

View workflow job for this annotation

GitHub Actions / check

Forbidden non-null assertion

Check warning on line 112 in src/components/config-provider/tests/config-provider.test.tsx

View workflow job for this annotation

GitHub Actions / check

Forbidden non-null assertion
})
})
8 changes: 6 additions & 2 deletions src/components/dropdown/item.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import classNames from 'classnames'
import React from 'react'
import type { FC, ReactNode } from 'react'
import { DownFill } from 'antd-mobile-icons'
import { NativeProps, withNativeProps } from '../../utils/native-props'
import { useShouldRender } from '../../utils/should-render'
import { DownFill } from 'antd-mobile-icons'
import { useConfig } from '../config-provider'

const classPrefix = `adm-dropdown-item`

Expand All @@ -20,6 +21,9 @@ export type DropdownItemProps = {
} & NativeProps

const Item: FC<DropdownItemProps> = props => {
const {
icons: { DropdownItemArrow = DownFill },
} = useConfig()
const cls = classNames(classPrefix, {
[`${classPrefix}-active`]: props.active,
[`${classPrefix}-highlight`]: props.highlight ?? props.active,
Expand All @@ -35,7 +39,7 @@ const Item: FC<DropdownItemProps> = props => {
[`${classPrefix}-title-arrow-active`]: props.active,
})}
>
{props.arrow === undefined ? <DownFill /> : props.arrow}
{props.arrow === undefined ? <DropdownItemArrow /> : props.arrow}
</span>
</div>
</div>
Expand Down
7 changes: 5 additions & 2 deletions src/components/form/form-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,10 @@ const FormItemLayout: FC<FormItemLayoutProps> = props => {

const context = useContext(FormContext)

const { locale } = useConfig()
const {
locale,
icons: { FormItemHelp = QuestionCircleOutline },
} = useConfig()

const hasFeedback =
props.hasFeedback !== undefined ? props.hasFeedback : context.hasFeedback
Expand Down Expand Up @@ -162,7 +165,7 @@ const FormItemLayout: FC<FormItemLayoutProps> = props => {
e.preventDefault()
}}
>
<QuestionCircleOutline />
<FormItemHelp />
</span>
</Popover>
)}
Expand Down
22 changes: 18 additions & 4 deletions src/components/image-uploader/image-uploader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ const classPrefix = `adm-image-uploader`
const defaultProps = {
disableUpload: false,
deletable: true,
deleteIcon: <CloseOutline className={`${classPrefix}-cell-delete-icon`} />,
showUpload: true,
multiple: false,
maxCount: 0,
Expand All @@ -91,8 +90,23 @@ const defaultProps = {

export const ImageUploader = forwardRef<ImageUploaderRef, ImageUploaderProps>(
(p, ref) => {
const { locale } = useConfig()
const props = mergeProps(defaultProps, p)
const {
locale,
icons: {
ImageUploaderDelete = CloseOutline,
ImageUploaderUpload = AddOutline,
},
} = useConfig()

const props = mergeProps(
{
deleteIcon: (
<ImageUploaderDelete className={`${classPrefix}-cell-delete-icon`} />
),
},
defaultProps,
p
)
const { columns } = props
const [value, setValue] = usePropsValue(props)

Expand Down Expand Up @@ -312,7 +326,7 @@ export const ImageUploader = forwardRef<ImageUploaderRef, ImageUploaderProps>(
aria-label={locale.ImageUploader.upload}
>
<span className={`${classPrefix}-upload-button-icon`}>
<AddOutline />
<ImageUploaderUpload />
</span>
</span>
)}
Expand Down
7 changes: 5 additions & 2 deletions src/components/input/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ export const Input = forwardRef<InputRef, InputProps>((p, ref) => {
const [hasFocus, setHasFocus] = useState(false)
const compositionStartRef = useRef(false)
const nativeInputRef = useRef<HTMLInputElement>(null)
const { locale } = useConfig()
const {
locale,
icons: { InputClear = CloseCircleFill },
} = useConfig()

useImperativeHandle(ref, () => ({
clear: () => {
Expand Down Expand Up @@ -219,7 +222,7 @@ export const Input = forwardRef<InputRef, InputProps>((p, ref) => {
}}
aria-label={locale.Input.clear}
>
<CloseCircleFill />
<InputClear />
</div>
)}
</div>
Expand Down
6 changes: 5 additions & 1 deletion src/components/list/list-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { NativeProps, withNativeProps } from '../../utils/native-props'
import { RightOutline } from 'antd-mobile-icons'
import classNames from 'classnames'
import { isNodeWithContent } from '../../utils/is-node-with-content'
import { useConfig } from '../config-provider'

const classPrefix = `adm-list-item`

Expand All @@ -22,6 +23,9 @@ export type ListItemProps = {
>

export const ListItem: FC<ListItemProps> = props => {
const {
icons: { ListItemArrow = RightOutline },
} = useConfig()
const clickable = props.clickable ?? !!props.onClick
const arrow = props.arrow === undefined ? clickable : props.arrow

Expand All @@ -46,7 +50,7 @@ export const ListItem: FC<ListItemProps> = props => {
)}
{isNodeWithContent(arrow) && (
<div className={`${classPrefix}-content-arrow`}>
{arrow === true ? <RightOutline /> : arrow}
{arrow === true ? <ListItemArrow /> : arrow}
</div>
)}
</div>
Expand Down
6 changes: 5 additions & 1 deletion src/components/nav-bar/nav-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import classNames from 'classnames'
import { LeftOutline } from 'antd-mobile-icons'
import { NativeProps, withNativeProps } from '../../utils/native-props'
import { mergeProps } from '../../utils/with-default-props'
import { useConfig } from '../config-provider'

const classPrefix = `adm-nav-bar`

Expand All @@ -20,6 +21,9 @@ const defaultProps = {
backArrow: true,
}
export const NavBar: FC<NavBarProps> = p => {
const {
icons: { NavBarBackArrow = LeftOutline },
} = useConfig()

Check warning on line 26 in src/components/nav-bar/nav-bar.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/nav-bar/nav-bar.tsx#L26

Added line #L26 was not covered by tests
const props = mergeProps(defaultProps, p)
const { back, backArrow } = props

Expand All @@ -31,7 +35,7 @@ export const NavBar: FC<NavBarProps> = p => {
<div className={`${classPrefix}-back`} onClick={props.onBack}>
{backArrow && (
<span className={`${classPrefix}-back-arrow`}>
{backArrow === true ? <LeftOutline /> : backArrow}
{backArrow === true ? <NavBarBackArrow /> : backArrow}
</span>
)}
<span aria-hidden='true'>{back}</span>
Expand Down
9 changes: 6 additions & 3 deletions src/components/notice-bar/notice-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { mergeProps } from '../../utils/with-default-props'
import { NativeProps, withNativeProps } from '../../utils/native-props'
import { useResizeEffect } from '../../utils/use-resize-effect'
import { useMutationEffect } from '../../utils/use-mutation-effect'
import { useConfig } from '../config-provider'

const classPrefix = `adm-notice-bar`

Expand Down Expand Up @@ -45,11 +46,13 @@ const defaultProps = {
delay: 2000,
speed: 50,
wrap: false,
icon: <SoundOutline />,
}

export const NoticeBar = memo<NoticeBarProps>(p => {
const props = mergeProps(defaultProps, p)
const {
icons: { NoticeBarClose = CloseOutline, NoticeBarNotice = SoundOutline },
} = useConfig()
const props = mergeProps({ icon: <NoticeBarNotice /> }, defaultProps, p)

const containerRef = useRef<HTMLSpanElement>(null)
const textRef = useRef<HTMLSpanElement>(null)
Expand Down Expand Up @@ -149,7 +152,7 @@ export const NoticeBar = memo<NoticeBarProps>(p => {
props.onClose?.()
}}
>
<CloseOutline className={`${classPrefix}-close-icon`} />
<NoticeBarClose className={`${classPrefix}-close-icon`} />
</div>
)}
</span>
Expand Down
Loading

0 comments on commit 8573e82

Please sign in to comment.