1- import { Pre } from "codehike/code " ;
2- import { useMemo } from "react" ;
3- import { CopyButton } from "./copy-button .js" ;
1+ import { LazyMotion , domMax } from "motion/react " ;
2+ import React from "react" ;
3+ import { SpeakeasyCodeSamplesCore } from "../core .js" ;
44import {
55 GetCodeSamplesRequest ,
66 MethodPaths ,
77} from "../models/operations/getcodesamples.js" ;
8+ import { OperationId } from "../types/custom.js" ;
9+ import { useCodeSampleState } from "./code-sample.state.js" ;
810import classes from "./code-sample.styles.js" ;
9- import {
10- useHighlightedCodeSamples ,
11- useSafeSpeakeasyCodeSamplesContext ,
12- useSelectedSnippet ,
13- } from "./hooks.js" ;
11+ import { CodeViewer , ErrorDisplay } from "./code-viewer.js" ;
12+ import codehikeTheme from "./codehike/theme.js" ;
13+ import { CopyButton } from "./copy-button.js" ;
1414import { LanguageSelector } from "./language-selector.js" ;
15- import { lineNumbers } from "./codehike/line-numbers.js" ;
16- import {
17- LanguageSelectorSkeleton ,
18- LoadingSkeleton ,
19- TitleSkeleton ,
20- } from "./skeleton.js" ;
21- import { getCssVars , githubColorVars , useSystemColorMode } from "./styles.js" ;
22- import { CodeSampleFilenameTitle , CodeSampleTitleComponent } from "./titles.js" ;
23- import { tokenTransitions } from "./codehike/token-transitions.js" ;
24- import { SpeakeasyCodeSamplesCore } from "../core.js" ;
25- import { OperationId } from "../types/custom.js" ;
26- import { LazyMotion , domAnimation } from "motion/react" ;
15+ import { LanguageSelectorSkeleton , LoadingSkeleton } from "./skeleton.js" ;
16+ import { getCssVars , useSystemColorMode } from "./styles.js" ;
17+ import { type CodeSampleTitleComponent , CodeSampleTitle } from "./titles.js" ;
2718
2819export type CodeSamplesViewerProps = {
2920 /** Whether the code snippet should be copyable. */
@@ -46,7 +37,7 @@ export type CodeSamplesViewerProps = {
4637 * @see CodeSampleFilenameTitle
4738 * @default CodeSampleMethodTitle
4839 */
49- title ?: CodeSampleTitleComponent ;
40+ title ?: CodeSampleTitleComponent | React . ReactNode | string ;
5041 /** The operation to get a code sample for. Can be queried by either
5142 * operationId or method+path.
5243 */
@@ -67,45 +58,38 @@ export function CodeSamplesViewer({
6758 operation,
6859 style,
6960 copyable,
70- defaultLang,
7161 client : clientProp ,
7262} : CodeSamplesViewerProps ) {
73- const TitleComponent = title ;
74-
75- const systemColorMode = useSystemColorMode ( ) ;
76-
77- const codeTheme = useMemo ( ( ) => {
78- if ( theme === "system" ) return githubColorVars [ systemColorMode ] ;
79- return githubColorVars [ theme ] ;
80- } , [ theme , systemColorMode ] ) ;
81-
82- const request : GetCodeSamplesRequest = useMemo ( ( ) => {
63+ const request : GetCodeSamplesRequest = React . useMemo ( ( ) => {
8364 if ( typeof operation === "string" ) return { operationIds : [ operation ] } ;
8465 return { methoPaths : [ operation ] } ;
8566 } , [ operation ] ) ;
8667
87- const client = useSafeSpeakeasyCodeSamplesContext ( clientProp ) ;
88- const { status, data, error } = useHighlightedCodeSamples ( client , request ) ;
68+ const { state, setSelectedLanguage } = useCodeSampleState ( {
69+ client : clientProp ,
70+ requestParams : request ,
71+ } ) ;
8972
90- const { selectedSnippet, selectedLang, setSelectedLang } = useSelectedSnippet (
91- data ,
92- defaultLang ,
93- ) ;
73+ const systemColorMode = useSystemColorMode ( ) ;
74+ const codeTheme = React . useMemo ( ( ) => {
75+ if ( theme === "system" ) return codehikeTheme [ systemColorMode ] ;
76+ return codehikeTheme [ theme ] ;
77+ } , [ theme , systemColorMode ] ) ;
9478
95- const longestCodeHeight = useMemo ( ( ) => {
79+ const longestCodeHeight = React . useMemo ( ( ) => {
9680 const largestLines = Math . max (
97- ...Object . values ( data ?? [ ] )
81+ ...Object . values ( state . snippets ?? [ ] )
9882 . filter ( ( snippet ) => snippet . code !== undefined )
9983 . map ( ( code ) => code . code ! . split ( "\n" ) . length ) ,
10084 ) ;
10185
10286 const lineHeight = 23 ;
10387 const padding = 12 ;
10488 return largestLines * lineHeight + padding * 2 ;
105- } , [ data ] ) ;
89+ } , [ state . snippets ] ) ;
10690
10791 return (
108- < LazyMotion strict features = { domAnimation } >
92+ < LazyMotion strict features = { domMax } >
10993 < div
11094 style = { {
11195 ...codeTheme ,
@@ -117,39 +101,37 @@ export function CodeSamplesViewer({
117101 className = { `${ classes . root } ${ className ?? "" } ` }
118102 >
119103 < div className = { classes . heading } >
120- { status === "loading" && error === undefined ? (
121- < TitleSkeleton />
122- ) : TitleComponent && selectedSnippet ? (
123- < TitleComponent { ...selectedSnippet ! . raw } />
124- ) : (
125- < CodeSampleFilenameTitle { ...selectedSnippet ! . raw } />
104+ < CodeSampleTitle
105+ component = { title }
106+ status = { state . status }
107+ data = { state . selectedSnippet ?. raw }
108+ />
109+ < >
110+ { state . status === "loading" && < LanguageSelectorSkeleton /> }
111+ { state . status === "success" && (
112+ < LanguageSelector
113+ value = { state . selectedSnippet ?. lang }
114+ onChange = { setSelectedLanguage }
115+ snippets = { state . snippets ?? [ ] }
116+ className = { classes . selector }
117+ />
118+ ) }
119+ </ >
120+ </ div >
121+ < div className = { classes . codeContainer } >
122+ { state . status === "success" && copyable && (
123+ < CopyButton code = { state . selectedSnippet . code } />
126124 ) }
127- { status === "loading" && error === undefined ? (
128- < LanguageSelectorSkeleton />
129- ) : (
130- < LanguageSelector
131- value = { selectedLang }
132- onChange = { setSelectedLang }
133- snippets = { data ?? [ ] }
134- className = { classes . selector }
125+ { state . status === "loading" && < LoadingSkeleton /> }
126+ { state . status === "error" && < ErrorDisplay error = { state . error } /> }
127+ { state . status === "success" && (
128+ < CodeViewer
129+ status = { state . status }
130+ code = { state . selectedSnippet }
131+ longestCodeHeight = { longestCodeHeight }
135132 />
136133 ) }
137134 </ div >
138- < div className = { classes . codeContainer } >
139- { status === "loading" ? (
140- < LoadingSkeleton />
141- ) : selectedSnippet ? (
142- < >
143- { copyable && < CopyButton code = { selectedSnippet . code } /> }
144- < Pre
145- className = { classes . pre }
146- style = { { height : longestCodeHeight } }
147- handlers = { [ lineNumbers , tokenTransitions ] }
148- code = { selectedSnippet }
149- />
150- </ >
151- ) : null }
152- </ div >
153135 </ div >
154136 </ LazyMotion >
155137 ) ;
0 commit comments