-
Notifications
You must be signed in to change notification settings - Fork 66
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
raylotan
committed
Aug 9, 2024
1 parent
8dd010e
commit 7d233ea
Showing
11 changed files
with
176 additions
and
106 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import isFunction from 'lodash/isFunction'; | ||
import React, { ReactElement, ReactNode } from 'react'; | ||
import log from '../_common/js/log'; | ||
import { TNode } from '../common'; | ||
|
||
// 解析 TNode 数据结构 | ||
export default function parseTNode( | ||
renderNode: TNode | TNode<any> | undefined, | ||
renderParams?: any, | ||
defaultNode?: ReactNode, | ||
): ReactNode { | ||
let node: ReactNode = null; | ||
|
||
if (typeof renderNode === 'function') { | ||
node = renderNode(renderParams); | ||
} else if (renderNode === true) { | ||
node = defaultNode; | ||
} else if (renderNode !== null) { | ||
node = renderNode ?? defaultNode; | ||
} | ||
return node as ReactNode; | ||
} | ||
|
||
/** | ||
* 解析各种数据类型的 TNode | ||
* 函数类型:content={(props) => <Icon></Icon>} | ||
* 组件类型:content={<Button>click me</Button>} 这种方式可以避免函数重复渲染,对应的 props 已经注入 | ||
* 字符类型 | ||
*/ | ||
export function parseContentTNode<T>(tnode: TNode<T>, props: T) { | ||
if (isFunction(tnode)) return tnode(props) as ReactNode; | ||
if (!tnode || ['string', 'number', 'boolean'].includes(typeof tnode)) return tnode as ReactNode; | ||
try { | ||
return React.cloneElement(tnode as ReactElement, { ...props }); | ||
} catch (e) { | ||
log.warn('parseContentTNode', `${tnode} is not a valid ReactNode`); | ||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,88 +1,92 @@ | ||
import classNames from 'classnames'; | ||
import React, { forwardRef, type MouseEvent } from 'react'; | ||
import React, { forwardRef, memo } from 'react'; | ||
import { Icon } from 'tdesign-icons-react'; | ||
import noop from '../_util/noop'; | ||
import parseTNode from 'tdesign-mobile-react/_util/parseTNode'; | ||
import { StyledProps } from 'tdesign-mobile-react/common'; | ||
import useDefaultProps from 'tdesign-mobile-react/hooks/useDefaultProps'; | ||
import useConfig from '../_util/useConfig'; | ||
import { tagDefaultProps } from './defaultProps'; | ||
import { TdTagProps } from './type'; | ||
|
||
export interface TagProps extends TdTagProps { | ||
className: string; | ||
style: object; | ||
} | ||
export interface TagProps extends TdTagProps, StyledProps { } | ||
|
||
const Tag = forwardRef<HTMLDivElement, TagProps>((props, ref) => { | ||
const { | ||
className = '', | ||
style = {}, | ||
closable = false, | ||
content = null, | ||
disabled = false, | ||
icon = undefined, | ||
maxWidth, | ||
children = '', | ||
shape = 'square', | ||
size = 'medium', | ||
theme = 'default', | ||
variant = 'dark', | ||
onClick = noop, | ||
onClose = noop, | ||
...other | ||
} = props; | ||
const Tag: React.FC<TagProps> = memo( | ||
forwardRef<HTMLDivElement, TagProps>((originProps, ref) => { | ||
const props = useDefaultProps(originProps, tagDefaultProps) | ||
const { | ||
className, | ||
style, | ||
closable, | ||
content, | ||
disabled, | ||
icon, | ||
maxWidth, | ||
children, | ||
shape, | ||
size, | ||
theme, | ||
variant, | ||
onClick, | ||
onClose, | ||
...otherProps | ||
} = props; | ||
|
||
const { classPrefix } = useConfig(); | ||
const baseClass = `${classPrefix}-tag`; | ||
const { classPrefix } = useConfig(); | ||
const baseClass = `${classPrefix}-tag`; | ||
|
||
const tagClassNames = classNames( | ||
`${baseClass}`, | ||
`${baseClass}--${theme}`, | ||
`${baseClass}--${shape}`, | ||
`${baseClass}--${variant}`, | ||
`${baseClass}--${size}`, | ||
{ | ||
[`${classPrefix}-is-closable ${baseClass}--closable`]: closable, | ||
[`${classPrefix}-is-disabled ${baseClass}--disabled`]: disabled, | ||
}, | ||
className, | ||
); | ||
const tagClassNames = classNames( | ||
`${baseClass}`, | ||
`${baseClass}--${theme}`, | ||
`${baseClass}--${shape}`, | ||
`${baseClass}--${variant}`, | ||
`${baseClass}--${size}`, | ||
{ | ||
[`${classPrefix}-is-closable ${baseClass}--closable`]: closable, | ||
[`${classPrefix}-is-disabled ${baseClass}--disabled`]: disabled, | ||
}, | ||
className, | ||
); | ||
|
||
const tagStyle = { | ||
...style, | ||
maxWidth: typeof maxWidth === 'number' ? `${maxWidth}px` : maxWidth, | ||
}; | ||
const tagStyle = { | ||
...style, | ||
maxWidth: typeof maxWidth === 'number' ? `${maxWidth}px` : maxWidth, | ||
}; | ||
|
||
const handleClose = (e: MouseEvent): void => { | ||
e.stopPropagation(); | ||
if (!props.disabled) { | ||
onClose?.({ e }); | ||
} | ||
}; | ||
const handleClose = (e) => { | ||
e.stopPropagation(); | ||
if (!props.disabled) { | ||
onClose?.({ e }); | ||
} | ||
}; | ||
|
||
const handleClick = (e: MouseEvent) => { | ||
if (disabled) { | ||
return; | ||
} | ||
onClick?.({ e }); | ||
}; | ||
const handleClick = (e) => { | ||
if (disabled) { | ||
return; | ||
} | ||
onClick?.({ e }); | ||
}; | ||
|
||
return ( | ||
<span | ||
className={tagClassNames} | ||
style={tagStyle} | ||
aria-disabled={props.disabled} | ||
role="button" | ||
onClick={handleClick} | ||
ref={ref} | ||
{...other} | ||
> | ||
{icon && <span className={`${baseClass}__icon`}>{icon}</span>} | ||
<span className={`${baseClass}__text`}>{content || children}</span> | ||
{props.closable && ( | ||
<span className={`${baseClass}__icon-close`} onClick={handleClose}> | ||
<Icon name="close" /> | ||
</span> | ||
)} | ||
</span> | ||
) | ||
}); | ||
const ChildNode = parseTNode(content) || parseTNode(children); | ||
|
||
export default React.memo(Tag); | ||
return ( | ||
<span | ||
className={tagClassNames} | ||
style={tagStyle} | ||
aria-disabled={props.disabled} | ||
role="button" | ||
onClick={handleClick} | ||
ref={ref} | ||
{...otherProps} | ||
> | ||
{icon && <span className={`${baseClass}__icon`}>{icon}</span>} | ||
<span className={`${baseClass}__text`}>{ChildNode}</span> | ||
{props.closable && ( | ||
<span className={`${baseClass}__icon-close`} onClick={handleClose}> | ||
<Icon name="close" /> | ||
</span> | ||
)} | ||
</span> | ||
) | ||
})); | ||
|
||
export default Tag; |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/** | ||
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC | ||
* */ | ||
|
||
import { TdCheckTagProps, TdTagProps } from './type'; | ||
|
||
export const tagDefaultProps: TdTagProps = { | ||
closable: false, | ||
disabled: false, | ||
icon: undefined, | ||
shape: 'square', | ||
size: 'medium', | ||
theme: 'default', | ||
variant: 'dark', | ||
}; | ||
|
||
export const checkTagDefaultProps: TdCheckTagProps = { | ||
closable: false, | ||
disabled: false, | ||
shape: 'square', | ||
size: 'medium', | ||
variant: 'dark', | ||
}; |