-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Expand file tree
/
Copy pathCustomPreset.tsx
More file actions
131 lines (126 loc) · 3.9 KB
/
CustomPreset.tsx
File metadata and controls
131 lines (126 loc) · 3.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*/
import {memo, useRef, useState} from 'react';
import {flushSync} from 'react-dom';
import {
useSandpack,
useActiveCode,
SandpackCodeEditor,
SandpackLayout,
} from '@codesandbox/sandpack-react/unstyled';
import cn from 'classnames';
import {IconChevron} from 'components/Icon/IconChevron';
import {NavigationBar} from './NavigationBar';
import {Preview} from './Preview';
import {useSandpackLint} from './useSandpackLint';
export const CustomPreset = memo(function CustomPreset({
providedFiles,
}: {
providedFiles: Array<string>;
}) {
const {lintErrors, lintExtensions} = useSandpackLint();
const {sandpack} = useSandpack();
const {code} = useActiveCode();
const {activeFile} = sandpack;
const lineCountRef = useRef<{[key: string]: number}>({});
if (!lineCountRef.current[activeFile]) {
// eslint-disable-next-line react-compiler/react-compiler
lineCountRef.current[activeFile] = code.split('\n').length;
}
const lineCount = lineCountRef.current[activeFile];
const isExpandable = lineCount > 16;
return (
<SandboxShell
providedFiles={providedFiles}
lintErrors={lintErrors}
lintExtensions={lintExtensions}
isExpandable={isExpandable}
/>
);
});
const SandboxShell = memo(function SandboxShell({
providedFiles,
lintErrors,
lintExtensions,
isExpandable,
}: {
providedFiles: Array<string>;
lintErrors: Array<any>;
lintExtensions: Array<any>;
isExpandable: boolean;
}) {
const containerRef = useRef<HTMLDivElement>(null);
const [isExpanded, setIsExpanded] = useState(false);
return (
<>
<div
className="shadow-lg dark:shadow-lg-dark rounded-lg"
ref={containerRef}
style={{
contain: 'content',
}}>
<NavigationBar providedFiles={providedFiles} />
<SandpackLayout
className={cn(
!(isExpandable || isExpanded) && 'rounded-b-lg overflow-hidden',
isExpanded && 'sp-layout-expanded'
)}>
<Editor lintExtensions={lintExtensions} />
<Preview
className="order-last xl:order-2"
isExpanded={isExpanded}
lintErrors={lintErrors}
/>
{(isExpandable || isExpanded) && (
<button
translate="yes"
className="sandpack-expand flex text-base justify-between dark:border-card-dark bg-wash dark:bg-card-dark items-center z-10 p-1 w-full order-2 xl:order-last border-b-1 relative top-0"
onClick={() => {
const nextIsExpanded = !isExpanded;
flushSync(() => {
setIsExpanded(nextIsExpanded);
});
if (!nextIsExpanded && containerRef.current !== null) {
// @ts-ignore
if (containerRef.current.scrollIntoViewIfNeeded) {
// @ts-ignore
containerRef.current.scrollIntoViewIfNeeded();
} else {
containerRef.current.scrollIntoView({
block: 'nearest',
inline: 'nearest',
});
}
}
}}>
<span className="flex p-2 focus:outline-none text-primary dark:text-primary-dark leading-[20px]">
<IconChevron
className="inline me-1.5 text-xl"
displayDirection={isExpanded ? 'up' : 'down'}
/>
{isExpanded ? 'Show less' : 'Show more'}
</span>
</button>
)}
</SandpackLayout>
</div>
</>
);
});
const Editor = memo(function Editor({
lintExtensions,
}: {
lintExtensions: Array<any>;
}) {
return (
<SandpackCodeEditor
showLineNumbers
showInlineErrors
showTabs={false}
showRunButton={false}
extensions={lintExtensions}
wrapContent={true}
/>
);
});