You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte/site/src/routes/repl/_components/Output/index.html

183 lines
3.9 KiB

<script>
import SplitPane from '../SplitPane.html';
import Viewer from './Viewer.html';
import CompilerOptions from './CompilerOptions.html';
import PropEditor from './PropEditor.html';
import CodeMirror from '../CodeMirror.html';
export let bundle
export let js;
export let css;
export let dom;
export let ssr;
export let props;
export let values_store;
export let json5;
export let sourceError;
export let sourceErrorLoc;
export let runtimeError;
export let compileOptions;
// refs
let viewer;
const setters = {};
let view = 'result';
function updateValues(prop, value) {
values_store.update(v => Object.assign({}, v, {
[prop]: value
}));
}
function setPropFromViewer(prop, value) {
// console.log(setters, prop, value);
// setters[prop](value);
updateValues(prop, value);
}
function setPropFromEditor(prop, value) {
viewer.setProp(prop, value);
updateValues(prop, value);
}
function navigate(event) {
// TODO handle navigation from error messages
}
</script>
<style>
.view-toggle {
height: var(--pane-controls-h);
border-bottom: 1px solid #eee;
white-space: nowrap;
}
button {
/* width: 50%;
height: 100%; */
text-align: left;
position: relative;
font: 400 1.2rem/1.5 var(--font);
border-bottom: var(--border-w) solid transparent;
padding: 1.2rem 0.8rem 0.8rem 0.8rem;
color: #999;
}
button.active {
border-bottom: var(--border-w) solid var(--prime);
color: #333;
}
div[slot] {
height: 100%;
}
h3 {
font: 700 1.2rem/1.5 var(--font);
padding: 1.2rem 0 0.8rem 1rem;
color: var(--text);
}
.loading.message {
position: absolute !important;
background-color: #666;
top: 1em;
left: 50%;
transform: translate(-50%,0);
}
.props {
display: grid;
padding: 0.5em;
grid-template-columns: auto 1fr;
grid-auto-rows: min-content;
grid-gap: 0.5em;
overflow-y: auto;
}
</style>
<div class="view-toggle">
<button
class:active="{view === 'result'}"
on:click="{() => view = 'result'}"
>Result</button>
<button
class:active="{view === 'js'}"
on:click="{() => view = 'js'}"
>JS output</button>
<button
class:active="{view === 'css'}"
on:click="{() => view = 'css'}"
>CSS output</button>
</div>
{#if view === 'result'}
<SplitPane type="vertical" pos={67}>
<div slot="a">
{#if bundle}
<Viewer
bind:this={viewer}
{bundle}
{dom}
{ssr}
{values_store}
{props}
{sourceError}
bind:error={runtimeError}
on:navigate={navigate}
on:binding="{e => setPropFromViewer(e.detail.prop, e.detail.value)}"
/>
{:else}
<!-- TODO componentise this -->
<p class="loading message">loading Svelte compiler...</p>
{/if}
</div>
<section slot="b">
<h3>Props editor</h3>
{#if props}
{#if props.length > 0}
<div class="props">
{#each props.sort() as prop (prop)}
<code style="display: block; whitespace: pre;">{prop}</code>
<!-- TODO `bind:this={propEditors[prop]}` — currently fails -->
<PropEditor
value={$values_store[prop]}
on:change="{e => setPropFromEditor(prop, e.detail.value)}"
/>
{/each}
</div>
{:else}
<div style="padding: 0.5em" class="linkify">
<!-- TODO explain distincion between logic-less and logic-ful components? -->
<!-- TODO style the <a> so it looks like a link -->
<p style="font-size: 1.3rem; color: var(--second)">This component has no props — <a href="guide#external-properties">declare props with the export keyword</a></p>
</div>
{/if}
{/if}
</section>
</SplitPane>
{:else}
<SplitPane type="vertical" pos={67}>
<div slot="a">
<CodeMirror
mode="javascript"
code="{view === 'js' ? js : css}"
error={sourceError}
errorLoc={sourceErrorLoc}
readonly
/>
</div>
<section slot="b">
<h3>Compiler options</h3>
<CompilerOptions bind:options={compileOptions}/>
</section>
</SplitPane>
{/if}