Browse Source
* added code for sandpack console
* add log
* added console for older bundle
* Revert "[beta] Sandpack - new bundler (#4458)"
This reverts commit 3ab1245314
.
* adds proper console and removes new bundle
* modify styles
* remove unwanted code
* nit
* fix types (#4677)
* update console
* little nits
* remove unwanted code changes
* update bundler URL
* use `message.firstLoad` for clearing console
* use `refresh` event to clear logs as well (used when going away and coming back to sandpack)
* remove padding for code blocks inside console
* small UI revamps
* change p to div since the sandpack comes inside the p, add try catch and a try catch for the catch again
* tweaks
* Fixes
* Reset unrelated changes
* tweaks
* fix
* fixes
* oops
* Fix
* fix
Co-authored-by: Danilo Woznica <danilowoz@gmail.com>
Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
main
Strek
3 years ago
committed by
GitHub
3 changed files with 163 additions and 0 deletions
@ -0,0 +1,154 @@ |
|||
/* |
|||
* Copyright (c) Facebook, Inc. and its affiliates. |
|||
*/ |
|||
import cn from 'classnames'; |
|||
import * as React from 'react'; |
|||
import {IconChevron} from 'components/Icon/IconChevron'; |
|||
|
|||
import {SandpackCodeViewer, useSandpack} from '@codesandbox/sandpack-react'; |
|||
import type {SandpackMessageConsoleMethods} from '@codesandbox/sandpack-client'; |
|||
|
|||
const getType = ( |
|||
message: SandpackMessageConsoleMethods |
|||
): 'info' | 'warning' | 'error' => { |
|||
if (message === 'log' || message === 'info') { |
|||
return 'info'; |
|||
} |
|||
|
|||
if (message === 'warn') { |
|||
return 'warning'; |
|||
} |
|||
|
|||
return 'error'; |
|||
}; |
|||
|
|||
type ConsoleData = Array<{ |
|||
data: Array<string | Record<string, string>>; |
|||
id: string; |
|||
method: SandpackMessageConsoleMethods; |
|||
}>; |
|||
|
|||
const MAX_MESSAGE_COUNT = 100; |
|||
|
|||
export const SandpackConsole = () => { |
|||
const {listen} = useSandpack(); |
|||
const [logs, setLogs] = React.useState<ConsoleData>([]); |
|||
const wrapperRef = React.useRef<HTMLDivElement>(null); |
|||
|
|||
React.useEffect(() => { |
|||
const unsubscribe = listen((message) => { |
|||
if ( |
|||
(message.type === 'start' && message.firstLoad) || |
|||
message.type === 'refresh' |
|||
) { |
|||
setLogs([]); |
|||
} |
|||
if (message.type === 'console' && message.codesandbox) { |
|||
setLogs((prev) => { |
|||
const messages = [...prev, ...message.log]; |
|||
messages.slice(Math.max(0, messages.length - MAX_MESSAGE_COUNT)); |
|||
|
|||
return messages.filter(({method}) => method === 'log'); |
|||
}); |
|||
} |
|||
}); |
|||
|
|||
return unsubscribe; |
|||
}, [listen]); |
|||
|
|||
const [isExpanded, setIsExpanded] = React.useState(false); |
|||
|
|||
React.useEffect(() => { |
|||
if (wrapperRef.current) { |
|||
wrapperRef.current.scrollTop = wrapperRef.current.scrollHeight; |
|||
} |
|||
}, [logs]); |
|||
|
|||
if (logs.length === 0) { |
|||
return null; |
|||
} |
|||
|
|||
return ( |
|||
<div className="absolute dark:border-gray-700 bg-white dark:bg-gray-95 border-t bottom-0 w-full dark:text-white"> |
|||
<div className="flex justify-between"> |
|||
<button |
|||
className="flex items-center p-1" |
|||
onClick={() => setIsExpanded(!isExpanded)}> |
|||
<IconChevron displayDirection={isExpanded ? 'down' : 'right'} /> |
|||
<span className="pl-1 text-sm">Console ({logs.length})</span> |
|||
</button> |
|||
<button |
|||
className="p-1" |
|||
onClick={() => { |
|||
setLogs([]); |
|||
setIsExpanded(false); |
|||
}}> |
|||
<svg |
|||
viewBox="0 0 24 24" |
|||
width="18" |
|||
height="18" |
|||
stroke="currentColor" |
|||
strokeWidth="2" |
|||
fill="none" |
|||
strokeLinecap="round" |
|||
strokeLinejoin="round"> |
|||
<circle cx="12" cy="12" r="10"></circle> |
|||
<line x1="4.93" y1="4.93" x2="19.07" y2="19.07"></line> |
|||
</svg> |
|||
</button> |
|||
</div> |
|||
{isExpanded && ( |
|||
<div className="w-full h-full border-y bg-white dark:border-gray-700 dark:bg-gray-95 min-h-[28px] console"> |
|||
<div className="max-h-52 h-auto overflow-auto" ref={wrapperRef}> |
|||
{logs.map(({data, id, method}) => { |
|||
return ( |
|||
<div |
|||
key={id} |
|||
className={cn( |
|||
'last:border-none border-b dark:border-gray-700 text-md p-1 pl-2 leading-6 font-mono', |
|||
`console-${getType(method)}` |
|||
)}> |
|||
<span className={cn('console-message')}> |
|||
{data.map((msg, index) => { |
|||
if (typeof msg === 'string') { |
|||
return <span key={`${msg}-${index}`}>{msg}</span>; |
|||
} |
|||
|
|||
let children; |
|||
if (msg != null && typeof msg['@t'] === 'string') { |
|||
// CodeSandbox wraps custom types
|
|||
children = msg['@t']; |
|||
} else { |
|||
try { |
|||
children = JSON.stringify(msg, null, 2); |
|||
} catch (error) { |
|||
try { |
|||
children = Object.prototype.toString.call(msg); |
|||
} catch (err) { |
|||
children = '[' + typeof msg + ']'; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return ( |
|||
<span |
|||
className={cn('console-span')} |
|||
key={`${msg}-${index}`}> |
|||
<SandpackCodeViewer |
|||
initMode="user-visible" |
|||
// fileType="js"
|
|||
code={children} |
|||
/> |
|||
</span> |
|||
); |
|||
})} |
|||
</span> |
|||
</div> |
|||
); |
|||
})} |
|||
</div> |
|||
</div> |
|||
)} |
|||
</div> |
|||
); |
|||
}; |
Loading…
Reference in new issue