feat(components): Initialize component state and enable property mapping

- Ensure every component has an initialized state, defaulting to empty.
- Implement property mapping to synchronize states between parent and child components.
This commit is contained in:
Samuel Andert 2023-07-24 15:00:05 +02:00
parent 5b7c49fd58
commit e12f6bcf05
6 changed files with 106 additions and 19 deletions

View File

@ -1,17 +1,67 @@
<script lang="ts">
import Composite from './Composite.svelte'; // Recursive import
import Composite from './Composite.svelte';
import components from '$lib/componentLoader';
import { getContextStore } from '$lib/stores/contextStore.ts';
import { createComponentStore, getComponentStore } from '$lib/stores/componentStores.ts';
export let componentsData = {
layout: '',
children: []
};
function initializeComponentState(child) {
// This will either retrieve the existing store or create a default one
child.store = createComponentStore(child.id, child.state || {});
if (child.children) {
child.children.forEach(initializeComponentState);
}
}
$: if (componentsData && componentsData.children) {
componentsData.children.forEach((child) => {
child.store = getContextStore(child.componentName);
componentsData.children.forEach(initializeComponentState);
}
function mapAndSubscribe(component) {
console.log('Mapping and subscribing for:', component.id); // Debug line
if (component.map) {
const localStore = getComponentStore(component.id);
// Use the subscribe method to log and work with the store's value
localStore.subscribe((localStoreValue) => {
console.log('Local store before mapping:', localStoreValue);
});
for (const [localKey, external] of Object.entries(component.map)) {
const [externalID, externalKey] = external.split('.').map((item) => item.trim());
const externalStore = getComponentStore(externalID);
if (externalStore) {
externalStore.subscribe((externalState) => {
console.log('External state:', externalState); // Debug line
if (externalState && externalKey in externalState) {
localStore.update((storeValue) => {
storeValue = storeValue || {};
storeValue[localKey] = externalState[externalKey];
return storeValue;
});
}
});
}
}
// Use the subscribe method again if you want to log after mapping
localStore.subscribe((localStoreValue) => {
console.log('Local store after mapping:', localStoreValue);
});
}
if (component.children) {
component.children.forEach(mapAndSubscribe);
}
}
$: if (componentsData && componentsData.children) {
componentsData.children.forEach(mapAndSubscribe);
}
async function getComponent(componentName) {
@ -23,12 +73,14 @@
}
</script>
<!-- Rest of the component markup remains unchanged -->
<div class="grid w-full h-full" style="display: grid; {componentsData.layout || ''}">
{#each componentsData.children as component (component.id)}
{#await getComponent(component.componentName) then Component}
{#if Component}
<div class="w-full h-full overflow-hidden {component.slot}">
<svelte:component this={Component} {...component.props} />
<svelte:component this={Component} id={component.id} {...component.props} />
{#if component.actions}
<div class="flex justify-end p-4">

View File

@ -1 +1,10 @@
<div class="p-12 bg-blue-400">Hello Earth</div>
<script>
export let id;
import { getComponentStore } from '$lib/stores/componentStores.ts';
const store = getComponentStore(id);
$: console.log('store:', $store);
</script>
<div class="p-12 bg-blue-400">Hello Earth {JSON.stringify($store)}</div>

View File

@ -2,16 +2,16 @@
import { onMount } from 'svelte';
import { connectWallet } from '$lib/services/wallet/wallet';
import { getComponentStore } from '$lib/stores/componentStores.ts';
// please abstract this.
export let id;
const store = getComponentStore(id);
let pkpWallet = null;
const pkpPubKey =
'046da3ba67065fd1e2726242ca01cd4601524893f4aa4b0042578fa6cbec28fa8c9a28eb9f7893932fc09717edc9e1db57e157a21eed346247c1db5a722a01f571';
// Specify your RPC URL here
const rpcURL = 'https://rpc.gnosischain.com/';
onMount(async () => {
pkpWallet = await connectWallet(pkpPubKey, rpcURL);
pkpWallet = await connectWallet($store.pkpPubKey, $store.rpcURL);
});
</script>

View File

View File

@ -0,0 +1,16 @@
import { writable } from 'svelte/store';
const componentStores = new Map();
// Create or retrieve a component store
export function createComponentStore(componentId, initialState = {}) {
if (!componentStores.has(componentId)) {
componentStores.set(componentId, writable(initialState));
}
return componentStores.get(componentId);
}
// Get component store or create a default empty one if not exists
export function getComponentStore(componentId) {
return componentStores.get(componentId) || createComponentStore(componentId);
}

View File

@ -11,14 +11,24 @@
`,
children: [
{
id: 1,
id: 'login1',
componentName: 'Login',
props: {},
slot: 'login',
children: [
{
id: 5,
componentName: 'Wallet'
id: 'wallet1',
componentName: 'Wallet',
state: {
rpcURL: 'https://rpc.gnosischain.com/',
pkpPubKey:
'046da3ba67065fd1e2726242ca01cd4601524893f4aa4b0042578fa6cbec28fa8c9a28eb9f7893932fc09717edc9e1db57e157a21eed346247c1db5a722a01f571'
},
children: [
{
id: 'HelloEarth1',
componentName: 'HelloEarth',
map: { pkp: 'wallet1.pkpPubKey', rpcURL: 'wallet1.rpcURL' }
}
]
}
]
},