objectInspector.tsx 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import {ComponentProps, MouseEvent, useMemo} from 'react';
  2. import {useTheme} from '@emotion/react';
  3. import styled from '@emotion/styled';
  4. import {
  5. chromeDark,
  6. chromeLight,
  7. ObjectInspector as OrigObjectInspector,
  8. } from '@sentry-internal/react-inspector';
  9. import {CopyToClipboardButton} from 'sentry/components/copyToClipboardButton';
  10. import ConfigStore from 'sentry/stores/configStore';
  11. import {useLegacyStore} from 'sentry/stores/useLegacyStore';
  12. import {space} from 'sentry/styles/space';
  13. type Props = Omit<ComponentProps<typeof OrigObjectInspector>, 'theme'> & {
  14. onCopy?: (copiedCode: string) => void;
  15. showCopyButton?: boolean;
  16. theme?: Record<string, any>;
  17. };
  18. function ObjectInspector({data, onCopy, showCopyButton, theme, ...props}: Props) {
  19. const config = useLegacyStore(ConfigStore);
  20. const emotionTheme = useTheme();
  21. const isDark = config.theme === 'dark';
  22. const INSPECTOR_THEME = useMemo(
  23. () => ({
  24. ...(isDark ? chromeDark : chromeLight),
  25. // Reset some theme values
  26. BASE_COLOR: 'inherit',
  27. ERROR_COLOR: emotionTheme.red400,
  28. TREENODE_FONT_FAMILY: emotionTheme.text.familyMono,
  29. TREENODE_FONT_SIZE: 'inherit',
  30. TREENODE_LINE_HEIGHT: 'inherit',
  31. BASE_BACKGROUND_COLOR: 'none',
  32. ARROW_FONT_SIZE: '10px',
  33. OBJECT_PREVIEW_OBJECT_MAX_PROPERTIES: 1,
  34. ...theme,
  35. }),
  36. [isDark, theme, emotionTheme.red400, emotionTheme.text]
  37. );
  38. const inspector = (
  39. <OrigObjectInspector
  40. data={data}
  41. // @ts-expect-error
  42. theme={INSPECTOR_THEME}
  43. {...props}
  44. />
  45. );
  46. if (showCopyButton) {
  47. return (
  48. <Wrapper>
  49. <StyledCopyButton
  50. borderless
  51. iconSize="xs"
  52. onCopy={onCopy}
  53. size="xs"
  54. text={JSON.stringify(data, null, '\t')}
  55. />
  56. <InspectorWrapper>{inspector}</InspectorWrapper>
  57. </Wrapper>
  58. );
  59. }
  60. return inspector;
  61. }
  62. const InspectorWrapper = styled('div')`
  63. margin-right: ${space(4)};
  64. `;
  65. const Wrapper = styled('div')`
  66. position: relative;
  67. /*
  68. We need some minimum vertical height so the copy button has room.
  69. But don't try to use min-height because then whitespace would be inconsistent.
  70. */
  71. padding-bottom: ${space(1.5)};
  72. `;
  73. const StyledCopyButton = styled(CopyToClipboardButton)`
  74. position: absolute;
  75. top: 0;
  76. right: ${space(0.5)};
  77. `;
  78. export type OnExpandCallback = (
  79. path: string,
  80. expandedState: Record<string, boolean>,
  81. event: MouseEvent<HTMLDivElement>
  82. ) => void;
  83. export default ObjectInspector;