import { html, css, LitElement } from "lit";
import { customElement, property, query } from "lit/decorators.js";
import { IOSMDOptions, OpenSheetMusicDisplay } from "opensheetmusicdisplay";
type BackendType = "svg" | "canvas";
type DrawingType = "compact" | "default";
@customElement("sheet-music")
export class SheetMusic extends LitElement {
_zoom = 1.0;
@property({ type: Boolean }) allowDrop = false;
@property() src = "";
@query("main") canvas!: HTMLElement;
controller?: OpenSheetMusicDisplay;
options: IOSMDOptions = {
autoResize: true,
backend: "canvas" as BackendType,
drawingParameters: "default" as DrawingType,
};
static styles = css`
main {
overflow-x: auto;
}
`;
render() {
return html``;
}
async renderMusic(content: string) {
if (!this.controller) return;
await this.controller.load(content);
this.controller.zoom = this._zoom;
this.controller.render();
this.requestUpdate();
}
private async getMusic(): Promise {
if (this.src.length > 0) return fetch(this.src).then((res) => res.text());
const elem = this.parentElement?.querySelector(
'script[type="text/xml"]'
) as HTMLScriptElement;
if (elem) return elem.innerHTML;
return "";
}
async firstUpdated() {
this.controller = new OpenSheetMusicDisplay(this.canvas, this.options);
this.requestUpdate();
const music = await this.getMusic();
if (music) this.renderMusic(music);
}
}
declare global {
interface HTMLElementTagNameMap {
"sheet-music": SheetMusic;
}
}