You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 lines
2.9 KiB

2 years ago
1 year ago
2 years ago
1 year ago
1 year ago
2 years ago
1 year ago
2 years ago
2 years ago
1 year ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. import IconAll, { ALL_ICON_KEYS, IconType as ParkIconType, IIconAllProps } from '@icon-park/react/es/all'
  2. import React, { Fragment } from 'react'
  3. import * as AntIcons from '@ant-design/icons/es/icons'
  4. import IconItem from './picker/IconRender.tsx'
  5. import { IconUnit } from './types.ts'
  6. import { createStyles } from '@/theme'
  7. type Prefix = 'antd:' | 'park:';
  8. type IconType = `${Prefix}${string}`;
  9. const useStyles = createStyles(({ css, cx }, props: any) => {
  10. const keyframes = css`
  11. @keyframes rotating {
  12. from {
  13. transform: rotate(0deg);
  14. }
  15. to {
  16. transform: rotate(360deg);
  17. }
  18. }
  19. `
  20. const container = css`
  21. display: inline-flex;
  22. align-items: center;
  23. justify-content: center;
  24. `
  25. const size = props.size ? css`
  26. height: ${props.size}px;
  27. width: ${props.size}px;
  28. line-height: ${props.size}px;
  29. ` : ''
  30. const isLoading = css`
  31. animation: rotating 2s linear infinite;
  32. `
  33. return {
  34. container: cx( container, size, props.className),
  35. isLoading: cx(keyframes, size, isLoading)
  36. }
  37. })
  38. interface IconProps extends Pick<IconUnit, 'type'> {
  39. type: IconType | IconUnit['type']
  40. isLoading?: boolean
  41. [key: string]: any
  42. }
  43. function isAntdOrParkIcon(value: string): value is IconType {
  44. return value.startsWith('antd:') || value.startsWith('park:')
  45. }
  46. export function Icon(props: IconProps) {
  47. const { styles, cx } = useStyles(props)
  48. const { type, isLoading, ...other } = props
  49. if (type && isAntdOrParkIcon(type)) {
  50. const [ t, c ] = type.split(':')
  51. return <IconItem {...other as any} type={t} componentName={c}/>
  52. }
  53. const AntIcon = AntIcons[type as keyof typeof AntIcons]
  54. if (AntIcon) {
  55. return <AntIcon {...other}/>
  56. }
  57. //如果是http或https链接,直接返回图片
  58. if (type && (type.startsWith('http') || type.startsWith('https') || type.startsWith('data:image'))) {
  59. // @ts-ignore 没有办法把所有的属性都传递给img
  60. return <img src={type} alt="icon" width={16} height={16} {...other}/>
  61. }
  62. if (ALL_ICON_KEYS.indexOf(type as ParkIconType) < 0) {
  63. return null
  64. }
  65. return (
  66. <Fragment>
  67. <IconAll type={type as IconType}
  68. className={cx(styles.container, {
  69. [styles.isLoading]: isLoading,
  70. })}
  71. theme="outline"
  72. size={other.size ?? 20}
  73. // fill="#868686"
  74. strokeWidth={3}
  75. {...other}/>
  76. </Fragment>
  77. )
  78. }
  79. // eslint-disable-next-line react-refresh/only-export-components
  80. export const getIcon = (type: string, props?: Partial<IIconAllProps>) => {
  81. if (React.isValidElement(type)) {
  82. return type
  83. }
  84. //判断是否为json格式
  85. if (type && type.startsWith('{') && type.endsWith('}')) {
  86. try {
  87. const obj = JSON.parse(type)
  88. type = obj.type
  89. props = obj
  90. } catch (e) { /* empty */
  91. }
  92. }
  93. return <Icon type={type} {...props}/>
  94. }
  95. export default Icon