code.tsx 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. import React, { useCallback, useMemo, useState } from 'react';
  2. import { PropsWithChildren } from 'react';
  3. import { cssClasses } from '@douyinfe/semi-foundation/chat/constants';
  4. import copy from 'copy-text-to-clipboard';
  5. import { IconCopyStroked, IconTick } from '@douyinfe/semi-icons';
  6. import { nth } from 'lodash';
  7. import { code } from '../../markdownRender/components';
  8. // code's default height type is html/js/css, add jsx & tsx;
  9. import "prismjs/components/prism-jsx.js";
  10. import "prismjs/components/prism-tsx.js";
  11. import LocaleConsumer from "../../locale/localeConsumer";
  12. import { Locale } from "../../locale/interface";
  13. const { PREFIX_CHAT_BOX } = cssClasses;
  14. const Code = (props: PropsWithChildren<{ className: string }>) => {
  15. const [copied, setCopied] = useState(false);
  16. const language = useMemo(() => {
  17. return nth(props.className?.split("-"), -1);
  18. }, [props.className]);
  19. const onCopyButtonClick = useCallback(() => {
  20. copy(props.children as string);
  21. setCopied(true);
  22. setTimeout(() => {
  23. setCopied(false);
  24. }, 2000);
  25. }, [props.children]);
  26. return language ? (<div className={`${PREFIX_CHAT_BOX}-content-code semi-always-dark`}>
  27. <div className={`${PREFIX_CHAT_BOX}-content-code-topSlot`}>
  28. <span className={`${PREFIX_CHAT_BOX}-content-code-topSlot-type`}>{language}</span>
  29. <span className={`${PREFIX_CHAT_BOX}-content-code-topSlot-copy`}>
  30. {copied ? (<span className={`${PREFIX_CHAT_BOX}-content-code-topSlot-copy-wrapper`}>
  31. <IconTick />
  32. <LocaleConsumer<Locale["Chat"]> componentName="Chat" >
  33. {(locale: Locale["Chat"]) => locale['copied']}
  34. </LocaleConsumer>
  35. </span>) : (<button
  36. className={`${PREFIX_CHAT_BOX}-content-code-topSlot-copy-wrapper ${PREFIX_CHAT_BOX}-content-code-topSlot-toCopy`}
  37. onClick={onCopyButtonClick}
  38. >
  39. <IconCopyStroked />
  40. <LocaleConsumer<Locale["Chat"]> componentName="Chat" >
  41. {(locale: Locale["Chat"]) => locale['copy']}
  42. </LocaleConsumer>
  43. </button>)}
  44. </span>
  45. </div>
  46. {code(props)}
  47. </div>) : (code(props));
  48. };
  49. export default Code;