import mermaid from 'https://unpkg.com/mermaid@9.2.2/dist/mermaid.esm.min.mjs'; import { Actor } from './actor.js'; import { Action } from './action.js'; import { debounce, hexToRGB } from '../util.js'; class MermaidDiagram { constructor(box, logBox) { this.box = box; this.container = this.box.addBox('Container'); this.element = this.box.addBox('Element'); this.renderBox = this.box.addBox('Render'); this.box.addBox('Spacer').setInnerHTML(' '); this.logBox = logBox; this.inSection = 0; } async log(msg, render = true) { this.logBox.addBox().setInnerHTML(msg).monospace(); if (render) { await this.render(); } return this; } async render() { const render = async () => { let innerText = this.logBox.getInnerText(); for (let i = 0; i < this.inSection; i++) { innerText += '\nend'; } const graph = await mermaid.mermaidAPI.render( this.element.getId(), innerText, ); this.renderBox.setInnerHTML(graph); }; await debounce(render, 100); } } export class Scene { constructor(name, rootBox) { this.name = name; this.box = rootBox.addBox(name); this.titleBox = this.box.addBox('Title').setInnerHTML(name); this.box.addBox('Spacer').setInnerHTML(' '); this.topSection = this.box.addBox('Top section').flex(); this.displayValuesBox = this.topSection.addBox('Values'); this.box.addBox('Spacer').setInnerHTML(' '); this.actors = new Set(); mermaid.mermaidAPI.initialize({ startOnLoad: false, theme: 'base', themeVariables: { darkMode: true, primaryColor: '#2a5b6c', primaryTextColor: '#b6b6b6', // lineColor: '#349cbd', lineColor: '#57747d', signalColor: '#57747d', // signalColor: '#349cbd', noteBkgColor: '#516f77', noteTextColor: '#cecece', activationBkgColor: '#1d3f49', activationBorderColor: '#569595', }, }); } withSequenceDiagram() { const box = this.box.addBox('Sequence diagram'); this.box.addBox('Spacer').setInnerHTML(' '); const logBox = this.box.addBox('Sequence diagram text'); this.sequence = new MermaidDiagram(box, logBox); this.sequence.log('sequenceDiagram', false); return this; } withFlowchart(direction = 'BT') { const box = this.topSection.addBox('Flowchart'); this.box.addBox('Spacer').setInnerHTML(' '); const logBox = this.box.addBox('Flowchart text'); this.flowchart = new MermaidDiagram(box, logBox); this.flowchart.log(`graph ${direction}`, false); return this; } async addActor(name) { const actor = new Actor(name, this); if (this.sequence) { await this.scene.sequence.log(`participant ${name}`); } return actor; } registerActor(actor) { this.actors.add(actor); } findActor(fn) { return Array.from(this.actors.values()).find(fn); } addAction(name) { const action = new Action(name, this); return action; } addDisplayValue(name) { const dv = this.displayValuesBox.addDisplayValue(name); return dv; } async deactivateAll() { for (const actor of this.actors.values()) { while (actor.active) { await actor.deactivate(); } } } async startSection(color = '#08252c') { const { r, g, b } = hexToRGB(color); this.sequence.inSection++; this.sequence.log(`rect rgb(${r}, ${g}, ${b})`, false); } async endSection() { this.sequence.inSection--; this.sequence.log('end'); } }