start using context API for REPL

pull/2179/head
Richard Harris 7 years ago
parent 64295c7d1a
commit 9e5c5a9f89

@ -1,33 +1,31 @@
<script>
import { createEventDispatcher } from 'svelte';
import { getContext, createEventDispatcher } from 'svelte';
import Icon from '../../Icon.svelte';
import { enter } from '../../../utils/events.js';
const { components, selected } = getContext('REPL');
const dispatch = createEventDispatcher();
export let component_store;
export let selected_store;
let editing = null;
function selectComponent(component) {
if ($selected_store != component) {
if ($selected != component) {
editing = null;
}
selected_store.set(component);
selected.set(component);
}
function editTab(component) {
if ($selected_store === component) {
editing = $selected_store;
if ($selected === component) {
editing = $selected;
}
}
function closeEdit() {
const match = /(.+)\.(svelte|js)$/.exec($selected_store.name);
$selected_store.name = match ? match[1] : $selected_store.name;
if (match && match[2]) $selected_store.type = match[2];
const match = /(.+)\.(svelte|js)$/.exec($selected.name);
$selected.name = match ? match[1] : $selected.name;
if (match && match[2]) $selected.type = match[2];
editing = null;
components = components; // TODO necessary?
@ -60,8 +58,8 @@
document.getElementById(component.name).scrollIntoView(false);
});
component_store.update(components => components.concat(component));
selected_store.set(component);
components.update(components => components.concat(component));
selected.set(component);
}
</script>
@ -171,10 +169,10 @@
<div class="component-selector">
<div class="file-tabs" on:dblclick="{addNew}">
{#each $component_store as component}
{#each $components as component}
<button
id={component.name}
class:active="{component === $selected_store}"
class:active="{component === $selected}"
data-name={component.name}
on:click="{() => selectComponent(component)}"
on:dblclick="{e => e.stopPropagation()}"

@ -1,7 +1,9 @@
<script>
import { getContext } from 'svelte';
import CodeMirror from '../CodeMirror.svelte';
export let component;
const { selected } = getContext('REPL');
export let error;
export let errorLoc;
export let warningCount = 0;
@ -24,10 +26,10 @@
</style>
<div class="editor-wrapper">
{#if component}
{#if $selected}
<CodeMirror
mode="{component.type === 'js' ? 'javascript' : 'handlebars'}"
code={component.source}
mode="{$selected.type === 'js' ? 'javascript' : 'handlebars'}"
code={$selected.source}
{error}
{errorLoc}
{warningCount}

@ -2,8 +2,6 @@
import ComponentSelector from './ComponentSelector.svelte';
import ModuleEditor from './ModuleEditor.svelte';
export let selected_store;
export let component_store;
export let error;
export let errorLoc;
export let warningCount;
@ -11,15 +9,12 @@
<!-- TODO would be nice if events bubbled -->
<ComponentSelector
{component_store}
{selected_store}
on:create
on:remove
on:select
/>
<ModuleEditor
component={$selected_store}
{error}
{errorLoc}
{warningCount}

@ -1,12 +1,12 @@
<script>
import { onMount, onDestroy, createEventDispatcher } from 'svelte';
import { onMount, onDestroy, createEventDispatcher, getContext } from 'svelte';
import getLocationFromStack from './getLocationFromStack.js';
import ReplProxy from './replProxy.js';
import { decode } from 'sourcemap-codec';
const dispatch = createEventDispatcher();
const { values } = getContext('REPL');
export let values_store;
export let bundle;
export let dom;
export let ssr;
@ -79,7 +79,7 @@
replProxy.onPropUpdate = (prop, value) => {
dispatch('binding', { prop, value });
values_store.update(values => Object.assign({}, values, {
values.update(values => Object.assign({}, values, {
[prop]: value
}));
};
@ -132,7 +132,7 @@
const createHtml = () => {
replProxy.eval(`${ssr.code}
var rendered = SvelteComponent.render(${JSON.stringify($values_store)});
var rendered = SvelteComponent.render(${JSON.stringify($values)});
if (rendered.css.code) {
var style = document.createElement('style');
@ -173,7 +173,7 @@
window.component = new SvelteComponent({
target: document.body,
props: ${JSON.stringify($values_store)}
props: ${JSON.stringify($values)}
});
`)
.then(()=> {

@ -1,11 +1,12 @@
<script>
import { getContext } from 'svelte';
import SplitPane from '../SplitPane.svelte';
import Viewer from './Viewer.svelte';
import CompilerOptions from './CompilerOptions.svelte';
import PropEditor from './PropEditor.svelte';
import CodeMirror from '../CodeMirror.svelte';
export let values_store;
const { values } = getContext('REPL');
export let bundle;
export let js;
@ -28,7 +29,7 @@
let view = 'result';
function updateValues(prop, value) {
values_store.update(v => Object.assign({}, v, {
values.update(v => Object.assign({}, v, {
[prop]: value
}));
}
@ -130,7 +131,6 @@
{bundle}
{dom}
{ssr}
{values_store}
{props}
{sourceError}
bind:error={runtimeError}
@ -155,7 +155,7 @@
<!-- TODO `bind:this={propEditors[prop]}` — currently fails -->
<PropEditor
value={$values_store[prop]}
value={$values[prop]}
on:change="{e => setPropFromEditor(prop, e.detail.value)}"
/>
{/each}

@ -1,5 +1,5 @@
<script>
import { onMount } from 'svelte';
import { onMount, setContext } from 'svelte';
import { writable } from 'svelte/store';
import * as fleece from 'golden-fleece';
import SplitPane from './SplitPane.svelte';
@ -16,26 +16,32 @@
export function toJSON() {
// TODO there's a bug here — Svelte hoists this function because
// it wrongly things that $component_store is global. Needs to
// it wrongly things that $components is global. Needs to
// factor in $ variables when determining hoistability
version; // workaround
return {
imports: bundle && bundle.imports || [],
components: $component_store,
values: $values_store
components: $components,
values: $values
};
}
let component_store = writable([]);
let values_store = writable({});
let selected_store = writable(null);
const components = writable([]);
const values = writable({});
const selected = writable(null);
setContext('REPL', {
components,
values,
selected
});
$: {
component_store.set(app.components);
values_store.set(app.values);
selected_store.set(app.components[0]);
components.set(app.components);
values.set(app.values);
selected.set(app.components[0]);
}
let workers;
@ -93,23 +99,19 @@
});
function removeComponent() {
const selected = $selected_store;
if (selected.name === 'App') {
if ($selected.name === 'App') {
// App.svelte can't be removed
selected.source = '';
// $selected_store.set(selected);
$selected.source = '';
} else {
const components = $component_store;
const index = components.indexOf(selected);
const index = $components.indexOf($selected);
if (~index) {
component_store.set(components.slice(0, index).concat(components.slice(index + 1)));
components.set($components.slice(0, index).concat($components.slice(index + 1)));
} else {
console.error(`Could not find component! That's... odd`);
}
selected_store.set(components[index] || components[components.length - 1]);
selected.set($components[index] || $components[$components.length - 1]);
}
}
@ -122,7 +124,7 @@
name: component.name,
filename: `${component.name}.svelte`
}, options),
entry: component === $component_store[0]
entry: component === $components[0]
});
} else {
js = css = `/* Select a component to see its compiled code */`;
@ -130,9 +132,9 @@
}
function handleChange(event) {
selected_store.update(component => {
selected.update(component => {
// TODO this is a bit hacky — we're relying on mutability
// so that updating component_store works... might be better
// so that updating components works... might be better
// if a) components had unique IDs, b) we tracked selected
// *index* rather than component, and c) `selected` was
// derived from `components` and `index`
@ -140,13 +142,13 @@
return component;
});
component_store.update(c => c);
components.update(c => c);
// recompile selected component
compile($selected_store, compileOptions);
compile($selected, compileOptions);
// regenerate bundle (TODO do this in a separate worker?)
workers.bundler.postMessage({ type: 'bundle', components: $component_store });
workers.bundler.postMessage({ type: 'bundle', components: $components });
}
function navigate(filename) {
@ -158,14 +160,14 @@
// selected = components.find(c => c.name === name);
}
$: if (sourceError && $selected_store) {
sourceErrorLoc = sourceError.filename === `${$selected_store.name}.${$selected_store.type}`
$: if (sourceError && $selected) {
sourceErrorLoc = sourceError.filename === `${$selected.name}.${$selected.type}`
? sourceError.start
: null;
}
$: if (runtimeError && $selected_store) {
runtimeErrorLoc = runtimeError.filename === `${$selected_store.name}.${$selected_store.type}`
$: if (runtimeError && $selected) {
runtimeErrorLoc = runtimeError.filename === `${$selected.name}.${$selected.type}`
? runtimeError.start
: null;
}
@ -174,8 +176,8 @@
workers.bundler.postMessage({ type: 'bundle', components: app.components });
}
$: if (workers && $selected_store) {
compile($selected_store, compileOptions);
$: if (workers && $selected) {
compile($selected, compileOptions);
}
</script>
@ -287,9 +289,6 @@
>
<section slot=a>
<Input
{component_store}
{selected_store}
{values_store}
error={sourceError}
errorLoc="{sourceErrorLoc || runtimeErrorLoc}"
{warningCount}
@ -302,14 +301,12 @@
<Output
bind:compileOptions
{version}
{selected_store}
{js}
{css}
{bundle}
{ssr}
{dom}
{props}
{values_store}
{sourceError}
{runtimeError}
{embedded}

Loading…
Cancel
Save