1import { silence } from '@strudel/core'; 2import { getDrawContext } from '@strudel/draw'; 3import { transpiler } from '@strudel/transpiler'; 4import { getAudioContext, webaudioOutput, initAudioOnFirstClick } from '@strudel/webaudio'; 5import { StrudelMirror, codemirrorSettings } from '@strudel/codemirror'; 6import { prebake } from './prebake.mjs'; 7 8if (typeof HTMLElement !== 'undefined') { 9 initAudioOnFirstClick(); 10 class StrudelRepl extends HTMLElement { 11 static observedAttributes = ['code']; 12 settings = codemirrorSettings.get(); 13 editor = null; 14 sync = false; 15 solo = true; 16 constructor() { 17 super(); 18 } 19 attributeChangedCallback(name, oldValue, newValue) { 20 if (name === 'code') { 21 this.code = newValue; 22 this.editor?.setCode(newValue); 23 } 24 } 25 connectedCallback() { 26 // setTimeout makes sure the dom is ready 27 setTimeout(() => { 28 const code = (this.innerHTML + '').replace('<!--', '').replace('-->', '').trim(); 29 if (code) { 30 // use comment code in element body if present 31 this.setAttribute('code', code); 32 } 33 }); 34 // use a separate container for the editor, to make sure the innerHTML stays as is 35 const container = document.createElement('div'); 36 this.parentElement.insertBefore(container, this.nextSibling); 37 const drawContext = getDrawContext(); 38 const drawTime = [-2, 2]; 39 this.editor = new StrudelMirror({ 40 defaultOutput: webaudioOutput, 41 getTime: () => getAudioContext().currentTime, 42 transpiler, 43 root: container, 44 initialCode: '// LOADING', 45 pattern: silence, 46 drawTime, 47 drawContext, 48 prebake, 49 onUpdateState: (state) => { 50 const event = new CustomEvent('update', { 51 detail: state, 52 }); 53 this.dispatchEvent(event); 54 }, 55 solo: this.solo, 56 sync: this.sync, 57 }); 58 // init settings 59 this.editor.updateSettings(this.settings); 60 this.editor.setCode(this.code); 61 } 62 // Element functionality written in here 63 } 64 65 customElements.define('strudel-editor', StrudelRepl); 66}