b625bd1995
- remove flickering at assistant message streamed end - add copy code - leave chat history when navigating to settings <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/22193?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
81 lines
2.0 KiB
TypeScript
81 lines
2.0 KiB
TypeScript
import { styled } from '@linaria/react';
|
|
import { useLingui } from '@lingui/react/macro';
|
|
import { isNumber, isString } from '@sniptt/guards';
|
|
import { Children, isValidElement } from 'react';
|
|
import { IconCopy } from 'twenty-ui/icon';
|
|
import { LightIconButton } from 'twenty-ui/input';
|
|
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
|
import { useCopyToClipboard } from '~/hooks/useCopyToClipboard';
|
|
|
|
const StyledContainer = styled.div`
|
|
position: relative;
|
|
|
|
.markdown-block-code {
|
|
margin: 0;
|
|
}
|
|
`;
|
|
|
|
const StyledCopyButtonContainer = styled.div`
|
|
align-items: center;
|
|
border-radius: ${themeCssVariables.border.radius.sm};
|
|
display: flex;
|
|
opacity: 0;
|
|
position: absolute;
|
|
right: ${themeCssVariables.spacing[2]};
|
|
top: ${themeCssVariables.spacing[2]};
|
|
transition: opacity calc(${themeCssVariables.animation.duration.fast} * 1s)
|
|
ease;
|
|
|
|
${StyledContainer}:hover & {
|
|
opacity: 1;
|
|
}
|
|
|
|
&:hover {
|
|
background: ${themeCssVariables.background.primary};
|
|
}
|
|
`;
|
|
|
|
const extractTextFromNode = (node: React.ReactNode): string => {
|
|
if (isString(node) || isNumber(node)) {
|
|
return node.toString();
|
|
}
|
|
|
|
if (Array.isArray(node)) {
|
|
return node.map(extractTextFromNode).join('');
|
|
}
|
|
|
|
if (isValidElement<{ children?: React.ReactNode }>(node)) {
|
|
return Children.toArray(node.props.children)
|
|
.map(extractTextFromNode)
|
|
.join('');
|
|
}
|
|
|
|
return '';
|
|
};
|
|
|
|
export const MarkdownCodeBlock = ({
|
|
children,
|
|
}: {
|
|
children: React.ReactNode;
|
|
}) => {
|
|
const { t } = useLingui();
|
|
const { copyToClipboard } = useCopyToClipboard();
|
|
|
|
const codeText = extractTextFromNode(children);
|
|
|
|
return (
|
|
<StyledContainer className="markdown-code-outer-container">
|
|
<StyledCopyButtonContainer>
|
|
<LightIconButton
|
|
Icon={IconCopy}
|
|
onClick={() => copyToClipboard(codeText, t`Code copied to clipboard`)}
|
|
title={t`Copy code`}
|
|
size="small"
|
|
accent="tertiary"
|
|
/>
|
|
</StyledCopyButtonContainer>
|
|
<pre className="markdown-block-code">{children}</pre>
|
|
</StyledContainer>
|
|
);
|
|
};
|