Skip to content

Commit 4c417a9

Browse files
committed
Don't allow switching target language if only JS is available
1 parent c53a4fc commit 4c417a9

File tree

5 files changed

+67
-26
lines changed

5 files changed

+67
-26
lines changed

beta/src/components/MDX/Sandpack/CustomPreset.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ export const CustomPreset = memo(function CustomPreset({
2222
showDevTools,
2323
onDevToolsLoad,
2424
devToolsLoaded,
25+
hasTSVersion,
2526
providedFiles,
2627
}: {
2728
showDevTools: boolean;
2829
devToolsLoaded: boolean;
2930
onDevToolsLoad: () => void;
31+
hasTSVersion: boolean;
3032
providedFiles: Array<string>;
3133
}) {
3234
const {lintErrors, lintExtensions} = useSandpackLint();
@@ -44,6 +46,7 @@ export const CustomPreset = memo(function CustomPreset({
4446
showDevTools={showDevTools}
4547
onDevToolsLoad={onDevToolsLoad}
4648
devToolsLoaded={devToolsLoaded}
49+
hasTSVersion={hasTSVersion}
4750
providedFiles={providedFiles}
4851
lintErrors={lintErrors}
4952
lintExtensions={lintExtensions}
@@ -56,6 +59,7 @@ const SandboxShell = memo(function SandboxShell({
5659
showDevTools,
5760
onDevToolsLoad,
5861
devToolsLoaded,
62+
hasTSVersion,
5963
providedFiles,
6064
lintErrors,
6165
lintExtensions,
@@ -64,6 +68,7 @@ const SandboxShell = memo(function SandboxShell({
6468
showDevTools: boolean;
6569
devToolsLoaded: boolean;
6670
onDevToolsLoad: () => void;
71+
hasTSVersion: boolean;
6772
providedFiles: Array<string>;
6873
lintErrors: Array<any>;
6974
lintExtensions: Array<any>;
@@ -76,7 +81,10 @@ const SandboxShell = memo(function SandboxShell({
7681
<div
7782
className="shadow-lg dark:shadow-lg-dark rounded-lg"
7883
ref={containerRef}>
79-
<NavigationBar providedFiles={providedFiles} />
84+
<NavigationBar
85+
hasTSVersion={hasTSVersion}
86+
providedFiles={providedFiles}
87+
/>
8088
<SandpackLayout
8189
className={cn(
8290
showDevTools && devToolsLoaded && 'sp-layout-devtools',

beta/src/components/MDX/Sandpack/NavigationBar.tsx

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Copyright (c) Facebook, Inc. and its affiliates.
33
*/
44

5-
import {
5+
import React, {
66
useRef,
77
useInsertionEffect,
88
useCallback,
@@ -20,7 +20,10 @@ import {
2020
import {OpenInCodeSandboxButton} from './OpenInCodeSandboxButton';
2121
import {ResetButton} from './ResetButton';
2222
import {DownloadButton} from './DownloadButton';
23-
import {SnippetTargetLanguageContext} from './SnippetLanguage';
23+
import {
24+
SnippetTargetLanguage,
25+
SnippetTargetLanguageContext,
26+
} from './SnippetLanguage';
2427
import {IconChevron} from '../../Icon/IconChevron';
2528
import {Listbox} from '@headlessui/react';
2629
import classNames from 'classnames';
@@ -42,44 +45,70 @@ const getFileName = (filePath: string): string => {
4245
return filePath.slice(lastIndexOfSlash + 1);
4346
};
4447

45-
function SnippetTargetLanguageButton(props: any) {
46-
const {children, snippetTargetLanguage} = props;
47-
const {
48-
setSnippetTargetLanguage,
49-
snippetTargetLanguage: currentSnippetTargetLanguage,
50-
} = useContext(SnippetTargetLanguageContext);
51-
52-
const isCurrent = currentSnippetTargetLanguage === snippetTargetLanguage;
48+
function SnippetTargetLanguageButton({
49+
children,
50+
active,
51+
disabled,
52+
snippetTargetLanguage,
53+
}: {
54+
children: React.ReactNode;
55+
active: boolean;
56+
disabled?: boolean | undefined;
57+
snippetTargetLanguage: SnippetTargetLanguage;
58+
}) {
59+
const {setSnippetTargetLanguage} = useContext(SnippetTargetLanguageContext);
5360

5461
return (
5562
<button
56-
aria-pressed={isCurrent ? true : undefined}
63+
aria-pressed={active}
64+
aria-disabled={disabled}
5765
className={classNames(
5866
'text-sm text-primary dark:text-primary-dark inline-flex mx-1 border-black',
59-
isCurrent && 'border-b-4'
67+
active && 'border-b-4',
68+
disabled && 'cursor-not-allowed'
6069
)}
61-
onClick={() => setSnippetTargetLanguage(snippetTargetLanguage)}
70+
onClick={() => {
71+
if (!disabled) {
72+
setSnippetTargetLanguage(snippetTargetLanguage);
73+
}
74+
}}
75+
title={disabled ? 'Language not available at the moment.' : undefined}
6276
type="button">
6377
{children}
6478
</button>
6579
);
6680
}
6781

68-
function SnippetTargetLanguageToggle() {
82+
function SnippetTargetLanguageToggle({hasTSVersion}: {hasTSVersion: boolean}) {
83+
const {snippetTargetLanguage} = useContext(SnippetTargetLanguageContext);
84+
6985
return (
7086
<div role="group" aria-label="Snippet target language">
71-
<SnippetTargetLanguageButton key="js" snippetTargetLanguage="js">
87+
<SnippetTargetLanguageButton
88+
key="js"
89+
active={!hasTSVersion || snippetTargetLanguage === 'js'}
90+
snippetTargetLanguage="js">
7291
JS
7392
</SnippetTargetLanguageButton>
7493

75-
<SnippetTargetLanguageButton key="ts" snippetTargetLanguage="ts">
94+
<SnippetTargetLanguageButton
95+
key="ts"
96+
active={hasTSVersion && snippetTargetLanguage === 'ts'}
97+
disabled={!hasTSVersion}
98+
snippetTargetLanguage="ts">
7699
TS
77100
</SnippetTargetLanguageButton>
78101
</div>
79102
);
80103
}
81104

82-
export function NavigationBar({providedFiles}: {providedFiles: Array<string>}) {
105+
export function NavigationBar({
106+
hasTSVersion,
107+
providedFiles,
108+
}: {
109+
hasTSVersion: boolean;
110+
providedFiles: Array<string>;
111+
}) {
83112
const {sandpack} = useSandpack();
84113
const containerRef = useRef<HTMLDivElement | null>(null);
85114
const tabsRef = useRef<HTMLDivElement | null>(null);
@@ -219,7 +248,7 @@ export function NavigationBar({providedFiles}: {providedFiles: Array<string>}) {
219248
<div
220249
className="px-3 flex items-center justify-end text-right"
221250
translate="yes">
222-
<SnippetTargetLanguageToggle />
251+
<SnippetTargetLanguageToggle hasTSVersion={hasTSVersion} />
223252
<DownloadButton providedFiles={providedFiles} />
224253
<ResetButton onReset={handleReset} />
225254
<OpenInCodeSandboxButton />

beta/src/components/MDX/Sandpack/SandpackRoot.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,10 @@ function SandpackRoot(props: SandpackProps) {
8080
const {snippetTargetLanguage} = React.useContext(
8181
SnippetTargetLanguageContext
8282
);
83-
const files = createFileMap(codeSnippets, snippetTargetLanguage);
83+
const {files, hasTSVersion} = createFileMap(
84+
codeSnippets,
85+
snippetTargetLanguage
86+
);
8487

8588
files['/styles.css'] = {
8689
code: [sandboxStyle, files['/styles.css']?.code ?? ''].join('\n\n'),
@@ -105,6 +108,7 @@ function SandpackRoot(props: SandpackProps) {
105108
showDevTools={showDevTools}
106109
onDevToolsLoad={() => setDevToolsLoaded(true)}
107110
devToolsLoaded={devToolsLoaded}
111+
hasTSVersion={hasTSVersion}
108112
providedFiles={Object.keys(files)}
109113
/>
110114
</SandpackProvider>

beta/src/components/MDX/Sandpack/createFileMap.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export const createFileMap = (
1313
const isTSFile = (filePath: string) => /\.(ts|tsx)$/.test(filePath);
1414
const isJSFile = (filePath: string) => /\.(js|jsx)$/.test(filePath);
1515

16-
const fileMap = codeSnippets.reduce<Record<string, SandpackFile>>(
16+
const files = codeSnippets.reduce<Record<string, SandpackFile>>(
1717
(result, codeSnippet) => {
1818
if ((codeSnippet.type as any).mdxName !== 'pre') {
1919
return result;
@@ -66,17 +66,17 @@ export const createFileMap = (
6666
{}
6767
);
6868

69-
for (const filePath in fileMap) {
69+
for (const filePath in files) {
7070
// Only remove JS files if we have a TS version available.
7171
// If no TS version is available we continue to display JS files.
7272
// Assuming that if one file is available as TS, every file is.
7373
// Assuming a JS version is available all the time.
7474
if (snippetTargetLanguage === 'ts' && isJSFile(filePath) && hasTSVersion) {
75-
delete fileMap[filePath];
75+
delete files[filePath];
7676
} else if (snippetTargetLanguage === 'js' && isTSFile(filePath)) {
77-
delete fileMap[filePath];
77+
delete files[filePath];
7878
}
7979
}
8080

81-
return fileMap;
81+
return {files, hasTSVersion};
8282
};

beta/src/components/MDX/Sandpack/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export default memo(function SandpackWrapper(props: any): any {
6262
const {snippetTargetLanguage} = useContext(SnippetTargetLanguageContext);
6363

6464
const codeSnippets = Children.toArray(props.children) as React.ReactElement[];
65-
const files = createFileMap(codeSnippets, snippetTargetLanguage);
65+
const {files} = createFileMap(codeSnippets, snippetTargetLanguage);
6666

6767
// To set the active file in the fallback we have to find the active file first.
6868
// If there are no active files we fallback to App.js as default.

0 commit comments

Comments
 (0)