fix(ai-chat) - improvements (#22193)
- 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. -->
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
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>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user