breaking changes, major refactoring of Composite

This commit is contained in:
Samuel Andert
2023-07-26 09:23:15 +02:00
parent 858d21e7db
commit 0161f4ba4f
14 changed files with 212 additions and 215 deletions

View File

@ -0,0 +1,144 @@
<script lang="ts">
import Composite from './Composite.svelte';
import components from '$lib/core/componentLoader';
import services from '$lib/core/servicesLoader';
import { createCompositeStore, getCompositeStore } from '$lib/core/compositeStores';
interface IComposite {
layout?: ICompositeLayout;
id: string;
slot?: string;
component: string;
services?: string[];
map?: Record<string, string>;
store?: Record<string, any>;
children?: IComposite[];
}
interface ICompositeLayout {
areas: string;
columns?: string;
rows?: string;
gap?: string;
tailwindClasses?: string;
}
export let composite: IComposite;
$: layoutStyle = composite?.layout
? `
grid-template-areas: ${composite.layout.areas};
${composite.layout.gap ? `gap: ${composite.layout.gap};` : ''}
${composite.layout.columns ? `grid-template-columns: ${composite.layout.columns};` : ''}
${composite.layout.rows ? `grid-template-rows: ${composite.layout.rows};` : ''}
`
: '';
function initializeCompositeState(child: IComposite) {
if (child.id) {
child.store = createCompositeStore(child.id, child.store || {});
}
if (child.children) {
child.children.forEach(initializeCompositeState);
}
}
$: if (composite && composite.children) {
composite.children.forEach(initializeCompositeState);
}
function mapAndSubscribe(component: IComposite) {
console.log('Mapping and subscribing for:', component.id);
if (component.map) {
const localStore = getCompositeStore(component.id);
for (const [localKey, external] of Object.entries(component.map)) {
const [externalID, externalKey] = external.split('.').map((item) => item.trim());
const externalStore = getCompositeStore(externalID);
if (externalStore) {
externalStore.subscribe((externalState) => {
console.log('External state:', externalState);
if (externalState && externalKey in externalState) {
localStore.update((storeValue) => {
storeValue = storeValue || {};
if (storeValue[localKey] !== externalState[externalKey]) {
storeValue[localKey] = externalState[externalKey];
return storeValue;
}
return storeValue;
});
}
});
}
}
}
if (component.children) {
component.children.forEach(mapAndSubscribe);
}
}
$: if (composite && composite.children) {
composite.children.forEach(mapAndSubscribe);
}
async function getComponent(componentName: string) {
if (components[componentName]) {
const module = await components[componentName]();
return module.default;
}
return null;
}
async function loadService(serviceName: string) {
if (services[serviceName]) {
const module = await services[serviceName]();
return module.default || module;
}
return null;
}
async function getServiceProps(component: IComposite) {
const loadedServices = {};
if (component.services) {
for (const serviceName of component.services) {
const loadedService = await loadService(serviceName);
if (loadedService) {
loadedServices[serviceName] = loadedService;
}
}
}
return loadedServices;
}
</script>
<div
class={composite?.layout
? `grid w-full h-full ${composite.layout.tailwindClasses}`
: 'grid w-full h-full'}
style={layoutStyle}
>
{#if composite && composite.children}
{#each composite.children as child (child.id)}
<div class={`w-full h-full overflow-hidden`} style={`grid-area: ${child.slot}`}>
{#await Promise.all( [getComponent(child.component), getServiceProps(child)] ) then [Component, serviceProps]}
{#if Component}
<svelte:component
this={Component}
id={child.id}
{...child.store}
services={serviceProps}
/>
{#if child.children && child.children.length}
<Composite composite={child} />
{/if}
{:else}
<p>Component {child.component} not found.</p>
{/if}
{/await}
</div>
{/each}
{/if}
</div>