From b53fa1201c69b99f93199d944dd92323ef5f5f93 Mon Sep 17 00:00:00 2001 From: b-ma Date: Mon, 22 Jul 2024 08:10:36 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20@=20ircam-is?= =?UTF-8?q?mm/soap-score@2f6ca409a2f0a2b021db867bd8398e82935bfc4b=20?= =?UTF-8?q?=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build/index.js | 2 +- build/index.js.map | 2 +- node_modules/.package-lock.json | 8 ++++---- node_modules/@ircam/soap-score/package.json | 6 +++--- .../soap-score/src/components/SoapScoreEditor.js | 2 +- package-lock.json | 10 +++++----- package.json | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/build/index.js b/build/index.js index 0b5d1ea1..bae9b629 100644 --- a/build/index.js +++ b/build/index.js @@ -3809,7 +3809,7 @@ BAR 33 } :host sc-editor { - width: 99%; + width: 100%; flex: 1; } diff --git a/build/index.js.map b/build/index.js.map index 6f20d84f..60332074 100644 --- a/build/index.js.map +++ b/build/index.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../node_modules/@ircam/sc-utils/src/is-browser.js", "../node_modules/@ircam/sc-utils/src/is-touch-device.js", "../node_modules/@ircam/sc-utils/src/delay.js", "../node_modules/@ircam/sc-utils/src/sleep.js", "../node_modules/@ircam/sc-gettime/src/browser.js", "../node_modules/@ircam/sc-utils/src/get-time.js", "../node_modules/@ircam/sc-utils/src/is-function.js", "../node_modules/@ircam/sc-utils/src/is-number.js", "../node_modules/is-plain-obj/index.js", "../node_modules/@ircam/sc-utils/src/is-plain-object.js", "../node_modules/@ircam/sc-utils/src/is-string.js", "../node_modules/@ircam/sc-utils/src/is-typed-array.js", "../node_modules/@ircam/sc-utils/src/is-url.js", "../node_modules/@ircam/sc-utils/src/is-sequence.js", "../node_modules/@ircam/sc-utils/src/atodb.js", "../node_modules/@ircam/sc-utils/src/linear-to-decibel.js", "../node_modules/@ircam/sc-utils/src/power-to-decibel.js", "../node_modules/@ircam/sc-utils/src/dbtoa.js", "../node_modules/@ircam/sc-utils/src/decibel-to-linear.js", "../node_modules/@ircam/sc-utils/src/decibel-to-power.js", "../node_modules/@ircam/sc-utils/src/ftom.js", "../node_modules/@ircam/sc-utils/src/mtof.js", "../node_modules/@ircam/sc-utils/src/hertz-to-normalised.js", "../node_modules/@ircam/sc-utils/src/normalised-to-hertz.js", "../node_modules/@ircam/sc-utils/src/linear-scale.js", "../node_modules/@ircam/sc-utils/src/exponential-scale.js", "../node_modules/@ircam/sc-utils/src/logarithmic-scale.js", "../node_modules/@ircam/sc-utils/src/normalized-to-table-scale.js", "../node_modules/@ircam/sc-utils/src/table-to-normalized-scale.js", "../node_modules/@ircam/sc-utils/src/id-generator.js", "../node_modules/@ircam/sc-utils/src/index.js", "../node_modules/@ircam/sc-scheduling/src/utils.js", "../node_modules/@ircam/sc-scheduling/src/PriorityQueue.js", "../node_modules/@ircam/sc-scheduling/src/SchedulerEvent.js", "../node_modules/@ircam/sc-scheduling/src/Scheduler.js", "../node_modules/@ircam/sc-scheduling/src/TransportEvent.js", "../node_modules/@ircam/sc-scheduling/src/TransportEventQueue.js", "../node_modules/@ircam/sc-scheduling/src/Transport.js", "../node_modules/@ircam/sc-scheduling/src/index.js", "../node_modules/@lit/reactive-element/src/css-tag.ts", "../node_modules/@lit/reactive-element/src/reactive-element.ts", "../node_modules/lit-html/src/lit-html.ts", "../node_modules/lit-element/src/lit-element.ts", "../node_modules/lit/index.js", "../node_modules/lodash.clonedeep/index.js", "../node_modules/@ircam/soap-score/src/utils/regexp.js", "../node_modules/parse-duration/index.mjs", "../node_modules/@ircam/soap-score/src/utils/decompose-compound-beats.js", "../node_modules/@ircam/soap-score/src/utils/time-signatures.js", "../node_modules/@ircam/soap-score/src/soap-score-parser.js", "../node_modules/@ircam/soap-score/src/utils/memoize-last.js", "../node_modules/@ircam/soap-score/src/SoapScoreInterpreter.js", "../node_modules/lit-html/src/directive.ts", "../node_modules/lit-html/src/directive-helpers.ts", "../node_modules/lit-html/src/directives/repeat.ts", "../node_modules/lit/directives/repeat.js", "../node_modules/@ircam/sc-components/src/styles.js", "../node_modules/@ircam/sc-components/src/ScElement.js", "../node_modules/@ircam/sc-components/src/sc-select.js", "../node_modules/lit-html/src/directives/class-map.ts", "../node_modules/lit/directives/class-map.js", "../node_modules/@ircam/sc-components/src/mixins/midi-controlled.js", "../node_modules/@ircam/sc-components/src/controllers/keyboard-controller.js", "../node_modules/@ircam/sc-components/src/sc-bang.js", "../node_modules/@ircam/sc-components/src/sc-button.js", "../node_modules/@ircam/sc-components/src/sc-clock.js", "../node_modules/lit-html/src/directives/unsafe-html.ts", "../node_modules/lit/directives/unsafe-html.js", "../node_modules/highlight.js/lib/core.js", "../node_modules/highlight.js/lib/languages/1c.js", "../node_modules/highlight.js/lib/languages/abnf.js", "../node_modules/highlight.js/lib/languages/accesslog.js", "../node_modules/highlight.js/lib/languages/actionscript.js", "../node_modules/highlight.js/lib/languages/ada.js", "../node_modules/highlight.js/lib/languages/angelscript.js", "../node_modules/highlight.js/lib/languages/apache.js", "../node_modules/highlight.js/lib/languages/applescript.js", "../node_modules/highlight.js/lib/languages/arcade.js", "../node_modules/highlight.js/lib/languages/arduino.js", "../node_modules/highlight.js/lib/languages/armasm.js", "../node_modules/highlight.js/lib/languages/xml.js", "../node_modules/highlight.js/lib/languages/asciidoc.js", "../node_modules/highlight.js/lib/languages/aspectj.js", "../node_modules/highlight.js/lib/languages/autohotkey.js", "../node_modules/highlight.js/lib/languages/autoit.js", "../node_modules/highlight.js/lib/languages/avrasm.js", "../node_modules/highlight.js/lib/languages/awk.js", "../node_modules/highlight.js/lib/languages/axapta.js", "../node_modules/highlight.js/lib/languages/bash.js", "../node_modules/highlight.js/lib/languages/basic.js", "../node_modules/highlight.js/lib/languages/bnf.js", "../node_modules/highlight.js/lib/languages/brainfuck.js", "../node_modules/highlight.js/lib/languages/c.js", "../node_modules/highlight.js/lib/languages/cal.js", "../node_modules/highlight.js/lib/languages/capnproto.js", "../node_modules/highlight.js/lib/languages/ceylon.js", "../node_modules/highlight.js/lib/languages/clean.js", "../node_modules/highlight.js/lib/languages/clojure.js", "../node_modules/highlight.js/lib/languages/clojure-repl.js", "../node_modules/highlight.js/lib/languages/cmake.js", "../node_modules/highlight.js/lib/languages/coffeescript.js", "../node_modules/highlight.js/lib/languages/coq.js", "../node_modules/highlight.js/lib/languages/cos.js", "../node_modules/highlight.js/lib/languages/cpp.js", "../node_modules/highlight.js/lib/languages/crmsh.js", "../node_modules/highlight.js/lib/languages/crystal.js", "../node_modules/highlight.js/lib/languages/csharp.js", "../node_modules/highlight.js/lib/languages/csp.js", "../node_modules/highlight.js/lib/languages/css.js", "../node_modules/highlight.js/lib/languages/d.js", "../node_modules/highlight.js/lib/languages/markdown.js", "../node_modules/highlight.js/lib/languages/dart.js", "../node_modules/highlight.js/lib/languages/delphi.js", "../node_modules/highlight.js/lib/languages/diff.js", "../node_modules/highlight.js/lib/languages/django.js", "../node_modules/highlight.js/lib/languages/dns.js", "../node_modules/highlight.js/lib/languages/dockerfile.js", "../node_modules/highlight.js/lib/languages/dos.js", "../node_modules/highlight.js/lib/languages/dsconfig.js", "../node_modules/highlight.js/lib/languages/dts.js", "../node_modules/highlight.js/lib/languages/dust.js", "../node_modules/highlight.js/lib/languages/ebnf.js", "../node_modules/highlight.js/lib/languages/elixir.js", "../node_modules/highlight.js/lib/languages/elm.js", "../node_modules/highlight.js/lib/languages/ruby.js", "../node_modules/highlight.js/lib/languages/erb.js", "../node_modules/highlight.js/lib/languages/erlang-repl.js", "../node_modules/highlight.js/lib/languages/erlang.js", "../node_modules/highlight.js/lib/languages/excel.js", "../node_modules/highlight.js/lib/languages/fix.js", "../node_modules/highlight.js/lib/languages/flix.js", "../node_modules/highlight.js/lib/languages/fortran.js", "../node_modules/highlight.js/lib/languages/fsharp.js", "../node_modules/highlight.js/lib/languages/gams.js", "../node_modules/highlight.js/lib/languages/gauss.js", "../node_modules/highlight.js/lib/languages/gcode.js", "../node_modules/highlight.js/lib/languages/gherkin.js", "../node_modules/highlight.js/lib/languages/glsl.js", "../node_modules/highlight.js/lib/languages/gml.js", "../node_modules/highlight.js/lib/languages/go.js", "../node_modules/highlight.js/lib/languages/golo.js", "../node_modules/highlight.js/lib/languages/gradle.js", "../node_modules/highlight.js/lib/languages/graphql.js", "../node_modules/highlight.js/lib/languages/groovy.js", "../node_modules/highlight.js/lib/languages/haml.js", "../node_modules/highlight.js/lib/languages/handlebars.js", "../node_modules/highlight.js/lib/languages/haskell.js", "../node_modules/highlight.js/lib/languages/haxe.js", "../node_modules/highlight.js/lib/languages/hsp.js", "../node_modules/highlight.js/lib/languages/http.js", "../node_modules/highlight.js/lib/languages/hy.js", "../node_modules/highlight.js/lib/languages/inform7.js", "../node_modules/highlight.js/lib/languages/ini.js", "../node_modules/highlight.js/lib/languages/irpf90.js", "../node_modules/highlight.js/lib/languages/isbl.js", "../node_modules/highlight.js/lib/languages/java.js", "../node_modules/highlight.js/lib/languages/javascript.js", "../node_modules/highlight.js/lib/languages/jboss-cli.js", "../node_modules/highlight.js/lib/languages/json.js", "../node_modules/highlight.js/lib/languages/julia.js", "../node_modules/highlight.js/lib/languages/julia-repl.js", "../node_modules/highlight.js/lib/languages/kotlin.js", "../node_modules/highlight.js/lib/languages/lasso.js", "../node_modules/highlight.js/lib/languages/latex.js", "../node_modules/highlight.js/lib/languages/ldif.js", "../node_modules/highlight.js/lib/languages/leaf.js", "../node_modules/highlight.js/lib/languages/less.js", "../node_modules/highlight.js/lib/languages/lisp.js", "../node_modules/highlight.js/lib/languages/livecodeserver.js", "../node_modules/highlight.js/lib/languages/livescript.js", "../node_modules/highlight.js/lib/languages/llvm.js", "../node_modules/highlight.js/lib/languages/lsl.js", "../node_modules/highlight.js/lib/languages/lua.js", "../node_modules/highlight.js/lib/languages/makefile.js", "../node_modules/highlight.js/lib/languages/mathematica.js", "../node_modules/highlight.js/lib/languages/matlab.js", "../node_modules/highlight.js/lib/languages/maxima.js", "../node_modules/highlight.js/lib/languages/mel.js", "../node_modules/highlight.js/lib/languages/mercury.js", "../node_modules/highlight.js/lib/languages/mipsasm.js", "../node_modules/highlight.js/lib/languages/mizar.js", "../node_modules/highlight.js/lib/languages/perl.js", "../node_modules/highlight.js/lib/languages/mojolicious.js", "../node_modules/highlight.js/lib/languages/monkey.js", "../node_modules/highlight.js/lib/languages/moonscript.js", "../node_modules/highlight.js/lib/languages/n1ql.js", "../node_modules/highlight.js/lib/languages/nestedtext.js", "../node_modules/highlight.js/lib/languages/nginx.js", "../node_modules/highlight.js/lib/languages/nim.js", "../node_modules/highlight.js/lib/languages/nix.js", "../node_modules/highlight.js/lib/languages/node-repl.js", "../node_modules/highlight.js/lib/languages/nsis.js", "../node_modules/highlight.js/lib/languages/objectivec.js", "../node_modules/highlight.js/lib/languages/ocaml.js", "../node_modules/highlight.js/lib/languages/openscad.js", "../node_modules/highlight.js/lib/languages/oxygene.js", "../node_modules/highlight.js/lib/languages/parser3.js", "../node_modules/highlight.js/lib/languages/pf.js", "../node_modules/highlight.js/lib/languages/pgsql.js", "../node_modules/highlight.js/lib/languages/php.js", "../node_modules/highlight.js/lib/languages/php-template.js", "../node_modules/highlight.js/lib/languages/plaintext.js", "../node_modules/highlight.js/lib/languages/pony.js", "../node_modules/highlight.js/lib/languages/powershell.js", "../node_modules/highlight.js/lib/languages/processing.js", "../node_modules/highlight.js/lib/languages/profile.js", "../node_modules/highlight.js/lib/languages/prolog.js", "../node_modules/highlight.js/lib/languages/properties.js", "../node_modules/highlight.js/lib/languages/protobuf.js", "../node_modules/highlight.js/lib/languages/puppet.js", "../node_modules/highlight.js/lib/languages/purebasic.js", "../node_modules/highlight.js/lib/languages/python.js", "../node_modules/highlight.js/lib/languages/python-repl.js", "../node_modules/highlight.js/lib/languages/q.js", "../node_modules/highlight.js/lib/languages/qml.js", "../node_modules/highlight.js/lib/languages/r.js", "../node_modules/highlight.js/lib/languages/reasonml.js", "../node_modules/highlight.js/lib/languages/rib.js", "../node_modules/highlight.js/lib/languages/roboconf.js", "../node_modules/highlight.js/lib/languages/routeros.js", "../node_modules/highlight.js/lib/languages/rsl.js", "../node_modules/highlight.js/lib/languages/ruleslanguage.js", "../node_modules/highlight.js/lib/languages/rust.js", "../node_modules/highlight.js/lib/languages/sas.js", "../node_modules/highlight.js/lib/languages/scala.js", "../node_modules/highlight.js/lib/languages/scheme.js", "../node_modules/highlight.js/lib/languages/scilab.js", "../node_modules/highlight.js/lib/languages/scss.js", "../node_modules/highlight.js/lib/languages/shell.js", "../node_modules/highlight.js/lib/languages/smali.js", "../node_modules/highlight.js/lib/languages/smalltalk.js", "../node_modules/highlight.js/lib/languages/sml.js", "../node_modules/highlight.js/lib/languages/sqf.js", "../node_modules/highlight.js/lib/languages/sql.js", "../node_modules/highlight.js/lib/languages/stan.js", "../node_modules/highlight.js/lib/languages/stata.js", "../node_modules/highlight.js/lib/languages/step21.js", "../node_modules/highlight.js/lib/languages/stylus.js", "../node_modules/highlight.js/lib/languages/subunit.js", "../node_modules/highlight.js/lib/languages/swift.js", "../node_modules/highlight.js/lib/languages/taggerscript.js", "../node_modules/highlight.js/lib/languages/yaml.js", "../node_modules/highlight.js/lib/languages/tap.js", "../node_modules/highlight.js/lib/languages/tcl.js", "../node_modules/highlight.js/lib/languages/thrift.js", "../node_modules/highlight.js/lib/languages/tp.js", "../node_modules/highlight.js/lib/languages/twig.js", "../node_modules/highlight.js/lib/languages/typescript.js", "../node_modules/highlight.js/lib/languages/vala.js", "../node_modules/highlight.js/lib/languages/vbnet.js", "../node_modules/highlight.js/lib/languages/vbscript.js", "../node_modules/highlight.js/lib/languages/vbscript-html.js", "../node_modules/highlight.js/lib/languages/verilog.js", "../node_modules/highlight.js/lib/languages/vhdl.js", "../node_modules/highlight.js/lib/languages/vim.js", "../node_modules/highlight.js/lib/languages/wasm.js", "../node_modules/highlight.js/lib/languages/wren.js", "../node_modules/highlight.js/lib/languages/x86asm.js", "../node_modules/highlight.js/lib/languages/xl.js", "../node_modules/highlight.js/lib/languages/xquery.js", "../node_modules/highlight.js/lib/languages/zephir.js", "../node_modules/highlight.js/lib/index.js", "../node_modules/highlight.js/es/index.js", "../node_modules/@ircam/sc-components/src/sc-code-example.js", "../node_modules/@ircam/sc-components/src/sc-color-picker.js", "../node_modules/number-precision/build/index.es.js", "../node_modules/@ircam/sc-components/src/sc-speed-surface.js", "../node_modules/@ircam/sc-components/src/sc-dial.js", "../node_modules/lit/directives/if-defined.js", "../node_modules/@ircam/sc-components/src/sc-position-surface.js", "../node_modules/@ircam/sc-components/src/sc-dots.js", "../node_modules/@ircam/sc-components/src/sc-dragndrop.js", "../node_modules/@codemirror/state/dist/index.js", "../node_modules/style-mod/src/style-mod.js", "../node_modules/w3c-keyname/index.js", "../node_modules/@codemirror/view/dist/index.js", "../node_modules/@lezer/common/dist/index.js", "../node_modules/@lezer/highlight/dist/index.js", "../node_modules/@codemirror/language/dist/index.js", "../node_modules/@codemirror/commands/dist/index.js", "../node_modules/@lezer/lr/dist/index.js", "../node_modules/@lezer/javascript/dist/index.js", "../node_modules/@codemirror/autocomplete/dist/index.js", "../node_modules/@codemirror/lang-javascript/dist/index.js", "../node_modules/@lezer/html/dist/index.js", "../node_modules/@lezer/css/dist/index.js", "../node_modules/@codemirror/lang-css/dist/index.js", "../node_modules/@codemirror/lang-html/dist/index.js", "../node_modules/@lezer/json/dist/index.js", "../node_modules/@codemirror/lang-json/dist/index.js", "../node_modules/@lezer/markdown/dist/index.js", "../node_modules/@codemirror/lang-markdown/dist/index.js", "../node_modules/@lezer/yaml/dist/index.js", "../node_modules/@codemirror/lang-yaml/dist/index.js", "../node_modules/@babel/runtime/helpers/esm/extends.js", "../node_modules/@uiw/codemirror-themes/esm/index.js", "../node_modules/@uiw/codemirror-theme-monokai/esm/color.js", "../node_modules/@uiw/codemirror-theme-monokai/esm/index.js", "../node_modules/crelt/index.js", "../node_modules/@codemirror/search/dist/index.js", "../node_modules/@codemirror/lint/dist/index.js", "../node_modules/@replit/codemirror-vscode-keymap/dist/index.js", "../node_modules/@ircam/sc-components/src/utils/icons.js", "../node_modules/@ircam/sc-components/src/sc-icon.js", "../node_modules/@ircam/sc-components/src/sc-editor.js", "../node_modules/@ircam/sc-components/src/utils/sc-context-menu.js", "../node_modules/@ircam/sc-components/src/sc-text.js", "../node_modules/@ircam/sc-components/src/sc-filetree.js", "../node_modules/@ircam/sc-components/src/sc-number.js", "../node_modules/@ircam/sc-components/src/sc-filter.js", "../node_modules/@ircam/sc-components/src/sc-flash.js", "../node_modules/@ircam/sc-components/src/sc-fullscreen.js", "../node_modules/lit-html/src/directives/range.ts", "../node_modules/lit/directives/range.js", "../node_modules/lit-html/src/directives/map.ts", "../node_modules/lit/directives/map.js", "../node_modules/@ircam/sc-components/src/controllers/enter-exit-controller.js", "../node_modules/@ircam/sc-components/src/sc-io-surface.js", "../node_modules/@ircam/sc-components/src/sc-keyboard.js", "../node_modules/@ircam/sc-components/src/sc-loop.js", "../node_modules/@ircam/sc-components/src/sc-matrix.js", "../node_modules/@ircam/sc-components/src/sc-midi.js", "../node_modules/@ircam/sc-components/src/sc-modal.js", "../node_modules/@ircam/sc-components/src/sc-next.js", "../node_modules/@ircam/sc-components/src/sc-prev.js", "../node_modules/@ircam/sc-components/src/sc-separator.js", "../node_modules/@ircam/sc-components/src/sc-slider.js", "../node_modules/@ircam/sc-components/src/sc-tab.js", "../node_modules/@ircam/sc-components/src/sc-toggle.js", "../node_modules/@ircam/sc-components/src/sc-radio.js", "../node_modules/@ircam/sc-components/src/sc-record.js", "../node_modules/@ircam/sc-components/src/sc-signal.js", "../node_modules/@ircam/sc-components/src/sc-status.js", "../node_modules/@ircam/sc-components/src/sc-switch.js", "../node_modules/@ircam/sc-components/src/sc-table.js", "../node_modules/@ircam/sc-components/src/sc-transport.js", "../node_modules/@ircam/sc-components/src/sc-tap-tempo.js", "../node_modules/@ircam/sc-components/src/sc-waveform.js", "../node_modules/@ircam/sc-components/src/index.js", "../node_modules/@ircam/soap-score/src/components/SoapTransportControl.js", "../node_modules/@ircam/soap-score/src/components/utils/MetronomeRenderer.js", "../node_modules/@ircam/soap-score/src/components/SoapMetronomeRenderer.js", "../node_modules/@ircam/soap-score/src/components/SoapFlashBeatRenderer.js", "../node_modules/@ircam/soap-score/src/components/SoapScoreLocationRenderer.js", "../node_modules/vexflow/build/esm/src/util.js", "../node_modules/vexflow/build/esm/src/fraction.js", "../node_modules/vexflow/build/esm/src/boundingbox.js", "../node_modules/vexflow/build/esm/src/boundingboxcomputation.js", "../node_modules/vexflow/build/esm/src/font.js", "../node_modules/vexflow/build/esm/src/registry.js", "../node_modules/vexflow/build/esm/src/element.js", "../node_modules/vexflow/build/esm/src/tables.js", "../node_modules/vexflow/build/esm/src/glyph.js", "../node_modules/vexflow/build/esm/src/modifier.js", "../node_modules/vexflow/build/esm/src/music.js", "../node_modules/vexflow/build/esm/src/typeguard.js", "../node_modules/vexflow/build/esm/src/accidental.js", "../node_modules/vexflow/build/esm/src/stem.js", "../node_modules/vexflow/build/esm/src/textformatter.js", "../node_modules/vexflow/build/esm/src/annotation.js", "../node_modules/vexflow/build/esm/src/articulation.js", "../node_modules/vexflow/build/esm/src/rendercontext.js", "../node_modules/vexflow/build/esm/src/tickable.js", "../node_modules/vexflow/build/esm/src/note.js", "../node_modules/vexflow/build/esm/src/stavemodifier.js", "../node_modules/vexflow/build/esm/src/stavebarline.js", "../node_modules/vexflow/build/esm/src/barnote.js", "../node_modules/vexflow/build/esm/src/beam.js", "../node_modules/vexflow/build/esm/src/bend.js", "../node_modules/vexflow/build/esm/src/web.js", "../node_modules/vexflow/build/esm/src/canvascontext.js", "../node_modules/vexflow/build/esm/src/chordsymbol.js", "../node_modules/vexflow/build/esm/src/clef.js", "../node_modules/vexflow/build/esm/src/clefnote.js", "../node_modules/vexflow/build/esm/src/tickcontext.js", "../node_modules/vexflow/build/esm/src/crescendo.js", "../node_modules/vexflow/build/esm/src/curve.js", "../node_modules/vexflow/build/esm/src/dot.js", "../node_modules/vexflow/build/esm/src/frethandfinger.js", "../node_modules/vexflow/build/esm/src/parser.js", "../node_modules/vexflow/build/esm/src/easyscore.js", "../node_modules/vexflow/build/esm/src/notehead.js", "../node_modules/vexflow/build/esm/src/stemmablenote.js", "../node_modules/vexflow/build/esm/src/stavenote.js", "../node_modules/vexflow/build/esm/src/stavetie.js", "../node_modules/vexflow/build/esm/src/tabtie.js", "../node_modules/vexflow/build/esm/src/voice.js", "../node_modules/vexflow/build/esm/src/gracenotegroup.js", "../node_modules/vexflow/build/esm/src/notesubgroup.js", "../node_modules/vexflow/build/esm/src/ornament.js", "../node_modules/vexflow/build/esm/src/parenthesis.js", "../node_modules/vexflow/build/esm/src/svgcontext.js", "../node_modules/vexflow/build/esm/src/renderer.js", "../node_modules/vexflow/build/esm/src/stringnumber.js", "../node_modules/vexflow/build/esm/src/strokes.js", "../node_modules/vexflow/build/esm/src/vibrato.js", "../node_modules/vexflow/build/esm/src/modifiercontext.js", "../node_modules/vexflow/build/esm/src/keysignature.js", "../node_modules/vexflow/build/esm/src/staverepetition.js", "../node_modules/vexflow/build/esm/src/stavesection.js", "../node_modules/vexflow/build/esm/src/stavetempo.js", "../node_modules/vexflow/build/esm/src/textnote.js", "../node_modules/vexflow/build/esm/src/stavetext.js", "../node_modules/vexflow/build/esm/src/stavevolta.js", "../node_modules/vexflow/build/esm/src/timesigglyph.js", "../node_modules/vexflow/build/esm/src/timesignature.js", "../node_modules/vexflow/build/esm/src/stave.js", "../node_modules/vexflow/build/esm/src/staveconnector.js", "../node_modules/vexflow/build/esm/src/formatter.js", "../node_modules/vexflow/build/esm/src/ghostnote.js", "../node_modules/vexflow/build/esm/src/glyphnote.js", "../node_modules/vexflow/build/esm/src/gracenote.js", "../node_modules/vexflow/build/esm/src/keysignote.js", "../node_modules/vexflow/build/esm/src/multimeasurerest.js", "../node_modules/vexflow/build/esm/src/pedalmarking.js", "../node_modules/vexflow/build/esm/src/repeatnote.js", "../node_modules/vexflow/build/esm/src/staveline.js", "../node_modules/vexflow/build/esm/src/system.js", "../node_modules/vexflow/build/esm/src/tabnote.js", "../node_modules/vexflow/build/esm/src/tabstave.js", "../node_modules/vexflow/build/esm/src/textbracket.js", "../node_modules/vexflow/build/esm/src/textdynamics.js", "../node_modules/vexflow/build/esm/src/timesignote.js", "../node_modules/vexflow/build/esm/src/tuplet.js", "../node_modules/vexflow/build/esm/src/vibratobracket.js", "../node_modules/vexflow/build/esm/src/factory.js", "../node_modules/vexflow/build/esm/src/gracetabnote.js", "../node_modules/vexflow/build/esm/src/keymanager.js", "../node_modules/vexflow/build/esm/src/stavehairpin.js", "../node_modules/vexflow/build/esm/src/tabslide.js", "../node_modules/vexflow/build/esm/src/tremolo.js", "../node_modules/vexflow/build/esm/src/tuning.js", "../node_modules/vexflow/build/esm/src/version.js", "../node_modules/vexflow/build/esm/src/flow.js", "../node_modules/vexflow/build/esm/src/fonts/bravura_glyphs.js", "../node_modules/vexflow/build/esm/src/fonts/common_metrics.js", "../node_modules/vexflow/build/esm/src/fonts/load_bravura.js", "../node_modules/vexflow/build/esm/src/fonts/custom_glyphs.js", "../node_modules/vexflow/build/esm/src/fonts/load_custom.js", "../node_modules/vexflow/build/esm/src/fonts/gonville_glyphs.js", "../node_modules/vexflow/build/esm/src/fonts/load_gonville.js", "../node_modules/vexflow/build/esm/src/fonts/leland_glyphs.js", "../node_modules/vexflow/build/esm/src/fonts/load_leland.js", "../node_modules/vexflow/build/esm/src/fonts/petaluma_glyphs.js", "../node_modules/vexflow/build/esm/src/fonts/load_petaluma.js", "../node_modules/vexflow/build/esm/src/fonts/load_all.js", "../node_modules/vexflow/build/esm/src/fonts/petalumascript_glyphs.js", "../node_modules/vexflow/build/esm/src/fonts/robotoslab_glyphs.js", "../node_modules/vexflow/build/esm/src/fonts/sans_bold_text_metrics.js", "../node_modules/vexflow/build/esm/src/fonts/sans_text_metrics.js", "../node_modules/vexflow/build/esm/src/fonts/serif_text_metrics.js", "../node_modules/vexflow/build/esm/src/fonts/textfonts.js", "../node_modules/vexflow/build/esm/src/vex.js", "../node_modules/vexflow/build/esm/src/index.js", "../node_modules/vexflow/build/esm/entry/vexflow.js", "../node_modules/@ircam/soap-score/src/components/SoapStaveRenderer.js", "../node_modules/@ircam/soap-score/src/utils/fixtures.js", "../node_modules/@ircam/soap-score/src/components/SoapScoreExamples.js", "../node_modules/@ircam/soap-score/src/components/SoapScoreGenerator.js", "../node_modules/@ircam/soap-score/src/components/SoapScoreEditor.js", "../node_modules/midi-parser-js/src/main.js", "../node_modules/lodash.isequal/index.js", "../node_modules/@ircam/soap-score/src/soap-score-writer.js", "../node_modules/@ircam/soap-score/src/parsers/midi2soap.js", "../node_modules/lodash.chunk/index.js", "../node_modules/@ircam/soap-score/src/parsers/augustin2soap.js", "../node_modules/@ircam/soap-score/src/components/SoapScoreImport.js", "../node_modules/audiobuffer-to-wav/index.js", "../node_modules/@ircam/soap-score/src/parsers/soap2asco.js", "../node_modules/@ircam/soap-score/src/components/SoapScoreExport.js", "../src/layouts/_conductor.js", "../src/layouts/_mobile.js", "../node_modules/@ircam/soap-score/src/components/utils/soap-chenillard.js", "../node_modules/@ircam/soap-score/src/components/utils/soap-progress-bar.js", "../node_modules/@ircam/soap-score/src/components/SoapProgressBeatRenderer.js", "../src/layouts/default.js", "../node_modules/@ircam/sc-loader/src/browser.js", "../node_modules/@ircam/sc-loader/src/AudioBufferLoader.js", "../src/App.js", "../src/index.js"], - "sourcesContent": ["// https://stackoverflow.com/questions/17575790/environment-detection-node-js-or-browser\n\n/**\n * Check if the platform is a browser or a node process\n * @return {boolean}\n * @example\n * import { isBrowser } from '@ircam/sc-utils';\n * isBrowser();\n * // > true|false\n */\nexport const isBrowser = new Function('try {return this===window;}catch(e){ return false;}');\n", "import { isBrowser } from './is-browser.js';\n\n/**\n * Check if the device supports touch events\n * @return {boolean}\n * @example\n * import { isTouchDevice } from '@ircam/sc-utils';\n * isTouchDevice();\n * // > true|false\n */\nexport function isTouchDevice() {\n if (!isBrowser()) {\n return false;\n }\n\n return (('ontouchstart' in window) ||\n (navigator.maxTouchPoints > 0) ||\n (navigator.msMaxTouchPoints > 0));\n}\n", "/**\n * Wait for a given number of milliseconds.\n *\n * See also `sleep`\n *\n * @param {Number} ms - Number of milliseconds to wait\n * @return {Promise}\n * @example\n * import { delay } from '@ircam/sc-utils';\n * // wait for 1 second\n * await delay(1000);\n */\nexport function delay(ms) {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n", "/**\n * Wait for a given number of seconds.\n *\n * See also `delay`\n *\n * @param {Number} sec - Number of seconds to wait\n * @return {Promise}\n * @example\n * import { sleep } from '@ircam/sc-utils';\n * // wait for 1 second\n * await sleep(1);\n */\nexport function sleep(sec) {\n return new Promise(resolve => setTimeout(resolve, sec * 1000));\n}\n\n", "// see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now\n// see: https://developer.mozilla.org/en-US/docs/Web/API/Performance/now\nconst usePerf = (globalThis.performance && globalThis.performance.now);\nconst start = usePerf ? performance.now() : Date.now();\n\nif (!globalThis.crossOriginIsolated) {\n // console.info('> self.crossOriginIsolated', globalThis.crossOriginIsolated || false);\n console.warn(`[@ircam/sc-gettime] Your page is not Cross Origin Isolated. The accuracy of the clock may be reduced by the User-Agent to prevent finger-printing\n(see: https://web.dev/coop-coep/ for more informations)`);\n}\n\nexport function getTime() {\n if (usePerf) {\n const now = performance.now();\n const delta = now - start;\n return delta * 1e-3;\n } else {\n const now = Date.now();\n const delta = now - start;\n return delta * 1e-3;\n }\n}\n", "/**\n * Provide a unified clock in seconds accross platforms, with an origin defined by\n * the start of the process.\n *\n * @example\n * import { getTime } from '@ircam/sc-utils';\n *\n * setInterval(() => {\n * const now = getTime();\n * // ...\n * }, 1000)\n */\nexport { getTime } from '@ircam/sc-gettime';\n", "/**\n * Check if the value is a function\n * @param {*} val - Value to check\n * @return {boolean}\n * @example\n * import { isFunction } from '@ircam/sc-utils';\n * isFunction(() => {});\n * // > true\n */\nexport function isFunction(val) {\n return Object.prototype.toString.call(val) == '[object Function]' ||\n Object.prototype.toString.call(val) == '[object AsyncFunction]';\n}\n\n", "/**\n * Check if the value is a number, including Infinity.\n * If you want to excluse Infinity, check the native Number.isFinite function\n * @param {*} val - Value to check\n * @return {boolean}\n * @example\n * import { isNumber } from '@ircam/sc-utils';\n * isNumber(42);\n * // > true\n */\nexport function isNumber(val) {\n return Number(val) === val;\n}\n", "export default function isPlainObject(value) {\n\tif (typeof value !== 'object' || value === null) {\n\t\treturn false;\n\t}\n\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in value) && !(Symbol.iterator in value);\n}\n", "import isPlainObj from 'is-plain-obj';\n\n/**\n * Check if the value is a Plain Old Javascript Object (POJO)\n * @param {*} val - Value to check\n * @return {boolean}\n * @example\n * import { isPlainObject } from '@ircam/sc-utils';\n * isPlainObject({ a: 1 });\n * // > true\n */\nexport function isPlainObject(val) {\n return isPlainObj(val);\n}\n", "/**\n * Check if the value is a string\n * @param {*} val - Value to check\n * @return {boolean}\n * @example\n * import { isString } from '@ircam/sc-utils';\n * isString('test');\n * // > true\n */\nexport function isString(val) {\n return (typeof val === 'string' || val instanceof String);\n}\n", "/**\n * Check if the value is a TypedArray\n * @param {*} val - Value to check\n * @return {boolean}\n * @example\n * import { isTypedArray } from '@ircam/sc-utils';\n * isTypedArray(new Float32Array([1, 2, 3]));\n * // > true\n */\nexport function isTypedArray(val) {\n return (\n val instanceof Int8Array\n || val instanceof Int16Array\n || val instanceof Int32Array\n || val instanceof Uint8Array\n || val instanceof Uint8ClampedArray\n || val instanceof Uint16Array\n || val instanceof Uint32Array\n || val instanceof Float32Array\n || val instanceof Float64Array\n )\n}\n", "/**\n * Check if the value is a valid URL\n * @param {*} val - Value to check\n * @return {boolean}\n * @example\n * import { isURL } from '@ircam/sc-utils';\n * isURL('http://sub.my-site.org/abcd?test=123');\n * // > true\n */\nexport function isURL(url) {\n try {\n new URL(url);\n return true;\n } catch (err) {\n return false;\n }\n}\n\n", "import { isTypedArray } from './is-typed-array.js';\n\n/**\n * Check if the value is a sequence (`Array` or `TypedArray`) of finite numbers\n * @param {any} val - Value to check\n * @return {boolean}\n * @example\n * import { isSequence } from '@ircam/sc-utils';\n * isSequence([1, 2, 3]);\n * // > true\n */\nexport function isSequence(val) {\n if (!isTypedArray(val) && !Array.isArray(val)) {\n return false;\n }\n\n for (let i = 0; i < val.length; i++) {\n if (!Number.isFinite(val[i])) {\n return false;\n }\n }\n\n return true;\n}\n", "/**\n * Convert a linear gain into dB\n *\n * _Alias:_ `linearToDecibel`\n *\n * @param {number} val - Value to convert\n * @return {number}\n * @example\n * import { atodb } from '@ircam/sc-utils';\n * atodb(0);\n * // > 1\n */\nexport function atodb(val) {\n return 8.685889638065035 * Math.log(val); // 20 * log10(val);\n}\n", "import { atodb } from './atodb.js';\n\n/**\n * Convert a linear gain into dB\n *\n * _Alias:_ `atodb`\n *\n * @param {number} val - Value to convert\n * @return {number}\n * @example\n * import { decibelToPower } from '@ircam/sc-utils';\n * decibelToPower(0);\n * // > 1\n */\nexport function linearToDecibel(val) {\n return atodb(atodb);\n}\n", "/**\n * Convert a linear gain into dB\n * @param {number} val - Value to convert\n * @return {number}\n * @example\n * import { decibelToPower } from '@ircam/sc-utils';\n * decibelToPower(0);\n * // > 1\n */\nexport function powerToDecibel(val) {\n return 4.3429448190325175 * Math.log(val); // 10 * log10(val)\n}\n\n", "/**\n * Convert a dB into linear gain\n *\n * _Alias:_ `decibelToLinear`\n *\n * @param {number} val - Value to convert\n * @return {number}\n * @example\n * import { dbtoa } from '@ircam/sc-utils';\n * dbtoa(0);\n * // > 1\n */\nexport function dbtoa(val) {\n return Math.exp(0.11512925464970229 * val); // pow(10, val / 20)\n}\n", "import { dbtoa } from './dbtoa.js';\n\n/**\n * Convert a dB into linear gain (i.e. gain)\n *\n * _Alias:_ `dbtoa`\n *\n * @param {number} val - Value to convert\n * @return {number}\n * @example\n * import { decibelToLinear } from '@ircam/sc-utils';\n * decibelToLinear(0);\n * // > 1\n */\nexport function decibelToLinear(val) {\n return dbtoa(val); // pow(10, val / 20)\n}\n\n", "/**\n * Convert a dB into power gain\n *\n * @param {number} val - Value to convert\n * @return {number}\n * @example\n * import { decibelToPower } from '@ircam/sc-utils';\n * decibelToPower(0);\n * // > 1\n */\nexport function decibelToPower(val) {\n return Math.exp(0.23025850929940458 * val); // pow(10, val / 10)\n}\n\n", "/**\n * Convert a frequency in Hz to a MIDI note\n *\n * @param {number} freq - Frequency to convert\n * @return {number}\n * @example\n * import { ftom } from '@ircam/sc-utils';\n * const freq = ftom(440);\n * // > 69\n */\nexport function ftom(freq) {\n // https://www.music.mcgill.ca/~gary/307/week1/node28.html\n return 12 * (Math.log(freq / 220) / Math.log(2)) + 57;\n}\n\n", "/**\n * Convert a MIDI note to frequency\n * @param {number} midiNote - MIDI Note to convert\n * @return {number}\n * @example\n * import { mtof } from '@ircam/sc-utils';\n * const freq = mtof(69);\n * // > 440\n */\nexport function mtof(midiNote) {\n // https://www.music.mcgill.ca/~gary/307/week1/node28.html\n return 440 * Math.pow(2, (midiNote - 69) / 12);\n}\n", "/**\n * Convert a frequency in Hertz to a normalised one in [0, 1].\n *\n * Normalised frequency of 1 is half the sample-rate (Nyquist frequency).\n *\n * @param {number} frequencyHertz - Frequency in Hertz to convert\n * @param {number} sampleRate - Twice the Nyquist frequency\n * @return {number}\n * @example\n * import { hertzToNormalised } from '@ircam/sc-utils';\n * hertzToNormalised(12000, {sampleRate: 48000});\n * // > 0.5\n */\nexport function hertzToNormalised(frequencyHertz, {\n sampleRate = 2, // normalised\n} = {}) {\n return frequencyHertz * 2 / sampleRate;\n}\n", "/**\n * Convert a normalised frequency, in [0, 1], to a frequency in Hertz.\n *\n * Normalised frequency of 1 is half the sample-rate (Nyquist frequency).\n *\n * @param {number} frequencyNormalised - Normalised frequency to convert\n * @param {number} sampleRate - Twice the Nyquist frequency\n * @return {number}\n * @example\n * import { normalisedToHertz } from '@ircam/sc-utils';\n * normalisedToHertz(0.5, {sampleRate: 48000});\n * // > 12000\n */\nexport function normalisedToHertz(frequencyNormalised, {\n sampleRate = 2, // normalised\n} = {}) {\n return frequencyNormalised * sampleRate * 0.5;\n}\n", "/**\n * Create a linear scale function.\n *\n * @param {number} inputStart - Start value of input range\n * @param {number} inputEnd - End value of input range\n * @param {number} outputStart - Start value of output range\n * @param {number} outputEnd - End value of output range\n * @param {boolean} [clip=false] - Clip output to output range, default to `false`\n * @return {Function}\n * \n * @example\n * import { scale } from '@ircam/sc-utils';\n * const myScale = scale(0, 1, 50, 100);\n * myScale(0.5);\n * // > 75\n */\nexport function linearScale(inputStart, inputEnd, outputStart, outputEnd, clip = false) {\n const a = (outputEnd - outputStart) / (inputEnd - inputStart);\n const b = outputStart - a * inputStart;\n\n if (!clip) {\n return x => a * x + b;\n } else {\n const upperBound = Math.max(outputStart, outputEnd);\n const lowerBound = Math.min(outputStart, outputEnd);\n\n return x => {\n const y = a * x + b;\n return Math.max(lowerBound, Math.min(upperBound, y));\n };\n }\n}\n", "/**\n * Create an exponential scale function.\n *\n * @param {number} inputStart - Start value of input range\n * @param {number} inputEnd - End value of input range\n * @param {number} outputStart - Start value of output range\n * @param {number} outputEnd - End value of output range\n * @param {number} [base=2] - Base value for exponential scaling, default to `2`\n * @param {boolean} [clip=false] - Clip output to output range, default to `false`\n *\n * @example\n * const { exponentialScale } = utils;\n * const midiToFreq = exponentialScale(69, 81, 440, 880);\n * midiToFreq(57);\n * // > 220\n */\nexport function exponentialScale(inputStart, inputEnd, outputStart, outputEnd, base = 2, clip = false) {\n base = Math.max(0, base);\n\n const inputRange = inputEnd - inputStart;\n const outputRange = outputEnd - outputStart;\n const inputMin = Math.min(inputStart, inputEnd);\n const inputMax = Math.max(inputStart, inputEnd);\n const logBase = Math.log(base);\n\n return value => {\n if (inputRange === 0 || outputRange === 0) {\n return value <= inputMin ? outputStart : outputEnd;\n }\n\n const input = clip ? Math.max(inputMin, Math.min(inputMax, value)) : value;\n\n return outputStart + outputRange\n * (Math.exp(logBase * (input - inputStart) / inputRange) - 1)\n / (base - 1);\n }\n}\n", "/**\n * Create a logarithmic scale function.\n *\n * @param {number} inputStart - Start value of input range\n * @param {number} inputEnd - End value of input range\n * @param {number} outputStart - Start value of output range\n * @param {number} outputEnd - End value of output range\n * @param {number} [base=2] - Base value for exponential scaling, default to `2`\n * @param {boolean} [clip=false] - Clip output to output range, default to `false`\n *\n * @example\n * const { exponentialScale } = utils;\n * const freqToMidi = exponentialScale(69, 81, 440, 880);\n * freqToMidi(220);\n * // > 57\n */\nexport function logarithmicScale(inputStart, inputEnd, outputStart, outputEnd, base = 2, clip = false) {\n base = Math.max(0, base);\n\n const inputRange = inputEnd - inputStart;\n const outputRange = outputEnd - outputStart;\n const inputMin = Math.min(inputStart, inputEnd);\n const inputMax = Math.max(inputStart, inputEnd);\n const logBase = Math.log(base);\n\n return value => {\n if (inputRange === 0 || outputRange === 0) {\n return value <= inputMin ? outputStart : outputEnd;\n }\n\n const input = clip ? Math.max(inputMin, Math.min(inputMax, value)) : value;\n\n return outputStart + outputRange\n * Math.log((base - 1) * (input - inputStart) / inputRange + 1)\n / logBase;\n }\n}\n\n", "import { isSequence } from './is-sequence.js';\n\n/**\n * Create a scale function that returns a linearly interpolated value from the given \n * transfert table according to the given normalized position.\n *\n * @param {number[]} transfertTable - Sequence of finite numbers to use as lookup table\n * @return {function}\n *\n * @example\n * import { normalizedToTableScale } from '@ircam/sc-utils'\n * const scale = normalizedToTableScale([1, 2, 4])\n * scale(0); // 1\n * scale(0.25); // 1.5\n * scale(0.5); // 2\n * scale(0.75); // 3\n * scale(1); // 4\n */\nexport function normalizedToTableScale(transfertTable) {\n if (!isSequence(transfertTable)) {\n throw new TypeError(`Cannot create 'normalizedToTableScale': given transfert table is not a sequence of finite numbers`);\n }\n\n if (transfertTable.length < 2) {\n throw new DOMExpection(`Cannot create 'normalizedToTableScale': given transfert table length must be greater than or equal to 2`, 'IndexSizeError');\n }\n\n return value => {\n if (!Number.isFinite(value)) {\n throw new TypeError(`Cannot execute 'normalizedToTableScale' scale function: given value is non-finite`);\n }\n\n value = Math.min(1, Math.max(0, value));\n const index = value * (transfertTable.length - 1);\n\n const prev = transfertTable[Math.floor(index)];\n const next = transfertTable[Math.ceil(index)];\n const k = index - Math.floor(index);\n\n return prev + (next - prev) * k;\n }\n}\n", "import { isSequence } from './is-sequence.js';\n\n/**\n * Create a scale function that returns a normalized position in the transfert \n * table according to the given value.\n *\n * @param {number[]} transfertTable - Sequence of finite numbers to use as lookup table\n * @return {function}\n *\n * @example\n * import { tableToNormalized } from '@ircam/sc-utils'\n * const scale = tableToNormalized([1, 2, 4])\n * scale(1); // 0\n * scale(1.5); // 0.25\n * scale(2); // 0.5\n * scale(3); // 0.75\n * scale(4); // 1\n */\nexport function tableToNormalizedScale(transfertTable) {\n if (!isSequence(transfertTable)) {\n throw new TypeError(`Cannot create 'tableToNormalizedScale': given transfert table is not a sequence of finite numbers`);\n }\n\n if (transfertTable.length < 2) {\n throw new DOMExpection(`Cannot create 'tableToNormalizedScale': given transfert table length must be greater than or equal to 2`, 'IndexSizeError');\n }\n\n // clamp given value to transfert table boundaries\n const min = transfertTable[0];\n const max = transfertTable[transfertTable.length - 1];\n\n return value => {\n if (!Number.isFinite(value)) {\n throw new TypeError(`Cannot execute 'tableToNormalizedScale' scale function: given value is non-finite`);\n }\n\n value = Math.min(max, Math.max(min, value));\n\n // find normalized position\n let position;\n\n for (let i = 0; i < transfertTable.length - 1; i++) {\n let prev = transfertTable[i];\n let next = transfertTable[i + 1];\n\n if (value >= prev && value <= next) {\n const k = (value - prev) / (next - prev);\n position = (i + k) / (transfertTable.length - 1);\n\n break;\n }\n }\n\n return position;\n }\n}", "/**\n * Create a iterator of incrementing ids\n * @return {Iterator}\n * @example\n * import { idGenerator } from '@ircam/sc-utils';\n * const generator = idGenerator();\n * const id = generator.next().value\n */\nexport function* idGenerator() {\n for (let i = 0; true; i++) {\n if (i === Number.MAX_SAFE_INTEGER) {\n i = 0;\n }\n\n yield i;\n }\n}\n\n", "// ---------------------------------------------------\n// Platform\n// ---------------------------------------------------\n\nexport { isBrowser } from './is-browser.js';\nexport { isTouchDevice } from './is-touch-device.js';\n\n// ---------------------------------------------------\n// Timing\n// ---------------------------------------------------\n\nexport { delay } from './delay.js';\nexport { sleep } from './sleep.js';\nexport { getTime } from './get-time.js';\n\n// ---------------------------------------------------\n// Type check\n// ---------------------------------------------------\n\nexport { isFunction } from './is-function.js';\nexport { isNumber } from './is-number.js';\nexport { isPlainObject } from './is-plain-object.js';\nexport { isString } from './is-string.js';\nexport { isTypedArray } from './is-typed-array.js';\nexport { isURL } from './is-url.js';\nexport { isSequence } from './is-sequence.js';\n\n// ---------------------------------------------------\n// Maths\n// ---------------------------------------------------\n\nexport { atodb } from './atodb.js';\nexport { linearToDecibel } from './linear-to-decibel.js';\nexport { powerToDecibel } from './power-to-decibel.js';\n\nexport { dbtoa } from './dbtoa.js';\nexport { decibelToLinear } from './decibel-to-linear.js';\nexport { decibelToPower } from './decibel-to-power.js';\n\nexport { ftom } from './ftom.js';\nexport { mtof } from './mtof.js';\n\nexport { hertzToNormalised } from './hertz-to-normalised.js';\nexport { normalisedToHertz } from './normalised-to-hertz.js';\n\nexport { linearScale } from './linear-scale.js';\nexport { exponentialScale } from './exponential-scale.js';\nexport { logarithmicScale } from './logarithmic-scale.js';\nexport { normalizedToTableScale } from './normalized-to-table-scale.js';\nexport { tableToNormalizedScale } from './table-to-normalized-scale.js';\n\n// ---------------------------------------------------\n// MISC\n// ---------------------------------------------------\n\nexport { idGenerator } from './id-generator.js';\n", "// quantify at 1e-9 (this is very subsample accurante...)\n// minimize some floating point weirdness that may happen, e.g.\n//\n// 0.97 + 0.12\n// > 1.0899999999999999\n// Math.round((0.97 + 0.12) * 1e9) * 1e-9\n// 1.09\n//\n// note that one sample duration is ~20\u00B5s (1 / 48000 = 0.00002083333)\n// so with a default precision of 1e-9 we quantize a sample with 20000 points\n// which is probably safe enough...\n//\n// this does not work in all cases (see tests), e.g.:\n// - before 0.005307370001000001\n// - after 0.0053073700000000005\n// but the issues/problems we have seen so\n// far are when we are around a integer, with a value just below causing infinite loops\n// -> was maybe an implementation issue...\n// let's confirm we want to keep this\n\n// positive point, it garantees we don't have a value that is smaller than expected\n// in particular when we have several convertion, e.g.\n// > 1.1 + 0.1\n// > 1.1999999999999997\n\n// in any case this needs to be dig more consistently...\n\nexport function quantize(val, precision = 1e-9) {\n return Math.round(val / precision) * precision;\n}\n\nexport function cloneDeep(obj) {\n return JSON.parse(JSON.stringify(obj));\n}\n\nexport const identity = t => t;\n\nexport function isPositiveNumber(value) {\n return Number.isFinite(value) && value >= 0;\n}\n", "import { quantize } from './utils.js';\n\nfunction swap(arr, a, b) {\n const tmp = arr[a];\n arr[a] = arr[b];\n arr[b] = tmp;\n}\n\n// export for tests\nexport const kQueueTime = Symbol('sc-scheduling:queue-time');\nexport const kQueuePriority = Symbol('sc-scheduling:queue-priority');\n\n/**\n * Priority queue implementing a binary heap.\n *\n * The queue acts as a min heap by default, but can be dynamically changed to a\n * max heap by setting `reverse` to true.\n *\n * The queue uses a Symbol (i.e. `Symbol.for('sc-scheduling-queue-time')`)\n * to store the given queue time into the given object. As such this should not\n * be visible for client code\n *\n * @param {Number} [heapLength=1000] - Default size of the array used to create the heap.\n * @private\n */\nclass PriorityQueue {\n /**\n * Pointer to the first empty index of the heap.\n * @type {Number}\n * @private\n */\n #currentLength = 1;\n /**\n * Array of the sorted indexes of the entries, the actual heap. Ignore the index 0.\n * @type {Array}\n * @private\n */\n #heap = null;\n\n constructor(heapLength = 1000) {\n this.#heap = new Array(heapLength + 1);\n }\n\n /**\n * Time of the first element in the binary heap. Returns Infinity if no object\n * registered in the queue yet.\n * @readonly\n * @returns {Number}\n */\n get time() {\n if (this.#currentLength > 1) {\n return this.#heap[1][kQueueTime];\n }\n\n return Infinity;\n }\n\n /**\n * First element in the binary heap.\n * @readonly\n * @returns {Number}\n */\n get head() {\n return this.#heap[1];\n }\n\n /**\n * Define if `entry1` should be lower in the topography than `entry2`.\n * Is dynamically affected to the priority queue according to handle `min` and `max` heap.\n *\n * @param {any} entry1\n * @param {any} entry2\n * @return {Boolean}\n * @private\n */\n #isLower(entry1, entry2) {\n const time1 = entry1[kQueueTime];\n const time2 = entry2[kQueueTime];\n\n if (time1 === time2) {\n const priority1 = entry1[kQueuePriority];\n const priority2 = entry2[kQueuePriority];\n return priority1 < priority2;\n }\n\n return time1 > time2;\n }\n\n /**\n * Define if `entry1` should be higher in the topography than `entry2`.\n * Is dynamically affected to the priority queue according to handle `min` and `max` heap.\n *\n * @param {Number} entry1\n * @param {Number} entry2\n * @return {Boolean}\n * @private\n */\n #isHigher(entry1, entry2) {\n const time1 = entry1[kQueueTime];\n const time2 = entry2[kQueueTime];\n\n if (time1 === time2) {\n const priority1 = entry1[kQueuePriority];\n const priority2 = entry2[kQueuePriority];\n return priority1 > priority2;\n }\n\n return time1 < time2;\n }\n\n /**\n * Fix the heap by moving an entry to a new upper position.\n *\n * @param {Number} startIndex - The index of the entry to move.\n * @private\n */\n #bubbleUp(startIndex) {\n let entry = this.#heap[startIndex];\n\n let index = startIndex;\n let parentIndex = Math.floor(index / 2);\n let parent = this.#heap[parentIndex];\n\n while (parent && this.#isHigher(entry, parent)) {\n swap(this.#heap, index, parentIndex);\n\n index = parentIndex;\n parentIndex = Math.floor(index / 2);\n parent = this.#heap[parentIndex];\n }\n }\n\n /**\n * Fix the heap by moving an entry to a new lower position.\n *\n * @param {Number} startIndex - The index of the entry to move.\n * @private\n */\n #bubbleDown(startIndex) {\n let entry = this.#heap[startIndex];\n\n let index = startIndex;\n let c1index = index * 2;\n let c2index = c1index + 1;\n let child1 = this.#heap[c1index];\n let child2 = this.#heap[c2index];\n\n while ((child1 && this.#isLower(entry, child1)) ||\n (child2 && this.#isLower(entry, child2)))\n {\n // swap with the minimum child\n let targetIndex;\n\n if (child2) {\n targetIndex = this.#isHigher(child1, child2)\n ? c1index\n : c2index;\n } else {\n targetIndex = c1index;\n }\n\n swap(this.#heap, index, targetIndex);\n\n // update to find next children\n index = targetIndex;\n c1index = index * 2;\n c2index = c1index + 1;\n child1 = this.#heap[c1index];\n child2 = this.#heap[c2index];\n }\n }\n\n /**\n * Build the heap (from bottom up).\n * @private\n */\n #buildHeap() {\n // find the index of the last internal node\n let maxIndex = Math.floor((this.#currentLength - 1) / 2);\n\n for (let i = maxIndex; i > 0; i--) {\n this.#bubbleDown(i);\n }\n }\n\n #sanitizeTime(time) {\n if (!Number.isFinite(time)) {\n // \u00B1Infinity should always be at the end of the queue, disregarding its sign.\n // Using Number.isFinite also allows us to handle NaN gracefully\n if (Math.abs(time) !== Infinity) {\n console.warn(`PriorityQueue: time is not a number: \"${time}\" (overriden to Infinity). This probably shows an error in your implementation.`);\n }\n\n time = this.reverse ? -Infinity : Infinity;\n } else {\n // Quantize time at \u00B5s to mitigate floating point error (tbc)\n time = quantize(time);\n }\n\n return time;\n }\n\n /**\n * Insert a new object in the binary heap and sort it.\n *\n * @param {Object} entry - Entry to insert.\n * @param {Number} time - Time at which the entry should be orderer.\n * @param {Number} [priority=0] - Additionnal priority in case of equal time between\n * two children. Higher priority means the entry will retrieved first.\n * @returns {Number} - Time of the first entry in the heap.\n */\n add(entry, time, priority = 0) {\n time = this.#sanitizeTime(time);\n\n entry[kQueueTime] = time;\n entry[kQueuePriority] = priority;\n // add the new entry at the end of the heap\n this.#heap[this.#currentLength] = entry;\n // bubble it up\n this.#bubbleUp(this.#currentLength);\n this.#currentLength += 1;\n\n return this.time;\n }\n\n /**\n * Move a given entry to a new position.\n * @param {Object} entry - Entry to move.\n * @param {Number} time - Time of the entry.\n * @return {Number} - Time of first entry in the heap.\n */\n move(entry, time) {\n const index = this.#heap.indexOf(entry);\n\n if (index !== -1) {\n entry[kQueueTime] = this.#sanitizeTime(time);\n // define if the entry should be bubbled up or down\n const parent = this.#heap[Math.floor(index / 2)];\n\n if (parent && this.#isHigher(entry, parent)) {\n this.#bubbleUp(index);\n } else {\n this.#bubbleDown(index);\n }\n }\n\n return this.time;\n }\n\n /**\n * Remove an entry from the heap and fix the heap.\n * @param {Object} entry - Entry to remove.\n * @return {Number} - Time of first entry in the heap.\n */\n remove(entry) {\n // find the index of the entry\n const index = this.#heap.indexOf(entry);\n\n if (index !== -1) {\n const lastIndex = this.#currentLength - 1;\n\n // if the entry is the last one\n if (index === lastIndex) {\n // remove the element from heap\n this.#heap[lastIndex] = undefined;\n } else {\n // swap with the last element of the heap\n swap(this.#heap, index, lastIndex);\n // remove the element from heap\n this.#heap[lastIndex] = undefined;\n\n if (index === 1) {\n this.#bubbleDown(1);\n } else {\n // bubble the (ex last) element up or down according to its new context\n const entry = this.#heap[index];\n const parent = this.#heap[Math.floor(index / 2)];\n\n if (parent && this.#isHigher(entry, parent)) {\n this.#bubbleUp(index);\n } else {\n this.#bubbleDown(index);\n }\n }\n }\n\n // delete symbol key\n delete entry[kQueueTime];\n delete entry[kQueuePriority];\n // update current length\n this.#currentLength = lastIndex;\n }\n\n return this.time;\n }\n\n /**\n * Clear the queue.\n */\n clear() {\n // clear symbol from each entry\n for (let i = 1; i < this.#currentLength; i++) {\n delete this.#heap[i][kQueueTime];\n delete this.#heap[i][kQueuePriority];\n }\n\n this.#currentLength = 1;\n this.#heap = new Array(this.#heap.length);\n }\n\n /**\n * Defines if the queue contains the given `entry`.\n *\n * @param {Object} entry - Entry to be checked\n * @return {Boolean}\n */\n has(entry) {\n return this.#heap.includes(entry);\n }\n}\n\nexport default PriorityQueue;\n", "const customInspectSymbol = Symbol.for('nodejs.util.inspect.custom');\nexport const kTickLookahead = Symbol('sc-scheduling:tick-lookahead');\n\n/**\n * Scheduler information provided as third argument of a callback registered\n * in the scheduler\n */\nexport default class SchedulerEvent {\n constructor() {\n this[kTickLookahead] = 0;\n }\n\n /**\n * Delta time between tick time and current time, in seconds\n * @type {Number}\n */\n get tickLookahead() {\n return this[kTickLookahead];\n }\n\n [customInspectSymbol]() {\n return `SchedulerEvent { tickLookahead: ${this.tickLookahead} }`;\n }\n}\n\n", "import {\n isFunction,\n isNumber,\n} from '@ircam/sc-utils';\n\nimport PriorityQueue from './PriorityQueue.js';\nimport SchedulerEvent, {\n kTickLookahead,\n} from './SchedulerEvent.js';\nimport {\n identity,\n} from './utils.js';\n\nconst kSchedulerInstance = Symbol('sc-scheduling:scheduler');\n// export for tests\nexport const kSchedulerCompatMode = Symbol('sc-scheduling:compat-mode');\n\n/**\n * Processor to add into a {@link Scheduler}.\n *\n * The processor will be called back by the Scheduler at the time it request,\n * do some processing and return the next time at which it wants to be called back.\n *\n * Note that the APIs of the `SchedulerProcessor` and of a `TransportProcessor`\n * are made in such way that it is possible to implement generic processors that\n * can be added both to a `Scheduler` and to a `Transport`.\n *\n * @typedef {function} SchedulerProcessor\n *\n * @param {number} currentTime - Current time in the timeline of the scheduler\n * @param {number} processorTime - Current time in the timeline of the processor\n * see `Scheduler#options.currentTimeToProcessorTimeFunction`.\n * @param {SchedulerEvent} event - Event that holds informations about the current\n * scheduler call.\n */\n\n/**\n * The `Scheduler` interface implements a lookahead scheduler that can be used to\n * schedule events in an arbitrary timelines.\n *\n * It aims at finding a tradeoff between time precision, real-time responsiveness\n * and the weaknesses of the native timers (i.e. `setTimeout` and `setInterval`)\n *\n * For an in-depth explaination of the pattern, see \n *\n * @example\n * import { Scheduler } from '@ircam/sc-scheduling';\n * import { getTime } from '@ircam/sc-utils';\n *\n * const scheduler = new Scheduler(getTime);\n *\n * const processor = (currentTime, processorTime, infos) => {\n * console.log(currentTime);\n * return currentTime + 0.1; // ask to be called back every 100ms\n * }\n *\n * // start processor in 1 second\n * scheduler.add(processor, getTime() + 1);\n */\nclass Scheduler {\n #getTimeFunction = null;\n #period = null;\n #lookahead = null;\n #currentTimeToProcessorTimeFunction = null;\n #maxRecursions = null;\n #verbose = null;\n\n #event = new SchedulerEvent();\n #queue = null;\n #processors = new Set();\n #bindedTick = null;\n #nextTime = Infinity;\n #timeoutId = null;\n #processorRecursionsInfos = new Map();\n\n /**\n * @param {function} getTimeFunction - Function that returns a time in seconds,\n * defining the timeline in which the scheduler is running.\n * @param {object} options - Options of the scheduler\n * @param {number} [options.period=0.02] - Period of the scheduler, in seconds\n * @param {number} [options.period=0.05] - Lookahead of the scheduler, in seconds\n * @param {number} [options.queueSize=1e3] - Default size of the queue, i.e.\n * the number of events that can be scheduled in parallel\n * @param {function} [options.currentTimeToProcessorTimeFunction=Identity] - Function\n * that maps between the scheduler timeline and the processors timeline. For\n * example to map between a synchronized timeline and an AudioContext own timeline.\n * @param {number} [options.maxRecursions=100] - Number of maximum calls\n * at same time before the processor is rejected from the scheduler\n */\n constructor(getTimeFunction, {\n period = 0.02,\n lookahead = 0.05,\n queueSize = 1e3,\n currentTimeToProcessorTimeFunction = identity,\n // [deprecated]\n currentTimeToAudioTimeFunction = null,\n maxRecursions = 100,\n verbose = false,\n } = {}) {\n if (!isFunction(getTimeFunction)) {\n throw new TypeError(`Cannot construct 'Scheduler': argument 1 should be a function returning a time in seconds`);\n }\n\n if (!Number.isFinite(period) || period <= 0) {\n throw new RangeError(`Cannot construct 'Scheduler': option 'period' (${period}) must be a strictly positive number`);\n }\n\n if (!Number.isFinite(lookahead) || lookahead <= 0) {\n throw new RangeError(`Cannot construct 'Scheduler': option 'lookahead' (${lookahead}) must be a strictly positive number`);\n }\n\n if (lookahead <= period) {\n throw new RangeError(`Cannot construct 'Scheduler': option 'lookahead' (${lookahead}) be greater than period (${period})`);\n }\n\n if (!Number.isFinite(queueSize) || queueSize <= 0) {\n throw new RangeError(`Cannot construct 'Scheduler': option 'queueSize' (${queueSize}) must be a strictly positive number`);\n }\n\n if (!Number.isFinite(maxRecursions) || maxRecursions <= 0) {\n throw new RangeError(`Cannot construct 'Scheduler': option 'maxRecursions' (${maxRecursions}) must be a strictly positive number`);\n }\n\n // sort of backward compatibility\n if (currentTimeToAudioTimeFunction !== null) {\n console.warn(`[Scheduler] 'options.currentTimeToAudioTimeFunction' is deprecated and will be removed in next release, use 'options.currentTimeToProcessorTimeFunction' instead.`);\n currentTimeToProcessorTimeFunction = currentTimeToAudioTimeFunction;\n }\n\n if (!isFunction(currentTimeToProcessorTimeFunction)) {\n throw new TypeError(`Cannot construct 'Scheduler': option 'currentTimeToProcessorTimeFunction' should be a function`);\n }\n\n\n this.#queue = new PriorityQueue(queueSize);\n this.#getTimeFunction = getTimeFunction;\n this.#period = period;\n this.#lookahead = lookahead;\n this.#currentTimeToProcessorTimeFunction = currentTimeToProcessorTimeFunction;\n this.#maxRecursions = maxRecursions;\n this.#verbose = !!verbose;\n\n // bind tick as instance attribute\n this.#bindedTick = this.#tick.bind(this);\n }\n\n /**\n * Period of the scheduler, in seconds.\n *\n * Minimum time span between the scheduler checks for events, in seconds.\n * Throws if negative or greater than lookahead.\n *\n * @type {number}\n */\n get period() {\n return this.#period;\n }\n\n set period(value) {\n if (!Number.isFinite(value) || value <= 0 || value >= this.lookahead) {\n throw new RangeError(`Cannot set 'period' on Scheduler: value must be strictly positive and lower than lookahead`);\n }\n\n this.#period = value;\n }\n\n /**\n * Lookahead duration, in seconds.\n * Throws if negative or lower than period.\n * @type {number}\n */\n get lookahead() {\n return this.#lookahead;\n }\n\n set lookahead(value) {\n if (!Number.isFinite(value) || value <= 0 || value <= this.period) {\n throw new RangeError(`Cannot set 'lookahead' on Scheduler: value must be strictly positive and greater than period`);\n }\n\n this.#lookahead = value;\n }\n\n /**\n * Current time in the scheduler timeline, in seconds.\n *\n * Basically an accessor for `getTimeFunction` parameter given in constructor.\n *\n * @type {number}\n */\n get currentTime() {\n // @note 2024/06 - tickTime was not null only within #tick which is sychronous.\n // So there was no way to read it, except within processors which already received\n // the value as argument.\n // In all other cases this was just returning `current time + lookahead` which\n // was not really useful.\n // return this.#tickTime || this.#getTimeFunction() + this.lookahead;\n\n return this.#getTimeFunction();\n }\n\n /**\n * [deprecated] Scheduler current audio time according to `currentTime`\n * @type {number}\n */\n get audioTime() {\n console.warn(`[Scheduler] 'audioTime' getter is deprecated and will be removed in next release, use 'processorTime' instead.`);\n return this.#currentTimeToProcessorTimeFunction(this.currentTime);\n }\n\n /**\n * Processor time, in seconds, according to `currentTime` and the transfert\n * function provided in `options.currentTimeToProcessorTimeFunction`.\n *\n * If `options.currentTimeToProcessorTimeFunction` has not been set, is equal\n * to `currentTime`.\n *\n * @type {number}\n */\n get processorTime() {\n return this.#currentTimeToProcessorTimeFunction(this.currentTime);\n }\n\n /**\n * Execute a function once at a given time.\n *\n * Calling `defer` compensates for the tick lookahead introduced by the scheduling\n * with a `setTimeout`. Can be usefull for example to synchronize audio events\n * which natively scheduled with visuals which have no internal timing/scheduling\n * ability.\n *\n * Be aware that this method will introduce small timing error of 1-2 ms order\n * of magnitude due to the `setTimeout`.\n *\n * @param {SchedulerProcessor} deferedProcessor - Callback function to schedule.\n * @param {number} time - Time at which the callback should be scheduled.\n * @example\n * const scheduler = new Scheduler(getTime);\n *\n * scheduler.add((currentTime, processorTime) => {\n * // schedule some audio event\n * playSomeSoundAt(processorTime);\n * // defer execution of visual display to compensate the tickLookahead\n * scheduler.defer(displaySomeSynchronizedStuff, currentTime);\n * // ask the scheduler to call back in 1 second\n * return currentTime + 1;\n * });\n */\n defer(deferedProcessor, time) {\n const processor = (currentTime, processorTime, event) => {\n setTimeout(() => {\n const now = this.#getTimeFunction();\n event[kTickLookahead] = currentTime - now;\n\n deferedProcessor(currentTime, processorTime, event);\n }, Math.ceil(event.tickLookahead * 1000));\n\n // clear processor\n return null;\n };\n\n this.add(processor, time);\n }\n\n /**\n * Check whether a given processor has been added to this scheduler\n *\n * @param {SchedulerProcessor} processor - Processor to test.\n * @returns {boolean}\n */\n has(processor) {\n // compat mode for old waves TimeEngine API\n if (processor[kSchedulerCompatMode]) {\n processor = processor[kSchedulerCompatMode];\n }\n // ----------------------------------------\n return this.#processors.has(processor);\n }\n\n /**\n * Add a processor to the scheduler.\n *\n * Note that given `time` is considered a logical time and that no particular\n * checks are made on it as it might break synchronization between several\n * processors. So if the given time is in the past, the processor will be called\n * in a recursive loop until it reaches current time.\n * This is the responsibility of the consumer code to handle such possible issues.\n *\n * @param {SchedulerProcessor} processor - Processor to add to the scheduler\n * @param {number} [time=this.currentTime] - Time at which the processor should be launched.\n * @param {Number} [priority=0] - Additional priority in case of equal time between\n * two processor. Higher priority means the processor will processed first.\n */\n add(processor, time = this.currentTime, priority = 0) {\n // compat mode for old waves TimeEngine API\n if (isFunction(processor.advanceTime)) {\n // make sure we don't bind twice and always grad the same binded instance\n if (processor[kSchedulerCompatMode] === undefined) {\n processor[kSchedulerCompatMode] = processor.advanceTime.bind(processor);\n }\n\n processor = processor[kSchedulerCompatMode];\n }\n // end compat mode -------------------------\n\n if (!isFunction(processor)) {\n throw new TypeError(`Cannot execute 'add' on Scheduler: argument 1 is not a function`);\n }\n\n // prevent that a processor is added to several scheduler\n if (processor[kSchedulerInstance] !== undefined) {\n if (processor[kSchedulerInstance] !== this) {\n throw new DOMException(`Cannot execute 'add' on Scheduler: Processor belongs to another scheduler`, 'NotSupportedErrror');\n } else {\n throw new DOMException(`Cannot execute 'add' on Scheduler: Processor has already been added to this scheduler`, 'NotSupportedErrror');\n }\n }\n\n processor[kSchedulerInstance] = this;\n this.#processors.add(processor);\n this.#processorRecursionsInfos.set(processor, { time: null, counter: 0 });\n this.#queue.add(processor, time, priority);\n\n const queueTime = this.#queue.time;\n this.#resetTick(queueTime, true);\n }\n\n /**\n * Reset next time of a given processor.\n *\n * If time is not a number, the processor is removed from the scheduler.\n *\n * Note that given `time` is considered a logical time and that no particular\n * checks are made on it as it might break synchronization between several\n * processors. So if the given time is in the past, the processor will be called\n * in a recursive loop until it reaches current time.\n * This is the responsibility of the consumer code to handle such possible issues.\n *\n * Be aware that calling this method within a processor callback function won't\n * work, because the reset will always be overriden by the processor return value.\n *\n * @param {SchedulerProcessor} processor - The processor to reschedule\n * @param {number} [time=undefined] - Time at which the processor must be rescheduled\n */\n reset(processor, time = undefined) {\n // compat mode for old waves TimeEngine API\n if (processor[kSchedulerCompatMode]) {\n processor = processor[kSchedulerCompatMode];\n }\n // ----------------------------------------\n\n if (!this.has(processor)) {\n throw new DOMException(`Cannot execute 'reset' on Scheduler: Processor has not been added to this scheduler`, 'NotSupportedError');\n }\n\n if (isNumber(time)) {\n // reset recursion counter\n const processorInfos = this.#processorRecursionsInfos.get(processor);\n processorInfos.time = time;\n processorInfos.counter = 1;\n // move processor inside queue\n this.#queue.move(processor, time);\n } else {\n this.#remove(processor);\n }\n\n const queueTime = this.#queue.time;\n this.#resetTick(queueTime, true);\n }\n\n /**\n * Remove a processor from the scheduler.\n *\n * @param {SchedulerProcessor} processor - The processor to reschedule\n */\n remove(processor) {\n // compat mode for old waves TimeEngine API\n if (processor[kSchedulerCompatMode]) {\n // no need to delete the kSchedulerCompatMode key, if the processor is added again\n // we just reuse the already existing binded advanceTime.\n processor = processor[kSchedulerCompatMode];\n }\n // ----------------------------------------\n\n if (!this.has(processor)) {\n throw new DOMException(`Cannot execute 'reset' on Scheduler: Processor has not been added to this scheduler`, 'NotSupportedError');\n }\n\n this.#remove(processor);\n\n const queueTime = this.#queue.time;\n this.#resetTick(queueTime, true);\n }\n\n /**\n * Clear the scheduler.\n */\n clear() {\n for (let processor of this.#processors) {\n delete processor[kSchedulerInstance];\n }\n\n this.#queue.clear();\n this.#processors.clear();\n this.#processorRecursionsInfos.clear();\n // just stops the scheduler\n this.#resetTick(Infinity, false);\n }\n\n #remove(processor) {\n delete processor[kSchedulerInstance];\n // remove from array and queue\n this.#queue.remove(processor);\n this.#processors.delete(processor);\n this.#processorRecursionsInfos.delete(processor);\n }\n\n #tick() {\n const tickTime = this.#getTimeFunction();\n let queueTime = this.#queue.time;\n\n this.#timeoutId = null;\n\n while (queueTime <= tickTime + this.lookahead) {\n // retreive the processor and advance its time\n const processor = this.#queue.head;\n const processorInfos = this.#processorRecursionsInfos.get(processor);\n\n // update SchedulerEvent with current delta time between the tick call and\n // the scheduled event\n this.#event[kTickLookahead] = queueTime - tickTime;\n // grab related audio time if a transfert function has been given\n const processorTime = this.#currentTimeToProcessorTimeFunction(queueTime);\n let nextTime;\n\n try {\n nextTime = processor(queueTime, processorTime, this.#event);\n } catch (err) {\n console.warn(`Running processor threw an error, processor removed from scheduler`);\n console.log(err);\n this.#remove(processor);\n }\n\n // Prevent infinite loops:\n // We don't want to enforce that nextTime > time because it can be handy for e.g.\n // playing chords, but this a common source of problems in development, when\n // such returned value completely freezes the browser...\n if (nextTime === processorInfos.time) {\n processorInfos.counter += 1;\n\n if (processorInfos.counter >= this.#maxRecursions) {\n console.warn(`\\\n[Scheduler] maxRecursions (${this.#maxRecursions}) at the same time (${nextTime}) has been reached, processor discarded:\n${processor}\nThis is generally due to a implementation bug, but if you know what you are doing you should consider increasing the 'maxRecursions' option.`);\n nextTime = Infinity;\n }\n } else {\n processorInfos.time = nextTime;\n processorInfos.counter = 1;\n }\n\n if (isNumber(nextTime)) {\n this.#queue.move(processor, nextTime);\n } else {\n // we don't need to reset the tick here\n this.#remove(processor);\n }\n\n // grab next event time in queue\n queueTime = this.#queue.time;\n }\n\n // minimum bound of this.period is ok as we are in the \"normal\" scheduling behaviour\n this.#resetTick(queueTime, false);\n }\n\n /**\n * @private\n * @param {number} queueTime - The current queue time\n * @param {boolean} isReschedulingEvent - whether the function has been called\n * from a modification in the timeline, i.e. add, reset, remove or just from\n * a regular `#tick``\n */\n #resetTick(queueTime, isReschedulingEvent) {\n\n // @note - we can't compare previous and next time to avoid rescheduling because\n // timeout are too noisy: i.e. it is sometimes triggered before its deadline,\n // therefore stopping the scheduler for no apparent reason\n\n const previousNextTime = this.#nextTime;\n this.#nextTime = queueTime;\n\n clearTimeout(this.#timeoutId);\n\n if (this.#nextTime !== Infinity) {\n if (this.#verbose && previousNextTime === Infinity) {\n console.log('[Scheduler] > scheduler start');\n }\n\n // @notes - Attempt to have a synchronous API if dt is 0 or very small:\n //\n // [idea] setTimeout introduce an error of around 1-2ms we could take into account.\n // So if _nextTime is within a 10ms window we execute the #tick in a microtask\n // to minimize the delay, in other cases we can quite safely rely on setTimeout\n //\n // if (dt < 0.01) {\n // // cf. https://javascript.info/microtask-queue\n // Promise.resolve().then(this.#tick);\n // }\n //\n // [result] But... this has a lot of undesirable side effects:\n //\n // 1. If reset tick is called several times in a row, the set immediate wont\n // be cancelled, then we might end up with several parallel timeout stacks which\n // is really bad.\n //\n // 2. We must stay asynchronous here because if some processor is used to\n // orchestrate other ones behavior (and reset their time), we dont' want to\n // have another processor behing executed before the orchestartor returns its next\n // time.\n //\n // [note/tbc] Maybe this advocates for making it all more simple, with a loop that just\n // starts and stop, only reschduling when an event is added within the period\n\n const now = this.#getTimeFunction();\n const dt = this.#nextTime - now;\n // if this a rescheduling event (i.e. add, reset, remove), `queueTime` can be\n // within the `period` window, so we just clamp the minimum timeout to 1ms.\n // Note that setTimeout(func, 0), is very noisy and quite often executed\n // later than setTimeout(func, 1), cf. tests/setTimeout-setInterval-accuracy.js\n const minimumBound = isReschedulingEvent ? 1e-3 : this.period;\n const timeoutDelay = Math.max(dt - this.lookahead, minimumBound);\n\n this.#timeoutId = setTimeout(this.#bindedTick, Math.ceil(timeoutDelay * 1000));\n\n } else if (this.#verbose && previousNextTime !== Infinity) {\n console.log('[Scheduler] > scheduler stop');\n }\n }\n}\n\nexport default Scheduler;\n", "const customInspectSymbol = Symbol.for('nodejs.util.inspect.custom');\n\n/**\n * Event emitted by the Transport when a change occurs\n * @hideconstructor\n */\nclass TransportEvent {\n #type = null;\n #time = null;\n #position = null;\n #speed = null;\n #loop = null;\n #loopStart = null;\n #loopEnd = null;\n #tickLookahead = null;\n\n /** @private */\n constructor(transportState, tickLookahead) {\n this.#type = transportState.eventType;\n this.#time = transportState.time;\n this.#position = transportState.position;\n this.#speed = transportState.speed;\n this.#loop = transportState.loop;\n this.#loopStart = transportState.loopStart;\n this.#loopEnd = transportState.loopEnd;\n this.#tickLookahead = tickLookahead;\n }\n\n /**\n * Type of the event\n * @type {string}\n */\n get type() {\n return this.#type;\n }\n\n /**\n * Time of the event\n * @type {number}\n */\n get time() {\n return this.#time;\n }\n\n /**\n * Position of the event in timeline\n * @type {number}\n */\n get position() {\n return this.#position;\n }\n\n /**\n * Current speed of the transport (0 is stopped or paused, 1 if started)\n * @type {number}\n */\n get speed() {\n return this.#speed;\n }\n\n /**\n * Wether the transport is looping\n * @type {boolean}\n */\n get loop() {\n return this.#loop;\n }\n\n /**\n * Start position of the loop\n * @type {number}\n */\n get loopStart() {\n return this.#loopStart;\n }\n\n /**\n * Stop position of the loop\n * @type {number}\n */\n get loopEnd() {\n return this.#loopEnd;\n }\n\n /**\n * Delta time between tick time and event time, in seconds\n * @type {number}\n */\n get tickLookahead() {\n return this.#tickLookahead;\n }\n\n [customInspectSymbol]() {\n return `\\\nTransportEvent {\n type: '${this.type}',\n time: ${this.time}\n position: ${this.position}\n speed: ${this.speed}\n loop: ${this.loop}\n loopStart: ${this.loopStart}\n loopEnd: ${this.loopEnd}\n tickLookahead: ${this.tickLookahead}\n}\\\n `;\n }\n}\n\nexport default TransportEvent;\n", "/**\n * @private\n * Dedicated queue for the Transport\n */\nexport default class TransportControlEventQueue {\n constructor(currentTime) {\n if (!Number.isFinite(currentTime)) {\n throw new TypeError(`Cannot construct 'TransportEventQueue': argument 1 should be the current time at instanciation`);\n }\n\n this.state = {\n eventType: null,\n time: currentTime,\n position: 0,\n speed: 0,\n loop: false,\n loopStart: 0,\n loopEnd: Infinity,\n };\n this.previousState = null;\n\n this.scheduledEvents = [];\n\n this.speed = 1;\n }\n\n get next() {\n return this.scheduledEvents[0] || null;\n }\n\n add(event) {\n if (![\n 'start',\n 'stop',\n 'pause',\n 'seek',\n 'cancel',\n 'loop',\n 'loop-start',\n 'loop-end',\n 'loop-point',\n 'speed',\n ].includes(event.type)) {\n throw new Error(`Invalid event type: \"${event.type}\"`);\n }\n\n // Prevent scheduling an event before current `state.time`. Note that this does\n // not prevent to schedule an event in the past according to scheduler currentTime,\n // which is desirable to mitigate possible network latencies\n if (this.state.time > event.time) {\n console.error(`Cannot execute 'add' on TransportEventQueue: Given 'event.time' is before current 'state.time'. Aborting...`, event);\n return null;\n }\n\n // cancel is really a real-time event\n if (event.type === 'cancel') {\n // remove all event which time are >= to the one of the cancel event\n // no need to sort the queue\n this.scheduledEvents = this.scheduledEvents.filter(e => e.time < event.time);\n return event; // this is always applied\n }\n\n this.scheduledEvents.push(event);\n\n this.scheduledEvents.sort((a, b) => {\n if (a.time < b.time) {\n return -1;\n } else if (a.time > b.time) {\n return 1;\n } else if (a.time === b.time) {\n return 0; // keep original order\n }\n });\n\n // Remove consecutive events of same type, disregarding `seek`, `loop`, `loop-start`\n // `loop-end` and `speed` events. For example in the `start|seek|seek|start` list\n // we want to keep `start|seek|seek` (the second `start` is redondant)\n let eventType = this.state.eventType;\n\n this.scheduledEvents = this.scheduledEvents.filter((event, i) => {\n // the events we want to dedup\n if (['start', 'stop', 'pause', 'cancel'].includes(event.type)) {\n if (event.type !== eventType) {\n eventType = event.type;\n return true;\n } else {\n return false;\n }\n }\n\n // keep all other events\n return true;\n });\n\n // return null if event has been discarded\n // i.e. scheduled in the past or filtered as duplicate\n return this.scheduledEvents.indexOf(event) !== -1 ? event : null;\n }\n\n dequeue() {\n const event = this.next;\n const nextState = Object.assign({}, this.state);\n\n nextState.eventType = event.type;\n nextState.time = event.time;\n nextState.position = this.getPositionAtTime(event.time);\n\n // update state infos according to event\n switch (event.type) {\n case 'start':\n nextState.speed = this.speed;\n break;\n case 'stop':\n nextState.position = 0;\n nextState.speed = 0;\n break;\n case 'pause':\n nextState.speed = 0;\n break;\n case 'seek':\n nextState.position = event.position;\n break;\n case 'loop':\n nextState.loop = event.loop;\n break;\n case 'loop-start':\n nextState.loopStart = event.loopStart;\n break;\n case 'loop-end':\n nextState.loopEnd = event.loopEnd;\n break;\n case 'loop-point':\n nextState.position = event.position;\n break;\n case 'speed':\n this.speed = event.speed;\n\n if (nextState.speed > 0) {\n nextState.speed = event.speed;\n }\n break;\n }\n\n this.scheduledEvents.shift();\n // @todo - we may use this to mitigate some lookahead issue w/ getPositionAtTime\n // i.e. asking for getPositionAtTime(currentTime) while dequeue as already been called\n // this.previousState = this.state;\n this.state = nextState;\n\n // clear any existing loop point\n this.scheduledEvents = this.scheduledEvents.filter(event => event.type !== 'loop-point');\n // reschedule loop-point event if needed\n if (this.state.loop && this.state.speed > 0) {\n // insert loop-point event in timeline according to what we know, if state\n // change in between the loop-point be reinserted at its right position.\n if (this.state.position < this.state.loopEnd) {\n const event = {\n type: 'loop-point',\n time: this.getTimeAtPosition(this.state.loopEnd),\n position: this.state.loopStart, // is rather abitrary but probably more convenient\n }\n\n this.add(event);\n }\n // if current position is after loop end, do nothing\n }\n\n return Object.assign({}, this.state);\n }\n\n // return estimated position at time according to state event informations\n getPositionAtTime(time) {\n if (!Number.isFinite(time)) {\n return Infinity;\n }\n\n const state = this.state;\n // compute position from actual state informations\n let position = state.position + (time - state.time) * state.speed;\n // outside a loop we clamp computed position to last event position\n let lowerBoundary = state.position;\n\n // apply loop if needed\n if (state.loop && position >= state.loopEnd) {\n position = position - state.loopStart;\n const diff = position % (state.loopEnd - state.loopStart);\n position = state.loopStart + diff;\n\n // update the time, and position of the state so that `getTimeAtPosition`\n // stays coherent for the engines added to the transport\n state.time = time - diff;\n state.position = state.loopStart;\n\n // if the state position is greater than loop start (e.g. if we pause in\n // the middle of the loop), loop start should be used as the lower boundary.\n lowerBoundary = Math.min(state.position, state.loopStart);\n }\n\n return Math.max(position, lowerBoundary);\n }\n\n // return estimated time accroding to an event and position\n getTimeAtPosition(position) {\n // Infinity * 0 give NaN so handle Infinity separately\n if (!Number.isFinite(position)) {\n return Infinity;\n }\n\n if (this.state.speed === 0) {\n return this.state.time;\n } else {\n return this.state.time + (position - this.state.position) / this.state.speed;\n }\n }\n}\n", "import { isNumber, isFunction } from '@ircam/sc-utils';\n\nimport { quantize, cloneDeep, isPositiveNumber } from './utils.js';\nimport Scheduler from './Scheduler.js';\nimport TransportEvent from './TransportEvent.js';\nimport TransportEventQueue from './TransportEventQueue.js';\n\nconst kTransportInstance = Symbol('sc-scheduling:transport');\n\n/**\n * Processor to add into a {@link Transport}.\n *\n * The processor will be called back by the Transport on each transport event to\n * define its behavior according to event. Between these events, it can be called\n * as a regular {@link SchedulerProcessor} to do some processing.\n *\n * Note that the APIs of the `SchedulerProcessor` and of a `TransportProcessor`\n * are made in such way that it is possible to implement generic processors that\n * can be added both to a `Scheduler` and to a `Transport`.\n *\n * @typedef {function} TransportProcessor\n *\n * @param {number} currentPosition - Current position in the timeline of the transport.\n * @param {number} processorTime - Current time in the timeline of the processor\n * see `Scheduler#options.currentTimeToProcessorTimeFunction`.\n * @param {TransportEvent|SchedulerEvent} event - Event that holds informations\n * about the current transport or scheduler call.\n */\n\n/**\n * The Transport abstraction allows to define and manipulate a timeline.\n *\n * All provided Transport commands (e.g. start, stop, etc) can be scheduled in the\n * underlying scheduler timeline which makes it usable in distributed and synchronized\n * contexts.\n *\n * @example\n * import { Scheduler, Transport, TransportEvent } from '@ircam/sc-scheduling';\n * import { getTime } from '@ircam/sc-utils';\n *\n * const scheduler = new Scheduler(getTime);\n * const transport = new Transport(scheduler);\n *\n * const processor = (position, time, infos) => {\n * if (infos instanceof TransportEvent) {\n * // ask to be called back only when the transport is running\n * return infos.speed > 0 ? position : Infinity;\n * }\n *\n * console.log(position);\n * return position + 0.1; // ask to be called back every 100ms\n * }\n *\n * transport.add(processor);\n * // start transport in 1 second\n * transport.start(getTime() + 1);\n */\nclass Transport {\n #scheduler = null;\n #bindedTick = null;\n #eventQueue = null;\n #processors = new Map(); // \n // we want transport events to be processed before regular processors\n #queuePriority = 1e3;\n\n /**\n * @param {Scheduler} scheduler - Instance of scheduler into which the transport\n * should run\n * @param {object} [initialState=null] - Initial state of the transport, to synchronize\n * it from another transport state (see `Transport#dumpState()`).\n */\n constructor(scheduler, initialState = null) {\n if (!(scheduler instanceof Scheduler)) {\n throw new TypeError(`Cannot construct 'Transport': Argument 1 must be an instance of Scheduler`);\n }\n\n this.#scheduler = scheduler;\n // init event queue state with current scheduler time, we can't assume\n // the transport is created at the beginning of the process\n this.#eventQueue = new TransportEventQueue(this.#scheduler.currentTime);\n this.#bindedTick = this.#tick.bind(this);\n\n if (initialState !== null) {\n this.#eventQueue.state = initialState.currentState;\n // init scheduler\n this.addEvents(initialState.scheduledEvents);\n }\n }\n\n /**\n * Retrieves the current state and event queue for the transport as a raw object.\n *\n * The returned value can be used to initialize the state of another synchronized\n * transport, cf. `initialValue` argument from constructor.\n *\n * @return {object}\n */\n serialize() {\n return {\n currentState: cloneDeep(this.#eventQueue.state),\n scheduledEvents: cloneDeep(this.#eventQueue.scheduledEvents),\n };\n }\n\n /**\n * Pointer to the underlying scheduler.\n * @type {Scheduler}\n */\n get scheduler() {\n return this.#scheduler;\n }\n\n /**\n * Current time from scheduler timeline, in seconds.\n * @type {number}\n */\n get currentTime() {\n return this.#scheduler.currentTime;\n }\n\n /**\n * Current processor time, in seconds.\n * @type {number}\n */\n get processorTime() {\n return this.#scheduler.processorTime;\n }\n\n /**\n * Current transport position, in seconds.\n * @type {number}\n */\n get currentPosition() {\n return this.getPositionAtTime(this.currentTime);\n }\n\n /**\n * Estimated position at given time according to the transport current state.\n *\n * @param {number} time - Time to convert to position\n * @return {number}\n */\n getPositionAtTime(time) {\n return quantize(this.#eventQueue.getPositionAtTime(time));\n }\n\n /**\n * Start the transport at a given time.\n *\n * @param {number} [time=this.currentTime] - Time to execute the command\n * @return {object|null} Raw event or `null` if event discarded\n */\n start(time = this.currentTime) {\n if (!isPositiveNumber(time)) {\n throw new TypeError(`Cannot execute 'start' on 'Transport': argument 1 (time) should be a positive number`);\n }\n\n const event = {\n type: 'start',\n time: quantize(time),\n };\n\n return this.addEvent(event);\n }\n\n /**\n * Stop the transport at a given time, position will be reset to zero.\n *\n * @param {number} [time=this.currentTime] - Time to execute the command\n * @return {object|null} Raw event or `null` if event discarded\n */\n stop(time = this.currentTime) {\n if (!isPositiveNumber(time)) {\n throw new TypeError(`Cannot execute 'stop' on 'Transport': argument 1 (time) should be a positive number`);\n }\n\n const event = {\n type: 'stop',\n time: quantize(time),\n };\n\n return this.addEvent(event);\n }\n\n /**\n * Pause the transport at a given time, position will remain untouched.\n *\n * @param {number} [time=this.currentTime] - Time to execute the command\n * @return {object|null} Raw event or `null` if event discarded\n */\n pause(time = this.currentTime) {\n if (!isPositiveNumber(time)) {\n throw new TypeError(`Cannot execute 'pause' on 'Transport': argument 1 (time) should be a positive number`);\n }\n\n const event = {\n type: 'pause',\n time: quantize(time),\n };\n\n return this.addEvent(event);\n }\n\n /**\n * Seek to a new position in the timeline at a given time.\n *\n * @param {number} position - New transport position\n * @param {number} [time=this.currentTime] - Time to execute the command\n * @return {object|null} Raw event or `null` if event discarded\n */\n seek(position, time = this.currentTime) {\n if (!Number.isFinite(position)) {\n throw new TypeError(`Cannot execute 'seek' on 'Transport': argument 1 (position) should be a finite number`);\n }\n\n if (!isPositiveNumber(time)) {\n throw new TypeError(`Cannot execute 'seek' on 'Transport': argument 2 (time) should be a positive number`);\n }\n\n const event = {\n type: 'seek',\n time: quantize(time),\n position: position,\n };\n\n return this.addEvent(event);\n }\n\n /**\n * Set the transport loop state at a given time.\n *\n * @param {boolean} value - Loop state\n * @param {number} [time=this.currentTime] - Time to execute the command\n * @return {object|null} Raw event or `null` if event discarded\n */\n loop(value, time = this.currentTime) {\n if (typeof value !== 'boolean') {\n throw new TypeError(`Cannot execute 'loop' on 'Transport': argument 2 (value) should be a boolean`);\n }\n\n if (!isPositiveNumber(time)) {\n throw new TypeError(`Cannot execute 'loop' on 'Transport': argument 1 (time) should be a positive number`);\n }\n\n const event = {\n type: 'loop',\n time: quantize(time),\n loop: value,\n };\n\n return this.addEvent(event);\n }\n\n // @todo - How to handle if loopEnd < loopStart as we can't know both avalues in advance?\n // - drop event when it's dequeued?\n /**\n * Set the transport loop start point at a given time.\n *\n * @param {number} position - Position of loop start point\n * @param {number} [time=this.currentTime] - Time to execute the command\n * @return {object|null} Raw event or `null` if event discarded\n */\n loopStart(position, time = this.currentTime) {\n if (position !== -Infinity && !Number.isFinite(position)) {\n throw new TypeError(`Cannot execute 'loopStart' on 'Transport': argument 1 (position) should be either a finite number or -Infinity`);\n }\n\n if (!isPositiveNumber(time)) {\n throw new TypeError(`Cannot execute 'loopStart' on 'Transport': argument 2 (time) should be a positive number`);\n }\n\n const event = {\n type: 'loop-start',\n time: quantize(time),\n loopStart: position,\n };\n\n return this.addEvent(event);\n }\n\n // @todo - How to handle if loopEnd < loopStart as we can't know both avalues in advance?\n // - drop event when it's dequeued?\n /**\n * Set the transport loop end point at a given time.\n *\n * @param {number} position - Position of loop end point\n * @param {number} [time=this.currentTime] - Time to execute the command\n * @return {object|null} Raw event or `null` if event discarded\n */\n loopEnd(position, time = this.currentTime) {\n if (position !== Infinity && !Number.isFinite(position)) {\n throw new TypeError(`Cannot execute 'loopStart' on 'Transport': argument 1 (position) should be either a finite number or Infinity`);\n }\n\n if (!isPositiveNumber(time)) {\n throw new TypeError(`Cannot execute 'loopEnd' on 'Transport': argument 2 (time) should be a positive number`);\n }\n\n const event = {\n type: 'loop-end',\n time: quantize(time),\n loopEnd: position,\n };\n\n return this.addEvent(event);\n }\n\n /**\n * Set transport speed at a given time.\n *\n * Note that speed must be strictly positive.\n * _Experimental_\n *\n * @param {number} speed - Speed of the transport, must be strictly > 0\n * @param {number} [time=this.currentTime] - Time to execute the command\n * @return {object|null} Raw event or `null` if event discarded\n */\n speed(value, time = this.currentTime) {\n if (!Number.isFinite(value)) {\n throw new TypeError(`Cannot execute 'speed' on 'Transport': argument 1 (value) should be a positive number`);\n }\n\n if (!isPositiveNumber(time)) {\n throw new TypeError(`Cannot execute 'speed' on 'Transport': argument 2 (time) should be a positive number`);\n }\n\n const event = {\n type: 'speed',\n time: quantize(time),\n speed: value,\n };\n\n return this.addEvent(event);\n }\n\n /**\n * Cancel all currently scheduled event after the given time.\n *\n * @param {number} [time=this.currentTime] - Time to execute the command\n * @return {object|null} Raw event or `null` if event discarded\n */\n cancel(time = this.currentTime) {\n if (!isPositiveNumber(time)) {\n throw new TypeError(`Cannot execute 'cancel' on 'Transport': argument 1 (time) should be a positive number`);\n }\n\n const event = {\n type: 'cancel',\n time: quantize(time),\n };\n\n return this.addEvent(event);\n }\n\n /**\n * Add raw event to the transport queue.\n *\n * Most of the time, you should use the dedicated higher level methods. However\n * this is useful to control several transports from a central event producer.\n * In particular this can be used to synchronize several transport on the network\n * according you have access to a synchronized timeline in which the schedulers\n * are running, cf. e.g. )\n *\n * @example\n * const scheduler = new Scheduler(getTime);\n * const primary = new Transport(scheduler);\n * // create a \"copy\" of the primary transport\n * const secondary = new Transport(scheduler, primary.serialize());\n * // perform some control command and share it with the secondary transport\n * const event = primary.start(getTime() + 1);\n * // `event` (as well as `primary.serialize()`) could e.g. be sent over the network\n * secondary.addEvent(event);\n *\n * @param {object} event - Raw event as returned by the transport control methods\n */\n addEvent(event) {\n // make sure we don't crash the transport if we try to add an event that\n // as been discarded when synchronizing several states on a master\n if (event === null) {\n return null;\n }\n\n // grab next before adding event, as it may be replaced by the new event\n const next = this.#eventQueue.next;\n const enqueued = this.#eventQueue.add(event);\n\n // cancel events are applied right now, no need to schedule them\n if (enqueued !== null && enqueued.type !== 'cancel') {\n if (!this.#scheduler.has(this.#bindedTick)) {\n // use logical next as it may not be the same as the enqueued event\n // (not sure this is actually possible, but this doesn't hurt...)\n this.#scheduler.add(this.#bindedTick, this.#eventQueue.next.time, this.#queuePriority);\n } else if (!next || enqueued.time < next.time) {\n // reschedule transport if inserted event is before previous next event\n this.#scheduler.reset(this.#bindedTick, enqueued.time);\n }\n }\n\n // console.log(enqueued);\n return enqueued;\n }\n\n /**\n * Add a list of raw events to the transport queue.\n *\n * @param {object[]} event - List of raw events\n */\n addEvents(eventList) {\n return eventList.map(event => this.addEvent(event));\n }\n\n /**\n * Add an processor to the transport.\n *\n * When a processor is added to the transport, it called with an 'init' event\n * to allow it to respond properly to the current state of the transport.\n * For example, if the transport has already been started.\n *\n * @param {TransportProcessor} processor - Engine to add to the transport\n * @throws Throw if the processor has already been added to this or another transport\n */\n add(processor) {\n if (!isFunction(processor)) {\n throw new TypeError(`Cannot execute 'add' on 'Transport': argument 1 is not a function`);\n }\n\n if (processor[kTransportInstance] !== undefined) {\n if (processor[kTransportInstance] !== this) {\n throw new DOMException(`Cannot execute 'add' on 'Transport': processor already added to another transport`, 'NotSupportedError');\n } else {\n throw new DOMException(`Cannot execute 'add' on 'Transport': processor already added this transport`, 'NotSupportedError');\n }\n }\n\n processor[kTransportInstance] = this;\n\n // infos can be SchedulerInfos or TransportEvent\n const wrappedEngine = (function wrappedEngine(currentTime, processorTime, infos) {\n // execute processor in transport timeline\n const position = this.getPositionAtTime(currentTime); // quantized\n const nextPosition = processor(position, processorTime, infos);\n\n if (isNumber(nextPosition)) {\n return this.#eventQueue.getTimeAtPosition(nextPosition);\n } else {\n // make sure processors do not remove themselves from the scheduler\n return Infinity;\n }\n }).bind(this);\n\n this.#processors.set(processor, wrappedEngine);\n\n // @todo - handle case where transport is in running state\n // add to scheduler at Infinity, children should never be removed from scheduler\n\n // call processor tick method according to current transport state\n // @todo - using scheduler current time is not good as it may include\n // lookahead\n const currentTime = this.currentTime;\n const processorTime = this.processorTime;\n const state = cloneDeep(this.#eventQueue.state);\n state.eventType = 'init';\n const tickLookahead = state.time - currentTime;\n const transportEvent = new TransportEvent(state, tickLookahead);\n\n this.#scheduler.add(wrappedEngine, Infinity);\n // allow processor to reset it's position in scheduler\n this.#tickEngine(wrappedEngine, currentTime, processorTime, transportEvent);\n }\n\n /**\n * Define if a given processor has been added to the transport.\n *\n * @param {TransportProcessor} processor - Engine to check\n * @return {boolean}\n */\n has(processor) {\n return this.#processors.has(processor);\n }\n\n /**\n * Remove a processor from the transport.\n *\n * @param {TransportProcessor} processor - Engine to remove from the transport\n * @throws Throw if the processor has not been added to the transport\n */\n remove(processor) {\n if (!this.has(processor)) {\n throw new DOMException(`Cannot execute 'remove' on 'Transport': processor does not belong to this transport`, 'NotSupportedError');\n }\n\n const wrappedEngine = this.#processors.get(processor);\n // remove from scheduler\n this.#scheduler.remove(wrappedEngine);\n this.#processors.delete(processor);\n delete processor[kTransportInstance];\n }\n\n /**\n * Remove all processors, cancel all registered transport event and pause transport\n */\n clear() {\n for (let processor of this.#processors.keys()) {\n this.remove(processor);\n }\n\n this.cancel(this.currentTime);\n this.stop(this.currentTime);\n }\n\n #tick(currentTime, processorTime, schedulerInfos) {\n const state = this.#eventQueue.dequeue();\n const transportEvent = new TransportEvent(state, schedulerInfos.tickLookahead);\n\n // Propagate transport event to all childrens, so that they can define their\n // position and reset their next time in scheduler.\n //\n // Note that we use the wrapped processor, so all convertions between time and\n // position is done inside the processor itself. Then, we can just propagate the\n // values received from the scheduler in a straightforward way.\n for (let processor of this.#processors.values()) {\n this.#tickEngine(processor, currentTime, processorTime, transportEvent);\n }\n\n // return time of next transport event\n if (this.#eventQueue.next) {\n return this.#eventQueue.next.time;\n } else {\n return Infinity;\n }\n }\n\n #tickEngine(processor, currentTime, processorTime, transportEvent) {\n let resetTime;\n\n try {\n resetTime = processor(currentTime, processorTime, transportEvent);\n } catch(err) {\n console.error(err);\n }\n\n // @fixme - This can fail due to back and forth conversions between time and position\n // if (resetTime < currentTime) {\n // console.warn('Handling TransportEvent cannot lead to scheduling in the past, removing faulty processor');\n // this.#scheduler.remove(processor);\n // }\n\n // no need for further check or conversion, everything is done in processor wrapper\n this.#scheduler.reset(processor, resetTime);\n }\n}\n\nexport default Transport;\n", "export { default as Scheduler } from './Scheduler.js';\nexport { default as SchedulerEvent } from './SchedulerEvent.js';\nexport { default as Transport } from './Transport.js';\nexport { default as TransportEvent } from './TransportEvent.js';\n", "/**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nconst NODE_MODE = false;\n\n// Allows minifiers to rename references to globalThis\nconst global = globalThis;\n\n/**\n * Whether the current browser supports `adoptedStyleSheets`.\n */\nexport const supportsAdoptingStyleSheets: boolean =\n global.ShadowRoot &&\n (global.ShadyCSS === undefined || global.ShadyCSS.nativeShadow) &&\n 'adoptedStyleSheets' in Document.prototype &&\n 'replace' in CSSStyleSheet.prototype;\n\n/**\n * A CSSResult or native CSSStyleSheet.\n *\n * In browsers that support constructible CSS style sheets, CSSStyleSheet\n * object can be used for styling along side CSSResult from the `css`\n * template tag.\n */\nexport type CSSResultOrNative = CSSResult | CSSStyleSheet;\n\nexport type CSSResultArray = Array;\n\n/**\n * A single CSSResult, CSSStyleSheet, or an array or nested arrays of those.\n */\nexport type CSSResultGroup = CSSResultOrNative | CSSResultArray;\n\nconst constructionToken = Symbol();\n\nconst cssTagCache = new WeakMap();\n\n/**\n * A container for a string of CSS text, that may be used to create a CSSStyleSheet.\n *\n * CSSResult is the return value of `css`-tagged template literals and\n * `unsafeCSS()`. In order to ensure that CSSResults are only created via the\n * `css` tag and `unsafeCSS()`, CSSResult cannot be constructed directly.\n */\nexport class CSSResult {\n // This property needs to remain unminified.\n ['_$cssResult$'] = true;\n readonly cssText: string;\n private _styleSheet?: CSSStyleSheet;\n private _strings: TemplateStringsArray | undefined;\n\n private constructor(\n cssText: string,\n strings: TemplateStringsArray | undefined,\n safeToken: symbol\n ) {\n if (safeToken !== constructionToken) {\n throw new Error(\n 'CSSResult is not constructable. Use `unsafeCSS` or `css` instead.'\n );\n }\n this.cssText = cssText;\n this._strings = strings;\n }\n\n // This is a getter so that it's lazy. In practice, this means stylesheets\n // are not created until the first element instance is made.\n get styleSheet(): CSSStyleSheet | undefined {\n // If `supportsAdoptingStyleSheets` is true then we assume CSSStyleSheet is\n // constructable.\n let styleSheet = this._styleSheet;\n const strings = this._strings;\n if (supportsAdoptingStyleSheets && styleSheet === undefined) {\n const cacheable = strings !== undefined && strings.length === 1;\n if (cacheable) {\n styleSheet = cssTagCache.get(strings);\n }\n if (styleSheet === undefined) {\n (this._styleSheet = styleSheet = new CSSStyleSheet()).replaceSync(\n this.cssText\n );\n if (cacheable) {\n cssTagCache.set(strings, styleSheet);\n }\n }\n }\n return styleSheet;\n }\n\n toString(): string {\n return this.cssText;\n }\n}\n\ntype ConstructableCSSResult = CSSResult & {\n new (\n cssText: string,\n strings: TemplateStringsArray | undefined,\n safeToken: symbol\n ): CSSResult;\n};\n\nconst textFromCSSResult = (value: CSSResultGroup | number) => {\n // This property needs to remain unminified.\n if ((value as CSSResult)['_$cssResult$'] === true) {\n return (value as CSSResult).cssText;\n } else if (typeof value === 'number') {\n return value;\n } else {\n throw new Error(\n `Value passed to 'css' function must be a 'css' function result: ` +\n `${value}. Use 'unsafeCSS' to pass non-literal values, but take care ` +\n `to ensure page security.`\n );\n }\n};\n\n/**\n * Wrap a value for interpolation in a {@linkcode css} tagged template literal.\n *\n * This is unsafe because untrusted CSS text can be used to phone home\n * or exfiltrate data to an attacker controlled site. Take care to only use\n * this with trusted input.\n */\nexport const unsafeCSS = (value: unknown) =>\n new (CSSResult as ConstructableCSSResult)(\n typeof value === 'string' ? value : String(value),\n undefined,\n constructionToken\n );\n\n/**\n * A template literal tag which can be used with LitElement's\n * {@linkcode LitElement.styles} property to set element styles.\n *\n * For security reasons, only literal string values and number may be used in\n * embedded expressions. To incorporate non-literal values {@linkcode unsafeCSS}\n * may be used inside an expression.\n */\nexport const css = (\n strings: TemplateStringsArray,\n ...values: (CSSResultGroup | number)[]\n): CSSResult => {\n const cssText =\n strings.length === 1\n ? strings[0]\n : values.reduce(\n (acc, v, idx) => acc + textFromCSSResult(v) + strings[idx + 1],\n strings[0]\n );\n return new (CSSResult as ConstructableCSSResult)(\n cssText,\n strings,\n constructionToken\n );\n};\n\n/**\n * Applies the given styles to a `shadowRoot`. When Shadow DOM is\n * available but `adoptedStyleSheets` is not, styles are appended to the\n * `shadowRoot` to [mimic spec behavior](https://wicg.github.io/construct-stylesheets/#using-constructed-stylesheets).\n * Note, when shimming is used, any styles that are subsequently placed into\n * the shadowRoot should be placed *before* any shimmed adopted styles. This\n * will match spec behavior that gives adopted sheets precedence over styles in\n * shadowRoot.\n */\nexport const adoptStyles = (\n renderRoot: ShadowRoot,\n styles: Array\n) => {\n if (supportsAdoptingStyleSheets) {\n (renderRoot as ShadowRoot).adoptedStyleSheets = styles.map((s) =>\n s instanceof CSSStyleSheet ? s : s.styleSheet!\n );\n } else {\n for (const s of styles) {\n const style = document.createElement('style');\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const nonce = (global as any)['litNonce'];\n if (nonce !== undefined) {\n style.setAttribute('nonce', nonce);\n }\n style.textContent = (s as CSSResult).cssText;\n renderRoot.appendChild(style);\n }\n }\n};\n\nconst cssResultFromStyleSheet = (sheet: CSSStyleSheet) => {\n let cssText = '';\n for (const rule of sheet.cssRules) {\n cssText += rule.cssText;\n }\n return unsafeCSS(cssText);\n};\n\nexport const getCompatibleStyle =\n supportsAdoptingStyleSheets ||\n (NODE_MODE && global.CSSStyleSheet === undefined)\n ? (s: CSSResultOrNative) => s\n : (s: CSSResultOrNative) =>\n s instanceof CSSStyleSheet ? cssResultFromStyleSheet(s) : s;\n", "/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * Use this module if you want to create your own base class extending\n * {@link ReactiveElement}.\n * @packageDocumentation\n */\n\nimport {\n getCompatibleStyle,\n adoptStyles,\n CSSResultGroup,\n CSSResultOrNative,\n} from './css-tag.js';\nimport type {\n ReactiveController,\n ReactiveControllerHost,\n} from './reactive-controller.js';\n\n// In the Node build, this import will be injected by Rollup:\n// import {HTMLElement, customElements} from '@lit-labs/ssr-dom-shim';\n\nexport * from './css-tag.js';\nexport type {\n ReactiveController,\n ReactiveControllerHost,\n} from './reactive-controller.js';\n\n/**\n * Removes the `readonly` modifier from properties in the union K.\n *\n * This is a safer way to cast a value to a type with a mutable version of a\n * readonly field, than casting to an interface with the field re-declared\n * because it preserves the type of all the fields and warns on typos.\n */\ntype Mutable = Omit & {\n -readonly [P in keyof Pick]: P extends K ? T[P] : never;\n};\n\n// TODO (justinfagnani): Add `hasOwn` here when we ship ES2022\nconst {\n is,\n defineProperty,\n getOwnPropertyDescriptor,\n getOwnPropertyNames,\n getOwnPropertySymbols,\n getPrototypeOf,\n} = Object;\n\nconst NODE_MODE = false;\n\n// Lets a minifier replace globalThis references with a minified name\nconst global = globalThis;\n\nif (NODE_MODE) {\n global.customElements ??= customElements;\n}\n\nconst DEV_MODE = true;\n\nlet issueWarning: (code: string, warning: string) => void;\n\nconst trustedTypes = (global as unknown as {trustedTypes?: {emptyScript: ''}})\n .trustedTypes;\n\n// Temporary workaround for https://crbug.com/993268\n// Currently, any attribute starting with \"on\" is considered to be a\n// TrustedScript source. Such boolean attributes must be set to the equivalent\n// trusted emptyScript value.\nconst emptyStringForBooleanAttribute = trustedTypes\n ? (trustedTypes.emptyScript as unknown as '')\n : '';\n\nconst polyfillSupport = DEV_MODE\n ? global.reactiveElementPolyfillSupportDevMode\n : global.reactiveElementPolyfillSupport;\n\nif (DEV_MODE) {\n // Ensure warnings are issued only 1x, even if multiple versions of Lit\n // are loaded.\n const issuedWarnings: Set = (global.litIssuedWarnings ??=\n new Set());\n\n // Issue a warning, if we haven't already.\n issueWarning = (code: string, warning: string) => {\n warning += ` See https://lit.dev/msg/${code} for more information.`;\n if (!issuedWarnings.has(warning)) {\n console.warn(warning);\n issuedWarnings.add(warning);\n }\n };\n\n issueWarning(\n 'dev-mode',\n `Lit is in dev mode. Not recommended for production!`\n );\n\n // Issue polyfill support warning.\n if (global.ShadyDOM?.inUse && polyfillSupport === undefined) {\n issueWarning(\n 'polyfill-support-missing',\n `Shadow DOM is being polyfilled via \\`ShadyDOM\\` but ` +\n `the \\`polyfill-support\\` module has not been loaded.`\n );\n }\n}\n\n/**\n * Contains types that are part of the unstable debug API.\n *\n * Everything in this API is not stable and may change or be removed in the future,\n * even on patch releases.\n */\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace ReactiveUnstable {\n /**\n * When Lit is running in dev mode and `window.emitLitDebugLogEvents` is true,\n * we will emit 'lit-debug' events to window, with live details about the update and render\n * lifecycle. These can be useful for writing debug tooling and visualizations.\n *\n * Please be aware that running with window.emitLitDebugLogEvents has performance overhead,\n * making certain operations that are normally very cheap (like a no-op render) much slower,\n * because we must copy data and dispatch events.\n */\n // eslint-disable-next-line @typescript-eslint/no-namespace\n export namespace DebugLog {\n export type Entry = Update;\n export interface Update {\n kind: 'update';\n }\n }\n}\n\ninterface DebugLoggingWindow {\n // Even in dev mode, we generally don't want to emit these events, as that's\n // another level of cost, so only emit them when DEV_MODE is true _and_ when\n // window.emitLitDebugEvents is true.\n emitLitDebugLogEvents?: boolean;\n}\n\n/**\n * Useful for visualizing and logging insights into what the Lit template system is doing.\n *\n * Compiled out of prod mode builds.\n */\nconst debugLogEvent = DEV_MODE\n ? (event: ReactiveUnstable.DebugLog.Entry) => {\n const shouldEmit = (global as unknown as DebugLoggingWindow)\n .emitLitDebugLogEvents;\n if (!shouldEmit) {\n return;\n }\n global.dispatchEvent(\n new CustomEvent('lit-debug', {\n detail: event,\n })\n );\n }\n : undefined;\n\n/*\n * When using Closure Compiler, JSCompiler_renameProperty(property, object) is\n * replaced at compile time by the munged name for object[property]. We cannot\n * alias this function, so we have to use a small shim that has the same\n * behavior when not compiling.\n */\n/*@__INLINE__*/\nconst JSCompiler_renameProperty =

