Added dynamic instantiation of machines in composite
This commit is contained in:
		| @@ -1,7 +1,6 @@ | |||||||
| <script> | <script> | ||||||
| 	import { Machine, interpret } from 'xstate'; |  | ||||||
|  |  | ||||||
| 	export let services; | 	export let services; | ||||||
|  | 	export let store; | ||||||
|  |  | ||||||
| 	let childStore; | 	let childStore; | ||||||
|  |  | ||||||
| @@ -9,44 +8,18 @@ | |||||||
| 		childStore = services.core.subscribeComposite('@child'); | 		childStore = services.core.subscribeComposite('@child'); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	const colorMachine = Machine({ |  | ||||||
| 		id: 'color', |  | ||||||
| 		initial: 'RED', |  | ||||||
| 		states: { |  | ||||||
| 			GREEN: { |  | ||||||
| 				on: { SWITCH: 'YELLOW' } |  | ||||||
| 			}, |  | ||||||
| 			YELLOW: { |  | ||||||
| 				on: { SWITCH: 'RED' } |  | ||||||
| 			}, |  | ||||||
| 			RED: { |  | ||||||
| 				on: { SWITCH: 'GREEN' } |  | ||||||
| 			} |  | ||||||
| 		}, |  | ||||||
| 		on: { |  | ||||||
| 			READY: 'GREEN', |  | ||||||
| 			NOTREADY: 'RED' |  | ||||||
| 		} |  | ||||||
| 	}); |  | ||||||
|  |  | ||||||
| 	let current = colorMachine.initialState.value; |  | ||||||
|  |  | ||||||
| 	const service = interpret(colorMachine) |  | ||||||
| 		.onTransition((state) => { |  | ||||||
| 			current = state.value; |  | ||||||
| 		}) |  | ||||||
| 		.start(); |  | ||||||
|  |  | ||||||
| 	$: { | 	$: { | ||||||
| 		if ($childStore && $childStore.xstate) { | 		if ($childStore && $childStore.machine.state) { | ||||||
| 			service.send($childStore.xstate); | 			services.machine.send($childStore.machine.state); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <div class="p-2 border-2 border-blue-500">I am the parent, this is my state: {current}</div> | <div class="p-2 border-2 border-blue-500"> | ||||||
|  | 	I am the parent, this is my state: {$store.machine.state} | ||||||
|  | </div> | ||||||
| <div | <div | ||||||
| 	class="p-2 border-2" | 	class="p-2 border-2" | ||||||
| 	style="background-color: {current}; border-radius: 50%; width: 50px; height: 50px;" | 	style="background-color: {$store.machine.state}; border-radius: 50%; width: 50px; height: 50px;" | ||||||
| /> | /> | ||||||
| <p>The child state: {JSON.stringify($childStore)}</p> | <p>The child state: {JSON.stringify($childStore)}</p> | ||||||
|   | |||||||
| @@ -11,10 +11,9 @@ | |||||||
| 	$: if (machine) { | 	$: if (machine) { | ||||||
| 		compositeMachine = Machine(machine); | 		compositeMachine = Machine(machine); | ||||||
|  |  | ||||||
| 		current = compositeMachine.initialState.value; // remove let | 		current = compositeMachine.initialState.value; | ||||||
| 		service = interpret(compositeMachine).onTransition((state) => { | 		service = interpret(compositeMachine).onTransition((state) => { | ||||||
| 			current = state.value; | 			$store.machine.state = state.value; | ||||||
| 			$store.xstate = state.value; |  | ||||||
| 		}); | 		}); | ||||||
|  |  | ||||||
| 		service.start(); | 		service.start(); | ||||||
| @@ -22,9 +21,7 @@ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <div class="border-2 border-yellow-500"> | <div class="border-2 border-yellow-500"> | ||||||
| 	{#if machine} | 	i am the child and this is my state: {$store.machine.state} | ||||||
| 		i am the child and this is my state: {current} |  | ||||||
| 	{/if} |  | ||||||
| 	<button | 	<button | ||||||
| 		class="px-4 py-2 font-bold text-white bg-blue-500 rounded hover:bg-blue-700" | 		class="px-4 py-2 font-bold text-white bg-blue-500 rounded hover:bg-blue-700" | ||||||
| 		on:click={() => service.send('TOGGLE')}>Switch</button | 		on:click={() => service.send('TOGGLE')}>Switch</button | ||||||
|   | |||||||
							
								
								
									
										14
									
								
								src/lib/components/Recipies/machines/toggleMachine.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/lib/components/Recipies/machines/toggleMachine.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | import { Machine } from 'xstate'; | ||||||
|  |  | ||||||
|  | export const toggleMachine = Machine({ | ||||||
|  |     id: 'toggleMachine', | ||||||
|  |     initial: 'NOTREADY', | ||||||
|  |     states: { | ||||||
|  |         NOTREADY: { | ||||||
|  |             on: { TOGGLE: 'READY' } | ||||||
|  |         }, | ||||||
|  |         READY: { | ||||||
|  |             on: { TOGGLE: 'NOTREADY' } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | }); | ||||||
| @@ -19,7 +19,7 @@ | |||||||
| 				component: 'LearnReady', | 				component: 'LearnReady', | ||||||
| 				slot: 'left', | 				slot: 'left', | ||||||
| 				store: { | 				store: { | ||||||
| 					xstate: 'NOTREADY' | 					machine: { state: 'NOTREADY' } | ||||||
| 				}, | 				}, | ||||||
| 				machine: { | 				machine: { | ||||||
| 					id: 'compositemachine', | 					id: 'compositemachine', | ||||||
| @@ -35,9 +35,28 @@ | |||||||
| 				} | 				} | ||||||
| 			}, | 			}, | ||||||
| 			{ | 			{ | ||||||
| 				id: 'parent', | 				id: 'learncolor', | ||||||
| 				component: 'LearnColor', | 				component: 'LearnColor', | ||||||
| 				slot: 'right' | 				slot: 'right', | ||||||
|  | 				machine: { | ||||||
|  | 					id: 'color', | ||||||
|  | 					initial: 'RED', | ||||||
|  | 					states: { | ||||||
|  | 						GREEN: { | ||||||
|  | 							on: { SWITCH: 'YELLOW' } | ||||||
|  | 						}, | ||||||
|  | 						YELLOW: { | ||||||
|  | 							on: { SWITCH: 'RED' } | ||||||
|  | 						}, | ||||||
|  | 						RED: { | ||||||
|  | 							on: { SWITCH: 'GREEN' } | ||||||
|  | 						} | ||||||
|  | 					}, | ||||||
|  | 					on: { | ||||||
|  | 						READY: 'GREEN', | ||||||
|  | 						NOTREADY: 'RED' | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 		] | 		] | ||||||
| 	}; | 	}; | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
| 	import { dataStore } from '$lib/core/dataLoader'; | 	import { dataStore } from '$lib/core/dataLoader'; | ||||||
| 	import { createCompositeStore, getCompositeStore } from '$lib/core/compositeStores'; | 	import { createCompositeStore, getCompositeStore } from '$lib/core/compositeStores'; | ||||||
| 	import { coreServices } from './coreServices'; | 	import { coreServices } from './coreServices'; | ||||||
| 	import { Machine } from 'xstate'; | 	import { Machine, interpret } from 'xstate'; | ||||||
|  |  | ||||||
| 	interface ICompositeLayout { | 	interface ICompositeLayout { | ||||||
| 		areas: string; | 		areas: string; | ||||||
| @@ -35,6 +35,7 @@ | |||||||
| 		core: coreServices | 		core: coreServices | ||||||
| 	}; | 	}; | ||||||
| 	let layoutStyle = ''; | 	let layoutStyle = ''; | ||||||
|  | 	let machineService; | ||||||
|  |  | ||||||
| 	$: { | 	$: { | ||||||
| 		layoutStyle = computeLayoutStyle(composite?.layout); | 		layoutStyle = computeLayoutStyle(composite?.layout); | ||||||
| @@ -50,6 +51,33 @@ | |||||||
| 				mapAndSubscribe(child); | 				mapAndSubscribe(child); | ||||||
| 			}); | 			}); | ||||||
| 		} | 		} | ||||||
|  | 		if (composite?.machine) { | ||||||
|  | 			const machine = Machine(composite.machine); | ||||||
|  | 			machineService = interpret(machine).onTransition((state) => { | ||||||
|  | 				getCompositeStore(composite.id).update((storeValue) => ({ | ||||||
|  | 					...storeValue, | ||||||
|  | 					machine: { state: state.value } | ||||||
|  | 				})); | ||||||
|  | 			}); | ||||||
|  | 			machineService.start(); | ||||||
|  | 			loadedServices.machine = machineService; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (composite?.children) { | ||||||
|  | 			composite.children.forEach((child) => { | ||||||
|  | 				if (child.machine) { | ||||||
|  | 					const childMachine = Machine(child.machine); | ||||||
|  | 					machineService = interpret(childMachine).onTransition((state) => { | ||||||
|  | 						getCompositeStore(child.id).update((storeValue) => ({ | ||||||
|  | 							...storeValue, | ||||||
|  | 							machine: { state: state.value } | ||||||
|  | 						})); | ||||||
|  | 					}); | ||||||
|  | 					machineService.start(); | ||||||
|  | 					loadedServices.machine = machineService; | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	function computeLayoutStyle(layout?: ICompositeLayout): string { | 	function computeLayoutStyle(layout?: ICompositeLayout): string { | ||||||
|   | |||||||
| @@ -1,17 +1,18 @@ | |||||||
| // coreServices.ts | // coreServices.ts | ||||||
| import { getCompositeStore } from './compositeStores'; | import { getCompositeStore } from './compositeStores'; | ||||||
|  | import { interpret, Machine } from 'xstate'; | ||||||
|  |  | ||||||
| export const coreServices = { | export const coreServices = { | ||||||
|     // updateComposite: (mappings: Record<string, string>) => { |     updateComposite: (mappings: Record<string, string>) => { | ||||||
|     //     for (const [mappingString, value] of Object.entries(mappings)) { |         for (const [mappingString, value] of Object.entries(mappings)) { | ||||||
|     //         const [storeID, key] = mappingString.replace('@', '').split(':'); |             const [storeID, key] = mappingString.replace('@', '').split(':'); | ||||||
|     //         const store = getCompositeStore(storeID); |             const store = getCompositeStore(storeID); | ||||||
|     //         store.update(storeData => { |             store.update(storeData => { | ||||||
|     //             storeData[key] = value; |                 storeData[key] = value; | ||||||
|     //             return storeData; |                 return storeData; | ||||||
|     //         }); |             }); | ||||||
|     //     } |         } | ||||||
|     // }, |     }, | ||||||
|     subscribeComposite: (mappingString: string) => { |     subscribeComposite: (mappingString: string) => { | ||||||
|         const [storeID] = mappingString.replace('@', '').split(':'); |         const [storeID] = mappingString.replace('@', '').split(':'); | ||||||
|         const store = getCompositeStore(storeID); |         const store = getCompositeStore(storeID); | ||||||
| @@ -19,5 +20,16 @@ export const coreServices = { | |||||||
|     }, |     }, | ||||||
|     testAlert: () => { |     testAlert: () => { | ||||||
|         alert("core service alert") |         alert("core service alert") | ||||||
|  |     }, | ||||||
|  |     machine: { | ||||||
|  |         service: null, | ||||||
|  |         send: (event) => coreServices.machine.service.send(event), | ||||||
|  |         initialize: (machineDefinition, store) => { | ||||||
|  |             const machine = Machine(machineDefinition); | ||||||
|  |             coreServices.machine.service = interpret(machine).onTransition((state) => { | ||||||
|  |                 store.update(storeValue => ({ ...storeValue, machine: { state: state.value } })); | ||||||
|  |             }); | ||||||
|  |             coreServices.machine.service.start(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user