import React, {useEffect, useState} from "react";
import {Theme} from "@code-hike/lighter";
import type {CodeThemeBlockProps} from "../CodeTheme";
import {
Code,
annotations,
} from "../Code"
import {
withCodeTabs
} from "../CodeTabs";
import {useCodeTheme} from "../CodeTheme";
import {useCoder} from "../CoderProvider";
import {CodeSampleAnalytics} from "./CodeSampleAnalytics";
export interface CodeSampleProps {
name: string;
description: string;
codeblocks?: CodeThemeBlockProps[];
theme?: Theme
size?: "full"
lineNumbers?: boolean
descriptionHead?: string
descriptionContent?: string | React.ReactNode
descriptionIcon?: string
markdownFormat?: boolean
kind?: "secondary"
controlByMeta?: boolean // TODO: BETTER IN THE FUTURE
/** How the language switcher renders: a row of tabs (default) or a
* dropdown to pick the language. */
languageSwitcher?: "tabs" | "dropdown"
/** Render each language as its programming-language icon (from xyd's
* built-in code-language icon set, drawn via the xyd `Icon` component)
* instead of the raw name. Languages without an icon keep their name. */
languageIcons?: boolean
/** Advanced override: fully control the label for a language tab/option.
* Takes precedence over `languageIcons`. Falls back to the name otherwise. */
renderLanguage?: (lang: string, meta?: string) => React.ReactNode
/** Extra action(s) rendered in the code toolbar, right after the copy button
* (e.g. Atlas's "run request" play icon). */
codeActions?: React.ReactNode
/** Controlled active language (a tab value = `meta || lang`). When set with
* `onLangChange`, the language switcher is CONTROLLED and shared — every
* CodeSample fed the same value shows the same language, and switching one
* updates them all (Atlas wires this to its page-shared SDK language). */
activeLang?: string
onLangChange?: (lang: string) => void
}
export const CodeContext = React.createContext<{
size?: "full"
lineNumbers?: boolean
descriptionHead?: string
descriptionContent?: string | React.ReactNode
descriptionIcon?: string
markdownFormat?: boolean
languageSwitcher?: "tabs" | "dropdown"
languageIcons?: boolean
renderLanguage?: (lang: string, meta?: string) => React.ReactNode
codeActions?: React.ReactNode
activeLang?: string
onLangChange?: (lang: string) => void
}>({})
export function CodeSample(props: CodeSampleProps) {
return
<$ThemedCodeSample {...props} />
}
function $ThemedCodeSample(props: CodeSampleProps) {
const {highlighted} = useCodeTheme()
const coder = useCoder()
if (props.kind === "secondary") {
return
}
let size: "full" | undefined = undefined
if (typeof props.size === "string") {
size = props.size
} else if (typeof coder.scroll === "boolean" && !coder.scroll) {
size = "full"
}
const lineNumbers = props.lineNumbers ?? coder.lines
return
<$CodeSampleTabs
description={props.description}
highlighted={highlighted}
controlByMeta={props.controlByMeta}
/>
}
const $CodeSampleTabs = withCodeTabs((props) => {
const {lineNumbers, size, descriptionHead, descriptionContent, descriptionIcon} = React.useContext(CodeContext)
const handlers = [
annotations.mark,
annotations.bg,
annotations.diff
]
if (lineNumbers) {
handlers.push(annotations.lineNumbers)
}
return
})