breaking changes, major refactoring of Composite
This commit is contained in:
144
src/lib/core/Composite.svelte
Normal file
144
src/lib/core/Composite.svelte
Normal 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>
|
Reference in New Issue
Block a user