remove props editor

pull/2199/head
Richard Harris 7 years ago
parent 217cd6c741
commit 0bbea065bb

@ -1,71 +0,0 @@
<script>
import { createEventDispatcher } from 'svelte';
import * as fleece from 'golden-fleece';
import CodeMirror from '../CodeMirror.svelte';
const dispatch = createEventDispatcher();
export let value;
let error;
let code;
if (value === undefined) {
code = 'undefined';
} else {
code = fleece.stringify(value);
console.log({ value, code });
}
$: try {
value = fleece.evaluate(code);
} catch (e) {
error = e;
}
let previous_code;
function handleChange(event) {
try {
const value = fleece.evaluate(event.detail.value);
code = previous_code = event.detail.value;
error = null;
dispatch('change', { value });
} catch (e) {
error = e;
}
}
function stringify(value) {
if (value === undefined) return '<undefined>';
const code = previous_code
? fleece.patch(previous_code, value)
: fleece.stringify(value);
previous_code = code;
return code;
}
</script>
<style>
.prop-editor {
border: 1px solid #eee;
}
.error {
background-color: rgba(218, 16, 96, 0.1);
border: 1px solid #da106e;
}
</style>
<div class="prop-editor" class:error title="{error && error.message || ''}">
<CodeMirror
mode="json"
code={stringify(value)}
lineNumbers={false}
on:change={handleChange}
tab={false}
flex
/>
</div>

@ -57,11 +57,6 @@ export default class ReplProxy {
this.handleCommandMessage(event.data); this.handleCommandMessage(event.data);
} }
if (action === 'prop_update') {
const { prop, value } = args;
this.handlers.onPropUpdate(prop, value)
}
if (action === 'fetch_progress') { if (action === 'fetch_progress') {
this.handlers.onFetchProgress(args.remaining) this.handlers.onFetchProgress(args.remaining)
} }
@ -71,14 +66,6 @@ export default class ReplProxy {
return this.iframeCommand('eval', { script }); return this.iframeCommand('eval', { script });
} }
setProp(prop, value) {
return this.iframeCommand('set_prop', {prop, value})
}
bindProps(props) {
return this.iframeCommand('bind_props', { props })
}
handleLinks() { handleLinks() {
return this.iframeCommand('catch_clicks', {}); return this.iframeCommand('catch_clicks', {});
} }

