feat(apps): state can be used as input in apps

This commit is contained in:
Ruben Fiszel
2023-03-14 20:44:14 +01:00
parent 81f989837b
commit 2f0acb9ffa
7 changed files with 49 additions and 22 deletions
@@ -84,7 +84,8 @@
true,
$state,
$mode == 'dnd',
$componentControl
$componentControl,
$worldStore
)
error = ''
return r
@@ -103,7 +104,8 @@
true,
$state,
$mode == 'dnd',
$componentControl
$componentControl,
$worldStore
)
error = ''
return r
@@ -163,7 +163,8 @@
false,
$state,
$mode == 'dnd',
$componentControl
$componentControl,
$worldStore
)
setResult(r)
$state = $state
@@ -1,4 +1,3 @@
import { goto } from '$app/navigation'
import { sendUserToast } from '$lib/utils'
import type { World } from '../../rx'
@@ -10,7 +9,7 @@ export function computeGlobalContext(
return {
...Object.fromEntries(
Object.entries(world?.outputsById ?? {})
.filter(([k, _]) => k != id)
.filter(([k, _]) => k != id && k != 'state')
.map(([key, value]) => {
return [
key,
@@ -47,17 +46,29 @@ function make_context_evaluator(
}
export async function eval_like(
text,
text: string,
context = {},
noReturn: boolean,
state: any,
state: Record<string, any>,
editor: boolean,
controlComponents: Record<string, { setTab?: (index: number) => void }>
controlComponents: Record<string, { setTab?: (index: number) => void }>,
worldStore: World | undefined
) {
const proxiedState = new Proxy(state, {
set(target, key, value) {
if (typeof key !== 'string') {
throw new Error('Invalid key')
}
let o = worldStore?.newOutput('state', key, value)
o?.set(value)
target[key] = value
return true
}
})
let evaluator = make_context_evaluator(text, context, noReturn)
return await evaluator(
context,
state,
proxiedState,
async (x, newTab) => {
if (newTab || editor) {
if (!newTab) {
@@ -13,6 +13,7 @@
import { push } from '$lib/history'
import { expandGriditem, findGridItem } from './appUtils'
import Grid from '../svelte-grid/Grid.svelte'
import { settableOutput } from '../rx'
export let policy: Policy
@@ -75,14 +75,14 @@
/>
</OutputHeader>
<OutputHeader id={'State'} name={'State'} color="blue" {expanded}>
{#key $state}
{#if Object.keys(filteredState).length > 0}
<ObjectViewer json={filteredState} />
{:else}
<div class="text-xs pl-2">No results</div>
{/if}
{/key}
<OutputHeader id={'state'} name={'State'} color="blue" {expanded}>
<ComponentOutputViewer
componentId={'state'}
outputs={Object.keys($state)}
on:select={({ detail }) => {
$connectingInput = connectInput($connectingInput, 'state', detail)
}}
/>
</OutputHeader>
</div>
@@ -47,7 +47,7 @@
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class={classNames(
'flex items-center justify-between p-1 cursor-pointer border-b',
'flex items-center justify-between p-1 cursor-pointer border-b gap-1 truncate',
hoverColor[color],
open && !manuallyOpen ? openBackground[color] : 'bg-white',
first ? 'border-t' : '',
@@ -66,7 +66,7 @@
>
{id}
</div>
<div class="text-2xs font-bold flex flex-row gap-2 items-center">
<div class="text-2xs font-bold flex flex-row gap-2 items-center truncate">
{name}
{#if !open && !manuallyOpen}
<ChevronDown size={14} />
+15 -3
View File
@@ -23,6 +23,7 @@ export type World = {
outputsById: Record<string, Record<string, Output<any>>>
connect: <T>(inputSpec: AppInput, next: (x: T) => void, id?: string) => Input<T>
stateId: Writable<number>
newOutput: <T>(id: string, name: string, previousValue: T) => Output<T>
}
export function buildWorld(
@@ -38,7 +39,8 @@ export function buildWorld(
Object.entries(context).map(([k, v]) => {
return [k, newWorld.newOutput('ctx', k, stateId, v)]
})
)
),
state: previousWorld?.outputsById?.state ?? {}
}
for (const [k, outputs] of Object.entries(components)) {
outputsById[k] = {}
@@ -52,9 +54,20 @@ export function buildWorld(
)
}
}
function newOutput<T>(id: string, name: string, previousValue: T) {
if (outputsById[id]?.[name]) {
return outputsById[id][name]
}
let o = newWorld.newOutput(id, name, stateId, previousValue)
if (!outputsById[id]) {
outputsById[id] = {}
}
outputsById[id][name] = o
return o
}
stateId.update((x) => x + 1)
return { outputsById, connect: newWorld.connect, stateId }
return { outputsById, connect: newWorld.connect, stateId, newOutput }
}
export function buildObservableWorld() {
@@ -166,7 +179,6 @@ export function settableOutput<T>(state: Writable<number>, previousValue: T): Ou
state.update((x) => x + 1)
value = x
subscribers.forEach((x) => x.next(value!))
}
}