mirror of
https://github.com/enricoros/big-AGI.git
synced 2026-05-11 06:00:15 -07:00
Update overlay buttons
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { IconButton, Tooltip } from '@mui/joy';
|
||||
import { Tooltip } from '@mui/joy';
|
||||
|
||||
import { Brand } from '~/common/app.config';
|
||||
import { CodePenIcon } from '~/common/components/icons/3rdparty/CodePenIcon';
|
||||
import { prettyTimestampForFilenames } from '~/common/util/timeUtils';
|
||||
|
||||
import { OverlayButton } from './RenderCode';
|
||||
|
||||
|
||||
// CodePen is a web-based HTML, CSS, and JavaScript code editor
|
||||
const _languages = ['html', 'css', 'javascript', 'json', 'typescript'];
|
||||
@@ -48,9 +50,9 @@ const handleOpenInCodePen = (code: string, language: string) => {
|
||||
export function ButtonCodePen(props: { code: string, language: string }): React.JSX.Element {
|
||||
return (
|
||||
<Tooltip title='Open in CodePen' variant='solid'>
|
||||
<IconButton variant='outlined' color='neutral' onClick={() => handleOpenInCodePen(props.code, props.language)}>
|
||||
<OverlayButton variant='outlined' onClick={() => handleOpenInCodePen(props.code, props.language)}>
|
||||
<CodePenIcon />
|
||||
</IconButton>
|
||||
</OverlayButton>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { IconButton, Tooltip } from '@mui/joy';
|
||||
import { Tooltip } from '@mui/joy';
|
||||
|
||||
import { OverlayButton } from './RenderCode';
|
||||
|
||||
|
||||
// JSFiidle is a web-based HTML, CSS, and JavaScript code editor
|
||||
@@ -49,9 +51,9 @@ const handleOpenInJsFiddle = (code: string, language: string) => {
|
||||
export function ButtonJsFiddle(props: { code: string, language: string }): React.JSX.Element {
|
||||
return (
|
||||
<Tooltip title='Open in JSFiddle' variant='solid'>
|
||||
<IconButton onClick={() => handleOpenInJsFiddle(props.code, props.language)}>
|
||||
<OverlayButton variant='outlined' onClick={() => handleOpenInJsFiddle(props.code, props.language)}>
|
||||
JS
|
||||
</IconButton>
|
||||
</OverlayButton>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { IconButton, Tooltip } from '@mui/joy';
|
||||
import { Tooltip } from '@mui/joy';
|
||||
|
||||
import { Brand } from '~/common/app.config';
|
||||
import { StackBlitzIcon } from '~/common/components/icons/3rdparty/StackBlitzIcon';
|
||||
import { prettyTimestampForFilenames } from '~/common/util/timeUtils';
|
||||
|
||||
import { OverlayButton } from './RenderCode';
|
||||
|
||||
|
||||
const _languages = [
|
||||
'typescript',
|
||||
@@ -77,9 +79,9 @@ const handleOpenInStackBlitz = (code: string, language: string, title?: string)
|
||||
export function ButtonStackBlitz(props: { code: string, language: string, title?: string }): React.JSX.Element {
|
||||
return (
|
||||
<Tooltip title='Open in StackBlitz' variant='solid'>
|
||||
<IconButton variant='outlined' color='neutral' onClick={() => handleOpenInStackBlitz(props.code, props.language, props.title)}>
|
||||
<OverlayButton variant='outlined' onClick={() => handleOpenInStackBlitz(props.code, props.language, props.title)}>
|
||||
<StackBlitzIcon />
|
||||
</IconButton>
|
||||
</OverlayButton>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import type { SxProps } from '@mui/joy/styles/types';
|
||||
import { Box, ButtonGroup, IconButton, Sheet, Tooltip, Typography } from '@mui/joy';
|
||||
import { Box, ButtonGroup, IconButton, Sheet, styled, Tooltip, Typography } from '@mui/joy';
|
||||
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
|
||||
import FitScreenIcon from '@mui/icons-material/FitScreen';
|
||||
import HtmlIcon from '@mui/icons-material/Html';
|
||||
@@ -19,11 +19,13 @@ import { ButtonStackBlitz, isStackBlitzSupported } from './ButtonStackBlitz';
|
||||
import { heuristicIsHtml, IFrameComponent } from '../RenderHtml';
|
||||
import { patchSvgString, RenderCodeMermaid } from './RenderCodeMermaid';
|
||||
|
||||
|
||||
export function getPlantUmlServerUrl(): string {
|
||||
// set at nextjs build time
|
||||
return process.env.NEXT_PUBLIC_PLANTUML_SERVER_URL || 'https://www.plantuml.com/plantuml/svg/';
|
||||
}
|
||||
|
||||
|
||||
async function fetchPlantUmlSvg(plantUmlCode: string): Promise<string | null> {
|
||||
// Get the PlantUML server from inline env var
|
||||
let plantUmlServerUrl = getPlantUmlServerUrl();
|
||||
@@ -64,13 +66,19 @@ async function fetchPlantUmlSvg(plantUmlCode: string): Promise<string | null> {
|
||||
}
|
||||
|
||||
|
||||
export const OverlayButton = styled(IconButton)(({ theme, variant }) => ({
|
||||
backgroundColor: variant === 'outlined' ? theme.palette.background.surface : undefined,
|
||||
'--Icon-fontSize': theme.fontSize.lg,
|
||||
})) as typeof IconButton;
|
||||
|
||||
|
||||
export const overlayButtonsSx: SxProps = {
|
||||
position: 'absolute', top: 0, right: 0, zIndex: 2, /* top of message and its chips */
|
||||
display: 'flex', flexDirection: 'row', gap: 1,
|
||||
opacity: 0, transition: 'opacity 0.2s cubic-bezier(.17,.84,.44,1)',
|
||||
// buttongroup: background
|
||||
'& > div > button': {
|
||||
backgroundColor: 'background.surface',
|
||||
// backgroundColor: 'background.surface',
|
||||
// backdropFilter: 'blur(12px)',
|
||||
},
|
||||
};
|
||||
@@ -206,53 +214,63 @@ function RenderCodeImpl(props: RenderCodeImplProps) {
|
||||
|
||||
{/* Buttons */}
|
||||
<Box className='overlay-buttons' sx={{ ...overlayButtonsSx, p: 0.5 }}>
|
||||
{/* Show HTML */}
|
||||
{isHTML && (
|
||||
<Tooltip title={optimizeLightweight ? null : renderHTML ? 'Hide' : 'Show Web Page'}>
|
||||
<IconButton variant={renderHTML ? 'solid' : 'soft'} color='danger' onClick={() => setShowHTML(!showHTML)}>
|
||||
<HtmlIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
{isMermaid && (
|
||||
<Tooltip title={optimizeLightweight ? null : renderMermaid ? 'Show Code' : 'Render Mermaid'}>
|
||||
<IconButton variant={renderMermaid ? 'solid' : 'soft'} onClick={() => setShowMermaid(!showMermaid)}>
|
||||
<SchemaIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
{isPlantUML && (
|
||||
<Tooltip title={optimizeLightweight ? null : renderPlantUML ? 'Show Code' : 'Render PlantUML'}>
|
||||
<IconButton variant={renderPlantUML ? 'solid' : 'soft'} onClick={() => setShowPlantUML(!showPlantUML)}>
|
||||
<SchemaIcon />
|
||||
</IconButton>
|
||||
<OverlayButton variant={renderHTML ? 'solid' : 'outlined'} color='danger' onClick={() => setShowHTML(!showHTML)}>
|
||||
<HtmlIcon sx={{ fontSize: 'xl2' }} />
|
||||
</OverlayButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{/* Show SVG */}
|
||||
{isSVG && (
|
||||
<Tooltip title={optimizeLightweight ? null : renderSVG ? 'Show Code' : 'Render SVG'}>
|
||||
<IconButton variant={renderSVG ? 'solid' : 'soft'} onClick={() => setShowSVG(!showSVG)}>
|
||||
<OverlayButton variant={renderSVG ? 'solid' : 'outlined'} onClick={() => setShowSVG(!showSVG)}>
|
||||
<ShapeLineOutlinedIcon />
|
||||
</IconButton>
|
||||
</OverlayButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
{((isMermaid && showMermaid) || (isPlantUML && showPlantUML && !plantUmlError) || (isSVG && showSVG && canScaleSVG)) && (
|
||||
<Tooltip title={optimizeLightweight ? null : fitScreen ? 'Original Size' : 'Fit Screen'}>
|
||||
<IconButton variant={fitScreen ? 'solid' : 'soft'} onClick={() => setFitScreen(on => !on)}>
|
||||
<FitScreenIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
|
||||
{/* Show Diagrams */}
|
||||
{(isMermaid || isPlantUML) && (
|
||||
<ButtonGroup aria-label='Diagram'>
|
||||
{/* Toggle rendering */}
|
||||
<Tooltip title={optimizeLightweight ? null : (renderMermaid || renderPlantUML) ? 'Show Code' : 'Render Mermaid'}>
|
||||
<OverlayButton variant={(renderMermaid || renderPlantUML) ? 'solid' : 'outlined'} onClick={() => {
|
||||
if (isMermaid) setShowMermaid(on => !on);
|
||||
if (isPlantUML) setShowPlantUML(on => !on);
|
||||
}}>
|
||||
<SchemaIcon />
|
||||
</OverlayButton>
|
||||
</Tooltip>
|
||||
|
||||
{/* Fit-To-Screen */}
|
||||
{((isMermaid && showMermaid) || (isPlantUML && showPlantUML && !plantUmlError) || (isSVG && showSVG && canScaleSVG)) && (
|
||||
<Tooltip title={optimizeLightweight ? null : fitScreen ? 'Original Size' : 'Fit Screen'}>
|
||||
<OverlayButton variant={fitScreen ? 'solid' : 'outlined'} onClick={() => setFitScreen(on => !on)}>
|
||||
<FitScreenIcon />
|
||||
</OverlayButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
</ButtonGroup>
|
||||
)}
|
||||
|
||||
{/* New Code Window Buttons */}
|
||||
{(canJSFiddle || canCodePen || canStackBlitz) && (
|
||||
<ButtonGroup aria-label='Open code in external editors' sx={{ cornerRadius: 'md' }}>
|
||||
<ButtonGroup aria-label='Open code in external editors'>
|
||||
{canJSFiddle && <ButtonJsFiddle code={blockCode} language={inferredCodeLanguage!} />}
|
||||
{canCodePen && <ButtonCodePen code={blockCode} language={inferredCodeLanguage!} />}
|
||||
{canStackBlitz && <ButtonStackBlitz code={blockCode} title={blockTitle} language={inferredCodeLanguage!} />}
|
||||
</ButtonGroup>
|
||||
)}
|
||||
|
||||
{/* Copy */}
|
||||
{props.noCopyButton !== true && (
|
||||
<Tooltip title={optimizeLightweight ? null : 'Copy Code'}>
|
||||
<IconButton variant='soft' onClick={handleCopyToClipboard}>
|
||||
<OverlayButton variant='outlined' onClick={handleCopyToClipboard}>
|
||||
<ContentCopyIcon />
|
||||
</IconButton>
|
||||
</OverlayButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user