@ -6,9 +6,8 @@
import { decode } from 'sourcemap-codec'; import { decode } from 'sourcemap-codec';
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
const { bundle, values, navigate } = getContext('REPL'); const { bundle, navigate } = getContext('REPL');
export let props;
export let error; // TODO should this be exposed as a prop? export let error; // TODO should this be exposed as a prop?
export function setProp(prop, value) { export function setProp(prop, value) {
@ -26,13 +25,6 @@
onMount(() => { onMount(() => {
proxy = new ReplProxy(iframe, { proxy = new ReplProxy(iframe, {
onPropUpdate: (prop, value) => {
dispatch('binding', { prop, value });
values.update(values => Object.assign({}, values, {
[prop]: value
}));
},
onFetchProgress: progress => { onFetchProgress: progress => {
pending_imports = progress; pending_imports = progress;
} }
@ -84,13 +76,10 @@
window._svelteTransitionManager = null; window._svelteTransitionManager = null;
window.component = new SvelteComponent({ window.component = new SvelteComponent({
target: document.body, target: document.body
props: ${JSON.stringify($values)}
}); });
`); `);
await proxy.bindProps(props);
error = null; error = null;
} catch (e) { } catch (e) {
const loc = getLocationFromStack(e.stack, $bundle.dom.map); const loc = getLocationFromStack(e.stack, $bundle.dom.map);

@ -4,7 +4,6 @@
import Viewer from './Viewer.svelte'; import Viewer from './Viewer.svelte';
import CompilerOptions from './CompilerOptions.svelte'; import CompilerOptions from './CompilerOptions.svelte';
import Compiler from './Compiler.js'; import Compiler from './Compiler.js';
import PropEditor from './PropEditor.svelte';
import CodeMirror from '../CodeMirror.svelte'; import CodeMirror from '../CodeMirror.svelte';
const { values, register_output } = getContext('REPL'); const { values, register_output } = getContext('REPL');
@ -13,9 +12,6 @@
export let sourceErrorLoc; export let sourceErrorLoc;
export let runtimeError; export let runtimeError;
export let embedded; export let embedded;
export let show_props;
let props;
let compile_options = { let compile_options = {
generate: 'dom', generate: 'dom',
@ -39,7 +35,6 @@
js_editor.set(compiled.js, 'js'); js_editor.set(compiled.js, 'js');
css_editor.set(compiled.css, 'css'); css_editor.set(compiled.css, 'css');
if (compiled.props) props = compiled.props;
}, },
update: async selected => { update: async selected => {
@ -49,7 +44,6 @@
js_editor.update(compiled.js); js_editor.update(compiled.js);
css_editor.update(compiled.css); css_editor.update(compiled.css);
if (compiled.props) props = compiled.props;
} }
}); });
@ -119,19 +113,6 @@
color: var(--text); color: var(--text);
} }
.props {
display: grid;
padding: 0.5em;
grid-template-columns: auto 1fr;
grid-auto-rows: min-content;
grid-gap: 0.5em;
overflow-y: auto;
}
.props code {
top: .1rem;
}
.tab-content { .tab-content {
position: absolute; position: absolute;
width: 100%; width: 100%;
@ -166,44 +147,11 @@
<!-- component viewer --> <!-- component viewer -->
<div class="tab-content" class:visible="{view === 'result'}"> <div class="tab-content" class:visible="{view === 'result'}">
<SplitPane type="vertical" pos={67} fixed={!show_props} fixed_pos={100}> <Viewer
<div slot="a"> bind:this={viewer}
<Viewer bind:error={runtimeError}
bind:this={viewer} on:binding="{e => setPropFromViewer(e.detail.prop, e.detail.value)}"
{props} />
bind:error={runtimeError}
on:binding="{e => setPropFromViewer(e.detail.prop, e.detail.value)}"
/>
</div>
<section slot="b">
{#if show_props}
<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[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="docs#external-properties">declare props with the export keyword</a></p>
</div>
{/if}
{/if}
{/if}
</section>
</SplitPane>
</div> </div>
<!-- js output --> <!-- js output -->

@ -11,7 +11,6 @@
export let version = 'beta'; // TODO change this to latest when the time comes export let version = 'beta'; // TODO change this to latest when the time comes
export let embedded = false; export let embedded = false;
export let orientation = 'columns'; export let orientation = 'columns';
export let show_props = true;
export function toJSON() { export function toJSON() {
// TODO there's a bug here — Svelte hoists this function because // TODO there's a bug here — Svelte hoists this function because
@ -22,14 +21,12 @@
return { return {
imports: $bundle.imports, imports: $bundle.imports,
components: $components, components: $components
values: $values
}; };
} }
export function set(data) { export function set(data) {
components.set(data.components); components.set(data.components);
values.set(data.values);
selected.set(data.components[0]); selected.set(data.components[0]);
module_editor.set($selected.source, $selected.type); module_editor.set($selected.source, $selected.type);
@ -40,7 +37,6 @@
const { name, type } = $selected || {}; const { name, type } = $selected || {};
components.set(data.components); components.set(data.components);
values.set(data.values);
const matched_component = data.components.find(file => file.name === name && file.type === type); const matched_component = data.components.find(file => file.name === name && file.type === type);
selected.set(matched_component || data.components[0]); selected.set(matched_component || data.components[0]);
@ -57,7 +53,6 @@
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
const components = writable([]); const components = writable([]);
const values = writable({});
const selected = writable(null); const selected = writable(null);
const bundle = writable(null); const bundle = writable(null);
@ -66,7 +61,6 @@
setContext('REPL', { setContext('REPL', {
components, components,
values,
selected, selected,
bundle, bundle,
@ -227,7 +221,7 @@
</section> </section>
<section slot=b style='height: 100%;'> <section slot=b style='height: 100%;'>
<Output {version} {embedded} {show_props}/> <Output {version} {embedded}/>
</section> </section>
</SplitPane> </SplitPane>
</div> </div>

@ -1,5 +1,4 @@
<script> <script>
import * as fleece from 'golden-fleece';
import { createEventDispatcher } from 'svelte'; import { createEventDispatcher } from 'svelte';
import UserMenu from './UserMenu.svelte'; import UserMenu from './UserMenu.svelte';
import Icon from '../../../../components/Icon.svelte'; import Icon from '../../../../components/Icon.svelte';
@ -54,8 +53,7 @@
async function fork(intentWasSave) { async function fork(intentWasSave) {
saving = true; saving = true;
const { components, values } = repl.toJSON(); const { components } = repl.toJSON();
const json5 = fleece.stringify(values); // TODO preserve the original code
try { try {
const r = await fetch(`gist/create`, { const r = await fetch(`gist/create`, {
@ -63,8 +61,7 @@
credentials: 'include', credentials: 'include',
body: JSON.stringify({ body: JSON.stringify({
name, name,
components, components
json5
}) })
}); });
@ -106,8 +103,7 @@
saving = true; saving = true;
const { components, values } = repl.toJSON(); const { components } = repl.toJSON();
const json5 = fleece.stringify(values); // TODO preserve the original code
try { try {
const files = {}; const files = {};
@ -131,13 +127,6 @@
} }
}); });
if (!gist.files['data.json5'] || json5 !== gist.files['data.json5'].content) {
files['data.json5'] = { content: json5 };
}
// data.json has been deprecated in favour of data.json5
if (gist.files['data.json']) gist.files['data.json'] = null;
const r = await fetch(`gist/${gist.id}`, { const r = await fetch(`gist/${gist.id}`, {
method: 'PATCH', method: 'PATCH',
credentials: 'include', credentials: 'include',
@ -171,7 +160,7 @@
async function download() { async function download() {
downloading = true; downloading = true;
const { components, imports, values } = repl.toJSON(); const { components, imports } = repl.toJSON();
const files = await (await fetch('/svelte-app.json')).json(); const files = await (await fetch('/svelte-app.json')).json();
@ -192,8 +181,7 @@
path: `src/main.js`, data: `import App from './App.svelte'; path: `src/main.js`, data: `import App from './App.svelte';
var app = new App({ var app = new App({
target: document.body, target: document.body
props: ${JSON.stringify(values, null, '\t').replace(/\n/g, '\n\t')}
}); });
export default app;` }); export default app;` });

@ -10,7 +10,6 @@
<script> <script>
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import * as fleece from 'golden-fleece';
import Repl from '../../components/Repl/index.svelte'; import Repl from '../../components/Repl/index.svelte';
export let version, gist, demo; export let version, gist, demo;
@ -33,8 +32,6 @@
name = description; name = description;
let values = {};
const components = Object.keys(files) const components = Object.keys(files)
.map(file => { .map(file => {
const dot = file.lastIndexOf('.'); const dot = file.lastIndexOf('.');
@ -42,11 +39,6 @@
const source = files[file].content; const source = files[file].content;
// while we're here...
if (file === 'data.json' || file === 'data.json5') {
values = tryParseData(source) || {};
}
return { return {
name: file.slice(0, dot), name: file.slice(0, dot),
type: file.slice(dot + 1), type: file.slice(dot + 1),
@ -63,7 +55,7 @@
return a.name < b.name ? -1 : 1; return a.name < b.name ? -1 : 1;
}); });
repl.set({ components, values }); repl.set({ components });
}); });
} else if (demo) { } else if (demo) {
const url = `api/examples/${demo}`; const url = `api/examples/${demo}`;
@ -73,21 +65,12 @@
const data = await response.json(); const data = await response.json();
repl.set({ repl.set({
values: tryParseData(data.json5) || {}, // TODO make this more error-resistant
components: data.components components: data.components
}); });
} }
}); });
} }
}); });
function tryParseData(json5) {
try {
return fleece.evaluate(json5);
} catch (err) {
return null;
}
}
</script> </script>
<style> <style>

@ -11,7 +11,6 @@
<script> <script>
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { locate } from 'locate-character'; import { locate } from 'locate-character';
import * as fleece from 'golden-fleece';
import AppControls from './_components/AppControls/index.svelte'; import AppControls from './_components/AppControls/index.svelte';
import Repl from '../../components/Repl/index.svelte'; import Repl from '../../components/Repl/index.svelte';
import examples from '../../../content/examples/manifest.json'; import examples from '../../../content/examples/manifest.json';
@ -60,8 +59,6 @@
name = description; name = description;
let values = {};
const components = Object.keys(files) const components = Object.keys(files)
.map(file => { .map(file => {
const dot = file.lastIndexOf('.'); const dot = file.lastIndexOf('.');
@ -69,11 +66,6 @@
const source = files[file].content; const source = files[file].content;
// while we're here...
if (file === 'data.json' || file === 'data.json5') {
values = tryParseData(source) || {};
}
let type = file.slice(dot + 1); let type = file.slice(dot + 1);
if (type === 'html') type = 'svelte'; if (type === 'html') type = 'svelte';
@ -93,7 +85,7 @@
return a.name < b.name ? -1 : 1; return a.name < b.name ? -1 : 1;
}); });
repl.set({ components, values }); repl.set({ components });
}); });
} }
}); });
@ -112,7 +104,6 @@
console.log(data.components); console.log(data.components);
repl.set({ repl.set({
values: tryParseData(data.json5) || {}, // TODO make this more error-resistant
components: data.components components: data.components
}); });
@ -128,14 +119,6 @@
gist_id = gist.id; gist_id = gist.id;
} }
function tryParseData(json5) {
try {
return fleece.evaluate(json5);
} catch (err) {
return null;
}
}
$: if (process.browser && demo) { $: if (process.browser && demo) {
load_demo(demo); load_demo(demo);
} }

@ -258,6 +258,6 @@
</div> </div>
<div class="tutorial-repl"> <div class="tutorial-repl">
<Repl bind:this={repl} orientation="rows" show_props={false} on:change={handle_change}/> <Repl bind:this={repl} orientation="rows" on:change={handle_change}/>
</div> </div>
</div> </div>

@ -36,16 +36,11 @@ function compile({ id, source, options, entry }) {
Object.assign({}, commonCompilerOptions, options) Object.assign({}, commonCompilerOptions, options)
); );
const props = entry
? (vars || stats.vars).map(v => v.writable && v.export_name).filter(Boolean) // TODO remove stats post-launch
: null;
return { return {
id, id,
result: { result: {
js: js.code, js: js.code,
css: css.code || `/* Add a <sty` + `le> tag to see compiled CSS */`, css: css.code || `/* Add a <sty` + `le> tag to see compiled CSS */`
props
} }
}; };
} catch (err) { } catch (err) {
@ -57,8 +52,7 @@ function compile({ id, source, options, entry }) {
id, id,
result: { result: {
js: message, js: message,
css: message, css: message
props: null
} }
}; };
} }

Loading…
Cancel
Save