1- import { useState } from "react" ;
1+ import { useCallback , useState } from "react" ;
22import {
33 Petrinaut ,
44 defaultTokenTypes ,
55 type PetriNetDefinitionObject ,
66} from "@hashintel/petrinaut" ;
7- import { useHazelIntegration } from "./app/use-hazel-integration" ;
7+ import {
8+ useHazelIntegration ,
9+ type HazelValue ,
10+ } from "./app/use-hazel-integration" ;
811import { produce } from "immer" ;
12+ import type { MinimalNetMetadata , SimulationState } from "@hashintel/petrinaut" ;
913
1014const createDefaultNetDefinition = ( ) : PetriNetDefinitionObject => {
1115 return {
@@ -15,6 +19,8 @@ const createDefaultNetDefinition = (): PetriNetDefinitionObject => {
1519 } ;
1620} ;
1721
22+ const existingNets : MinimalNetMetadata [ ] = [ ] ;
23+
1824/**
1925 * An incomplete type guard to check if a value is a valid Petri net definition.
2026 * Does not check the content of arrays.
@@ -41,6 +47,22 @@ const isValidNetDefinition = (
4147 return true ;
4248} ;
4349
50+ /**
51+ * Hazel errors if sent an empty array at the root of an object value returned, e.g. { simulationState: [] }.
52+ */
53+ const stripEmptyTuple = (
54+ simulationState : SimulationState ,
55+ ) : HazelValue [ "simulationState" ] => {
56+ if (
57+ simulationState . length === 0 ||
58+ Object . keys ( simulationState [ 0 ] ) . length === 0
59+ ) {
60+ return undefined ;
61+ }
62+
63+ return simulationState ;
64+ } ;
65+
4466/**
4567 * Wraps Petrinaut with the event handlers necessary for a Hazel Livelit.
4668 */
@@ -50,6 +72,7 @@ export const App = () => {
5072
5173 const [ netDefinition , setNetDefinition ] =
5274 useState < PetriNetDefinitionObject | null > ( null ) ;
75+ const [ simulationState , setSimulationState ] = useState < SimulationState > ( [ ] ) ;
5376
5477 const { setSyntax } = useHazelIntegration ( {
5578 id,
@@ -60,57 +83,89 @@ export const App = () => {
6083 try {
6184 const parsedValue = JSON . parse ( value ) ;
6285
63- if ( isValidNetDefinition ( parsedValue ) ) {
64- setNetDefinition ( parsedValue ) ;
86+ if ( isValidNetDefinition ( parsedValue . netDefinition ) ) {
87+ setNetDefinition ( parsedValue . netDefinition ) ;
88+ setSimulationState ( parsedValue . simulationState ?? [ ] ) ;
6589 } else {
66- console . error ( "Invalid net definition" , parsedValue ) ;
90+ console . error ( "Invalid net definition" , parsedValue . netDefinition ) ;
6791 const defaultNetDefinition = createDefaultNetDefinition ( ) ;
6892 setNetDefinition ( defaultNetDefinition ) ;
69- setSyntax ( JSON . stringify ( defaultNetDefinition ) ) ;
93+
94+ setSyntax ( {
95+ netDefinition : defaultNetDefinition ,
96+ simulationState : stripEmptyTuple ( simulationState ) ,
97+ } ) ;
7098 }
7199 } catch ( error ) {
72100 console . error ( "Error parsing net definition as JSON" , error ) ;
73101 }
74102 } ,
75103 } ) ;
76104
105+ const reportSimulationState = useCallback (
106+ ( simulationState : SimulationState ) => {
107+ console . log ( "Simulation state reported" ) ;
108+ setSimulationState ( simulationState ) ;
109+
110+ setSyntax ( {
111+ netDefinition : netDefinition as PetriNetDefinitionObject ,
112+ simulationState : stripEmptyTuple ( simulationState ) ,
113+ } ) ;
114+ } ,
115+ [ netDefinition , setSyntax ] ,
116+ ) ;
117+
118+ const mutatePetriNetDefinition = useCallback (
119+ ( definitionMutationFn : ( definition : PetriNetDefinitionObject ) => void ) => {
120+ setNetDefinition ( ( existingDefinition ) => {
121+ const newDefinition = produce ( existingDefinition , definitionMutationFn ) ;
122+ setSyntax ( {
123+ netDefinition : newDefinition as PetriNetDefinitionObject ,
124+ simulationState : stripEmptyTuple ( simulationState ) ,
125+ } ) ;
126+ return newDefinition ;
127+ } ) ;
128+ } ,
129+ [ setSyntax , simulationState ] ,
130+ ) ;
131+
77132 if ( ! netDefinition ) {
133+ if ( typeof window !== "undefined" && window . self === window . top ) {
134+ return (
135+ < p style = { { padding : 15 } } >
136+ This application is designed to be run in an iFrame.
137+ </ p >
138+ ) ;
139+ }
78140 return null ;
79141 }
80142
81143 return (
82144 < Petrinaut
83145 key = { id }
84- hideNetManagementControls
146+ hideNetManagementControls = "includeLoadExampleOnly"
85147 petriNetId = { id }
86148 petriNetDefinition = { netDefinition }
87- existingNets = { [ ] }
88- mutatePetriNetDefinition = { ( definitionMutationFn ) => {
89- setNetDefinition ( ( existingDefinition ) => {
90- const newDefinition = produce (
91- existingDefinition ,
92- definitionMutationFn ,
93- ) ;
94-
95- setSyntax ( JSON . stringify ( newDefinition ) ) ;
96-
97- return newDefinition ;
98- } ) ;
99- } }
149+ existingNets = { existingNets }
150+ mutatePetriNetDefinition = { mutatePetriNetDefinition }
100151 parentNet = { null }
101- createNewNet = { ( ) => {
102- throw new Error (
103- "Petrinaut should not be attemping to create new nets when wrapped by Patchwork" ,
104- ) ;
152+ createNewNet = { ( { petriNetDefinition } ) => {
153+ setNetDefinition ( petriNetDefinition ) ;
154+ setSimulationState ( [ ] ) ;
155+ setSyntax ( {
156+ netDefinition : petriNetDefinition ,
157+ simulationState : undefined ,
158+ } ) ;
105159 } }
106160 loadPetriNet = { ( ) => {
107161 throw new Error (
108- "Petrinaut should not be attemping to load other nets when wrapped by Patchwork " ,
162+ "Petrinaut should not be attemping to load other nets when used as a Hazel livelit " ,
109163 ) ;
110164 } }
165+ reportSimulationState = { reportSimulationState }
111166 setTitle = { ( ) => {
112167 throw new Error (
113- "Petrinaut should not be attemping to set the net title when wrapped by Patchwork " ,
168+ "Petrinaut should not be attemping to set the net title when used as a Hazel livelit " ,
114169 ) ;
115170 } }
116171 title = { "" }
0 commit comments