numeral.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import React, { PureComponent } from 'react';
  2. import PropTypes from 'prop-types';
  3. import { strings } from '@douyinfe/semi-foundation/typography/constants';
  4. import Base from './base';
  5. import {
  6. TypographyBaseSize,
  7. TypographyBaseType,
  8. TypographyBaseRule,
  9. OmitTypographyProps,
  10. TypographyBaseTruncate,
  11. } from './interface';
  12. import { CopyableConfig, LinkType } from './title';
  13. import FormatNumeral from '@douyinfe/semi-foundation/typography/formatNumeral';
  14. type OmitNumeralProps = OmitTypographyProps;
  15. export interface NumeralProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, OmitNumeralProps> {
  16. rule?: TypographyBaseRule;
  17. precision?: number;
  18. truncate?: TypographyBaseTruncate;
  19. parser?: (value: string) => string;
  20. children?: React.ReactNode;
  21. className?: string;
  22. code?: boolean;
  23. component?: React.ElementType;
  24. copyable?: CopyableConfig | boolean;
  25. delete?: boolean;
  26. disabled?: boolean;
  27. icon?: React.ReactNode | string;
  28. link?: LinkType;
  29. mark?: boolean;
  30. size?: TypographyBaseSize;
  31. strong?: boolean;
  32. style?: React.CSSProperties;
  33. type?: TypographyBaseType;
  34. underline?: boolean
  35. }
  36. export default class Numeral extends PureComponent<NumeralProps> {
  37. static propTypes = {
  38. rule: PropTypes.oneOf(strings.RULE),
  39. precision: PropTypes.number,
  40. truncate: PropTypes.oneOf(strings.TRUNCATE),
  41. parser: PropTypes.func,
  42. copyable: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]),
  43. delete: PropTypes.bool,
  44. disabled: PropTypes.bool,
  45. icon: PropTypes.oneOfType([PropTypes.node, PropTypes.string]),
  46. mark: PropTypes.bool,
  47. underline: PropTypes.bool,
  48. link: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]),
  49. strong: PropTypes.bool,
  50. type: PropTypes.oneOf(strings.TYPE),
  51. size: PropTypes.oneOf(strings.SIZE),
  52. style: PropTypes.object,
  53. className: PropTypes.string,
  54. code: PropTypes.bool,
  55. component: PropTypes.string,
  56. };
  57. static defaultProps = {
  58. rule: 'text',
  59. precision: 0,
  60. truncate: 'round',
  61. parser: undefined,
  62. copyable: false,
  63. delete: false,
  64. icon: '',
  65. mark: false,
  66. underline: false,
  67. strong: false,
  68. link: false,
  69. type: 'primary',
  70. style: {},
  71. size: 'normal',
  72. className: '',
  73. };
  74. // Traverse the entire virtual DOM using a depth-first traversal algorithm, then format each piece. (in react)
  75. formatNodeDFS(node) {
  76. if (!Array.isArray(node)) {
  77. node = [node];
  78. }
  79. // Because the property is read-only, an object is returned for overwriting rather than directly modifying the object's contents.
  80. node = node.map(item => {
  81. if (typeof item === 'string' || typeof item === 'number') {
  82. // Formatting the digital content of nodes.
  83. return new FormatNumeral(
  84. String(item),
  85. this.props.rule,
  86. this.props.precision,
  87. this.props.truncate,
  88. this.props.parser
  89. ).format();
  90. }
  91. if (typeof item === 'function') {
  92. return this.formatNodeDFS(item());
  93. }
  94. if (typeof item === 'object' && 'children' in item['props']) {
  95. return {
  96. ...item,
  97. props: { ...item['props'], children: this.formatNodeDFS(item['props']['children']) },
  98. };
  99. }
  100. return item;
  101. });
  102. return node.length === 1 ? node[0] : node;
  103. }
  104. render() {
  105. // Deep copy and remove props that are not needed by the Base component.
  106. const baseProps = Object.assign({}, this.props) as Record<string, unknown>;
  107. delete baseProps.rule;
  108. delete baseProps.parser;
  109. // Each piece of content in the virtual DOM is formatted by the `formatNumeral` function.
  110. baseProps.children = this.formatNodeDFS(this.props.children);
  111. return <Base component={'span'} {...baseProps} />;
  112. }
  113. }