(\n prop: P,\n _obj: unknown\n): P => prop;\n\n/**\n * Converts property values to and from attribute values.\n */\nexport interface ComplexAttributeConverter {\n /**\n * Called to convert an attribute value to a property\n * value.\n */\n fromAttribute?(value: string | null, type?: TypeHint): Type;\n\n /**\n * Called to convert a property value to an attribute\n * value.\n *\n * It returns unknown instead of string, to be compatible with\n * https://github.com/WICG/trusted-types (and similar efforts).\n */\n toAttribute?(value: Type, type?: TypeHint): unknown;\n}\n\ntype AttributeConverter =\n | ComplexAttributeConverter\n | ((value: string | null, type?: TypeHint) => Type);\n\n/**\n * Defines options for a property accessor.\n */\nexport interface PropertyDeclaration {\n /**\n * When set to `true`, indicates the property is internal private state. The\n * property should not be set by users. When using TypeScript, this property\n * should be marked as `private` or `protected`, and it is also a common\n * practice to use a leading `_` in the name. The property is not added to\n * `observedAttributes`.\n */\n readonly state?: boolean;\n\n /**\n * Indicates how and whether the property becomes an observed attribute.\n * If the value is `false`, the property is not added to `observedAttributes`.\n * If true or absent, the lowercased property name is observed (e.g. `fooBar`\n * becomes `foobar`). If a string, the string value is observed (e.g\n * `attribute: 'foo-bar'`).\n */\n readonly attribute?: boolean | string;\n\n /**\n * Indicates the type of the property. This is used only as a hint for the\n * `converter` to determine how to convert the attribute\n * to/from a property.\n */\n readonly type?: TypeHint;\n\n /**\n * Indicates how to convert the attribute to/from a property. If this value\n * is a function, it is used to convert the attribute value a the property\n * value. If it's an object, it can have keys for `fromAttribute` and\n * `toAttribute`. If no `toAttribute` function is provided and\n * `reflect` is set to `true`, the property value is set directly to the\n * attribute. A default `converter` is used if none is provided; it supports\n * `Boolean`, `String`, `Number`, `Object`, and `Array`. Note,\n * when a property changes and the converter is used to update the attribute,\n * the property is never updated again as a result of the attribute changing,\n * and vice versa.\n */\n readonly converter?: AttributeConverter;\n\n /**\n * Indicates if the property should reflect to an attribute.\n * If `true`, when the property is set, the attribute is set using the\n * attribute name determined according to the rules for the `attribute`\n * property option and the value of the property converted using the rules\n * from the `converter` property option.\n */\n readonly reflect?: boolean;\n\n /**\n * A function that indicates if a property should be considered changed when\n * it is set. The function should take the `newValue` and `oldValue` and\n * return `true` if an update should be requested.\n */\n hasChanged?(value: Type, oldValue: Type): boolean;\n\n /**\n * Indicates whether an accessor will be created for this property. By\n * default, an accessor will be generated for this property that requests an\n * update when set. If this flag is `true`, no accessor will be created, and\n * it will be the user's responsibility to call\n * `this.requestUpdate(propertyName, oldValue)` to request an update when\n * the property changes.\n */\n readonly noAccessor?: boolean;\n\n /**\n * Whether this property is wrapping accessors. This is set by `@property`\n * to control the initial value change and reflection logic.\n *\n * @internal\n */\n wrapped?: boolean;\n}\n\n/**\n * Map of properties to PropertyDeclaration options. For each property an\n * accessor is made, and the property is processed according to the\n * PropertyDeclaration options.\n */\nexport interface PropertyDeclarations {\n readonly [key: string]: PropertyDeclaration;\n}\n\ntype PropertyDeclarationMap = Map;\n\ntype AttributeMap = Map;\n\n/**\n * A Map of property keys to values.\n *\n * Takes an optional type parameter T, which when specified as a non-any,\n * non-unknown type, will make the Map more strongly-typed, associating the map\n * keys with their corresponding value type on T.\n *\n * Use `PropertyValues` when overriding ReactiveElement.update() and\n * other lifecycle methods in order to get stronger type-checking on keys\n * and values.\n */\n// This type is conditional so that if the parameter T is not specified, or\n// is `any`, the type will include `Map`. Since T is not\n// given in the uses of PropertyValues in this file, all uses here fallback to\n// meaning `Map`, but if a developer uses\n// `PropertyValues` (or any other value for T) they will get a\n// strongly-typed Map type.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type PropertyValues = T extends object\n ? PropertyValueMap\n : Map;\n\n/**\n * Do not use, instead prefer {@linkcode PropertyValues}.\n */\n// This type must be exported such that JavaScript generated by the Google\n// Closure Compiler can import a type reference.\nexport interface PropertyValueMap extends Map {\n get(k: K): T[K] | undefined;\n set(key: K, value: T[K]): this;\n has(k: K): boolean;\n delete(k: K): boolean;\n}\n\nexport const defaultConverter: ComplexAttributeConverter = {\n toAttribute(value: unknown, type?: unknown): unknown {\n switch (type) {\n case Boolean:\n value = value ? emptyStringForBooleanAttribute : null;\n break;\n case Object:\n case Array:\n // if the value is `null` or `undefined` pass this through\n // to allow removing/no change behavior.\n value = value == null ? value : JSON.stringify(value);\n break;\n }\n return value;\n },\n\n fromAttribute(value: string | null, type?: unknown) {\n let fromValue: unknown = value;\n switch (type) {\n case Boolean:\n fromValue = value !== null;\n break;\n case Number:\n fromValue = value === null ? null : Number(value);\n break;\n case Object:\n case Array:\n // Do *not* generate exception when invalid JSON is set as elements\n // don't normally complain on being mis-configured.\n // TODO(sorvell): Do generate exception in *dev mode*.\n try {\n // Assert to adhere to Bazel's \"must type assert JSON parse\" rule.\n fromValue = JSON.parse(value!) as unknown;\n } catch (e) {\n fromValue = null;\n }\n break;\n }\n return fromValue;\n },\n};\n\nexport interface HasChanged {\n (value: unknown, old: unknown): boolean;\n}\n\n/**\n * Change function that returns true if `value` is different from `oldValue`.\n * This method is used as the default for a property's `hasChanged` function.\n */\nexport const notEqual: HasChanged = (value: unknown, old: unknown): boolean =>\n !is(value, old);\n\nconst defaultPropertyDeclaration: PropertyDeclaration = {\n attribute: true,\n type: String,\n converter: defaultConverter,\n reflect: false,\n hasChanged: notEqual,\n};\n\n/**\n * A string representing one of the supported dev mode warning categories.\n */\nexport type WarningKind =\n | 'change-in-update'\n | 'migration'\n | 'async-perform-update';\n\nexport type Initializer = (element: ReactiveElement) => void;\n\n// Temporary, until google3 is on TypeScript 5.2\ndeclare global {\n interface SymbolConstructor {\n readonly metadata: unique symbol;\n }\n}\n\n// Ensure metadata is enabled. TypeScript does not polyfill\n// Symbol.metadata, so we must ensure that it exists.\n(Symbol as {metadata: symbol}).metadata ??= Symbol('metadata');\n\ndeclare global {\n // This is public global API, do not change!\n // eslint-disable-next-line no-var\n var litPropertyMetadata: WeakMap<\n object,\n Map\n >;\n}\n\n// Map from a class's metadata object to property options\n// Note that we must use nullish-coalescing assignment so that we only use one\n// map even if we load multiple version of this module.\nglobal.litPropertyMetadata ??= new WeakMap<\n object,\n Map\n>();\n\n/**\n * Base element class which manages element properties and attributes. When\n * properties change, the `update` method is asynchronously called. This method\n * should be supplied by subclasses to render updates as desired.\n * @noInheritDoc\n */\nexport abstract class ReactiveElement\n // In the Node build, this `extends` clause will be substituted with\n // `(globalThis.HTMLElement ?? HTMLElement)`.\n //\n // This way, we will first prefer any global `HTMLElement` polyfill that the\n // user has assigned, and then fall back to the `HTMLElement` shim which has\n // been imported (see note at the top of this file about how this import is\n // generated by Rollup). Note that the `HTMLElement` variable has been\n // shadowed by this import, so it no longer refers to the global.\n extends HTMLElement\n implements ReactiveControllerHost\n{\n // Note: these are patched in only in DEV_MODE.\n /**\n * Read or set all the enabled warning categories for this class.\n *\n * This property is only used in development builds.\n *\n * @nocollapse\n * @category dev-mode\n */\n static enabledWarnings?: WarningKind[];\n\n /**\n * Enable the given warning category for this class.\n *\n * This method only exists in development builds, so it should be accessed\n * with a guard like:\n *\n * ```ts\n * // Enable for all ReactiveElement subclasses\n * ReactiveElement.enableWarning?.('migration');\n *\n * // Enable for only MyElement and subclasses\n * MyElement.enableWarning?.('migration');\n * ```\n *\n * @nocollapse\n * @category dev-mode\n */\n static enableWarning?: (warningKind: WarningKind) => void;\n\n /**\n * Disable the given warning category for this class.\n *\n * This method only exists in development builds, so it should be accessed\n * with a guard like:\n *\n * ```ts\n * // Disable for all ReactiveElement subclasses\n * ReactiveElement.disableWarning?.('migration');\n *\n * // Disable for only MyElement and subclasses\n * MyElement.disableWarning?.('migration');\n * ```\n *\n * @nocollapse\n * @category dev-mode\n */\n static disableWarning?: (warningKind: WarningKind) => void;\n\n /**\n * Adds an initializer function to the class that is called during instance\n * construction.\n *\n * This is useful for code that runs against a `ReactiveElement`\n * subclass, such as a decorator, that needs to do work for each\n * instance, such as setting up a `ReactiveController`.\n *\n * ```ts\n * const myDecorator = (target: typeof ReactiveElement, key: string) => {\n * target.addInitializer((instance: ReactiveElement) => {\n * // This is run during construction of the element\n * new MyController(instance);\n * });\n * }\n * ```\n *\n * Decorating a field will then cause each instance to run an initializer\n * that adds a controller:\n *\n * ```ts\n * class MyElement extends LitElement {\n * @myDecorator foo;\n * }\n * ```\n *\n * Initializers are stored per-constructor. Adding an initializer to a\n * subclass does not add it to a superclass. Since initializers are run in\n * constructors, initializers will run in order of the class hierarchy,\n * starting with superclasses and progressing to the instance's class.\n *\n * @nocollapse\n */\n static addInitializer(initializer: Initializer) {\n this.__prepare();\n (this._initializers ??= []).push(initializer);\n }\n\n static _initializers?: Initializer[];\n\n /*\n * Due to closure compiler ES6 compilation bugs, @nocollapse is required on\n * all static methods and properties with initializers. Reference:\n * - https://github.com/google/closure-compiler/issues/1776\n */\n\n /**\n * Maps attribute names to properties; for example `foobar` attribute to\n * `fooBar` property. Created lazily on user subclasses when finalizing the\n * class.\n * @nocollapse\n */\n private static __attributeToPropertyMap: AttributeMap;\n\n /**\n * Marks class as having been finalized, which includes creating properties\n * from `static properties`, but does *not* include all properties created\n * from decorators.\n * @nocollapse\n */\n protected static finalized: true | undefined;\n\n /**\n * Memoized list of all element properties, including any superclass\n * properties. Created lazily on user subclasses when finalizing the class.\n *\n * @nocollapse\n * @category properties\n */\n static elementProperties: PropertyDeclarationMap;\n\n /**\n * User-supplied object that maps property names to `PropertyDeclaration`\n * objects containing options for configuring reactive properties. When\n * a reactive property is set the element will update and render.\n *\n * By default properties are public fields, and as such, they should be\n * considered as primarily settable by element users, either via attribute or\n * the property itself.\n *\n * Generally, properties that are changed by the element should be private or\n * protected fields and should use the `state: true` option. Properties\n * marked as `state` do not reflect from the corresponding attribute\n *\n * However, sometimes element code does need to set a public property. This\n * should typically only be done in response to user interaction, and an event\n * should be fired informing the user; for example, a checkbox sets its\n * `checked` property when clicked and fires a `changed` event. Mutating\n * public properties should typically not be done for non-primitive (object or\n * array) properties. In other cases when an element needs to manage state, a\n * private property set with the `state: true` option should be used. When\n * needed, state properties can be initialized via public properties to\n * facilitate complex interactions.\n * @nocollapse\n * @category properties\n */\n static properties: PropertyDeclarations;\n\n /**\n * Memoized list of all element styles.\n * Created lazily on user subclasses when finalizing the class.\n * @nocollapse\n * @category styles\n */\n static elementStyles: Array = [];\n\n /**\n * Array of styles to apply to the element. The styles should be defined\n * using the {@linkcode css} tag function, via constructible stylesheets, or\n * imported from native CSS module scripts.\n *\n * Note on Content Security Policy:\n *\n * Element styles are implemented with `