import type { CSSProperties, ReactNode } from 'react'
import type { CodeBlockTokenType } from './codeBlock.token'
import Block from '../Primitives/Block/Block'
import { FOUNDATION_THEME } from '../../tokens'
import { DiffLineType, type DiffLine } from './types'
import type { SyntaxToken } from './utils'
export type LineCounter = { left: number; right: number }
export const EmptyGutterCell: React.FC<{
width: string | number | undefined
}> = ({ width }) => (
)
type LineNumberGutterProps = {
lineIndex: number
width: string | number | undefined
color: string | undefined
style?: React.CSSProperties
}
export const LineNumberGutter: React.FC = ({
lineIndex,
width,
color,
style,
}) => (
{lineIndex + 1}
)
export type TokenizedCodeLineProps = {
tokens: SyntaxToken[]
getTokenColor: (type: string) => string
paddingTop?: string | number
paddingBottom?: string | number
paddingLeft?: string | number
paddingRight?: string | number
whiteSpace?: 'pre-wrap' | 'pre'
}
export const TokenizedCodeLine: React.FC = ({
tokens,
getTokenColor,
paddingTop,
paddingBottom,
paddingLeft,
paddingRight,
whiteSpace = 'pre-wrap',
}) => (
token.value).join('')}
style={{
flex: 1,
whiteSpace,
wordBreak: whiteSpace === 'pre' ? 'normal' : 'break-word',
paddingTop:
typeof paddingTop === 'number' ? `${paddingTop}px` : paddingTop,
paddingBottom:
typeof paddingBottom === 'number'
? `${paddingBottom}px`
: paddingBottom,
paddingLeft:
typeof paddingLeft === 'number'
? `${paddingLeft}px`
: paddingLeft,
paddingRight:
typeof paddingRight === 'number'
? `${paddingRight}px`
: paddingRight,
lineHeight: '18px',
}}
>
{tokens.map((token, tokenIndex) => (
{token.value}
))}
)
export type CodeLineWrapperProps = {
children: ReactNode
style?: React.CSSProperties
lineIndex?: number
}
export const CodeLineWrapper: React.FC = ({
children,
style,
lineIndex,
}) => (
{children}
)
export type PreElementProps = {
children: ReactNode
fontFamily: string | undefined
fontSize: string | number | undefined
lineHeight: string | number | undefined
id?: string
}
export const PreElement: React.FC = ({
children,
fontFamily,
fontSize,
lineHeight,
id,
}) => (
{children}
)
export type DiffRowRenderContext = {
shouldShowLineNumbers: boolean
tokens: CodeBlockTokenType
tokenizeLine: (line: string) => SyntaxToken[]
getTokenColor: (type: string) => string
getDiffGutterStyle: (lineType?: DiffLineType) => CSSProperties
getDiffLineBackground: (lineType?: DiffLineType) => CSSProperties
}
/**
* One full-width row: left pane + right pane in a single flex row so both
* sides always share the same row height.
*/
export const renderDiffUnifiedRowPair = (
leftLine: DiffLine | undefined,
rightLine: DiffLine | undefined,
rowKey: string,
counters: LineCounter,
ctx: DiffRowRenderContext,
tokens: CodeBlockTokenType
): ReactNode => {
const showLeft = Boolean(leftLine)
const showRight = Boolean(rightLine)
const leftContent = leftLine?.content ?? ''
const rightContent = rightLine?.content ?? ''
const leftBgType = leftLine?.type
const rightBgType = rightLine?.type
let leftGutterIndex = 0
if (showLeft) {
leftGutterIndex = counters.left
counters.left += 1
}
let rightGutterIndex = 0
if (showRight) {
rightGutterIndex = counters.right
counters.right += 1
}
const leftColumnStyle: CSSProperties = {
backgroundColor: tokens.backgroundColor,
...ctx.getDiffLineBackground(leftBgType),
}
const rightColumnStyle: CSSProperties = {
backgroundColor: tokens.backgroundColor,
...ctx.getDiffLineBackground(rightBgType),
}
return (
{ctx.shouldShowLineNumbers &&
(showLeft ? (
) : (
))}
{ctx.shouldShowLineNumbers &&
(showRight ? (
) : (
))}
)
}