import NotiveElement, { customElement } from "../../element"; import h, { CreateElement } from "../../html"; import { ActiveCellSelection, RangeSelection } from "../../selection"; import "./index.css"; function getSelectedSubdivisionsCount(): number | undefined { const selection = window.notive.selection; if (!selection) return; if (selection instanceof ActiveCellSelection) { return 1; } if (!(selection instanceof RangeSelection)) return; const grid = window.notive.getGrid(selection.gridId); if (!grid) return; const selectedCells = selection.getSelectedCells(grid); return Math.min(...selectedCells.map((cells) => cells.length)); } @customElement("ntv-toolbar") class NotiveToolbarElement extends NotiveElement { #subdivisionsInputEl: HTMLInputElement = h.input({ title: "Subdivisions", placeholder: "-", disabled: true, }); connectedCallback() { this.#render(); window.addEventListener("ntv:selectionchange", () => { if (window.notive.pendingSelection) { this.#subdivisionsInputEl.disabled = true; this.#subdivisionsInputEl.value = ""; return; } const subdivisionsCount = getSelectedSubdivisionsCount(); if (!subdivisionsCount) { this.#subdivisionsInputEl.disabled = true; this.#subdivisionsInputEl.value = ""; return; } this.#subdivisionsInputEl.disabled = false; this.#subdivisionsInputEl.value = subdivisionsCount.toString(); }); this.#subdivisionsInputEl.addEventListener("change", () => { window.notive.subdivideSelection( parseInt(this.#subdivisionsInputEl.value), ); }); } #render() { this.append( h.section( h.button( { dataset: { variant: "icon" }, onclick: () => { const subdivisions = Math.max( 1, parseInt(this.#subdivisionsInputEl.value) - 1, ); this.#subdivisionsInputEl.value = subdivisions.toString(); window.notive.subdivideSelection(subdivisions); }, }, "-", ), this.#subdivisionsInputEl, h.button( { dataset: { variant: "icon" }, onclick: () => { const subdivisions = parseInt(this.#subdivisionsInputEl.value) + 1; this.#subdivisionsInputEl.value = subdivisions.toString(); window.notive.subdivideSelection(subdivisions); }, }, "+", ), ), h.section( h.button( { dataset: { variant: "menu" }, onclick: () => { this.#play(); }, }, "Play", ), ), ); } async #play() { const Tone = await import("tone"); await Tone.start(); const transport = Tone.getTransport(); transport.stop(); transport.position = 0; transport.cancel(); const synth = new Tone.Synth().toDestination(); const seq = new Tone.Sequence( (time, note) => { synth.triggerAttackRelease(note, 0.1, time); }, ["C4", "D4", "E4"], "1m", ).start(0); seq.loop = false; transport.start(); } } export default NotiveToolbarElement.makeFactory();