/**
* Teleport
* Copyright (C) 2023 Gravitational, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
import { useRef } from 'react';
import styled from 'styled-components';
import { Box, ButtonSecondary, Flex } from 'design';
import { Check, Copy, Download } from 'design/Icon';
import { copyToClipboard } from 'design/utils/copyToClipboard';
import selectElementContent from 'design/utils/selectElementContent';
import { saveOnDisk } from 'shared/utils/saveOnDisk';
const ONE_SECOND_IN_MS = 1000;
export function TextSelectCopyMulti({
lines,
bash = true,
maxHeight = 'none',
saveContent = { save: false, filename: '' },
}: Props) {
const refs = useRef([]);
function onCopyClick(index) {
copyToClipboard(lines[index].text).then(() => {
const targetEl =
refs.current[index].getElementsByClassName('icon-container')[0];
targetEl.classList.toggle('copied');
setTimeout(() => {
targetEl.classList.toggle('copied');
}, ONE_SECOND_IN_MS);
});
const targetEl =
refs.current[index].getElementsByClassName('text-to-copy')[0];
selectElementContent(targetEl as HTMLElement);
}
return (
{lines.map((line, index) => {
const isLastText = index === lines.length - 1;
return (
(refs.current[index] = s)}
>
{line.comment && {line.comment}}
{bash && {`$`}}
onCopyClick(index)}>
{saveContent.save && (
saveOnDisk(
line.text,
saveContent.filename,
'plain/text'
)
}
>
)}
);
})}
);
}
const Icon = styled.div`
display: flex;
.icon-check {
display: none;
}
.icon-copy {
display: inline-flex;
}
&.copied {
.icon-check {
display: inline-flex;
}
.icon-copy {
display: none;
}
}
`;
const Comment = styled.div`
color: rgb(117 113 94 / 80%);
`;
const StyledButtonSecondary = styled(ButtonSecondary)`
height: 28px;
width: 28px;
border-radius: 20px;
min-height: auto;
padding: 0;
margin-top: -4px;
background: rgba(255, 255, 255, 0.07);
&:hover,
&:focus {
background: rgba(255, 255, 255, 0.13);
}
`;
const Lines = styled(Box)`
white-space: pre;
word-break: break-all;
font-size: 12px;
font-family: ${({ theme }) => theme.fonts.mono};
overflow: auto;
line-height: 20px;
color: ${props => props.theme.colors.light};
`;
type Line = {
// text is the text to copy.
text: string;
// comment is an optional grayed out text that
// will render above the text to copy.
comment?: string;
};
export type Props = {
lines: Line[];
// bash is a flag that when true will append a
// `$` sign in front of the lines text.
bash?: boolean;
saveContent?: saveContent;
maxHeight?: string;
};
type saveContent = {
save: boolean;
filename: string;
};