jevstrudel.git / packages / repl / repl-component.mjs
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}