@tspro/web-music-score 3.2.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/CHANGELOG.md +26 -10
  2. package/README.md +189 -331
  3. package/dist/audio/index.d.ts +1 -1
  4. package/dist/audio/index.js +1 -1
  5. package/dist/audio/index.mjs +2 -2
  6. package/dist/audio-cg/index.js +1 -1
  7. package/dist/audio-cg/index.mjs +2 -2
  8. package/dist/{chunk-LCTM7BID.mjs → chunk-D643HZHM.mjs} +2 -2
  9. package/dist/core/index.js +2 -2
  10. package/dist/core/index.mjs +3 -3
  11. package/dist/{guitar-C2Cp71NZ.d.ts → guitar-cNmE-EvH.d.ts} +1 -1
  12. package/dist/iife/index.global.js +11 -11
  13. package/dist/{interface-BlNl69uT.d.ts → interface-7k8qGG44.d.ts} +89 -81
  14. package/dist/{interface-Bn5HFt_U.d.mts → interface-XoKiryoV.d.mts} +88 -80
  15. package/dist/{note-BFa43I86.d.ts → note-CcVdUFqS.d.ts} +1 -1
  16. package/dist/pieces/index.d.mts +2 -2
  17. package/dist/pieces/index.d.ts +3 -3
  18. package/dist/pieces/index.js +4 -7
  19. package/dist/pieces/index.mjs +8 -11
  20. package/dist/react-ui/index.d.mts +3 -3
  21. package/dist/react-ui/index.d.ts +5 -5
  22. package/dist/react-ui/index.js +1 -1
  23. package/dist/react-ui/index.mjs +2 -2
  24. package/dist/{scale-DRR-t4Kr.d.mts → scale-C2pCNxdE.d.mts} +4 -3
  25. package/dist/{scale-ebJm37q1.d.ts → scale-CvPbJvfN.d.ts} +5 -4
  26. package/dist/score/index.d.mts +98 -31
  27. package/dist/score/index.d.ts +99 -32
  28. package/dist/score/index.js +748 -567
  29. package/dist/score/index.mjs +755 -574
  30. package/dist/tempo-BAYoZ_Li.d.mts +187 -0
  31. package/dist/tempo-r2sb6Ku2.d.ts +187 -0
  32. package/dist/theory/index.d.mts +3 -3
  33. package/dist/theory/index.d.ts +6 -6
  34. package/dist/theory/index.js +221 -78
  35. package/dist/theory/index.mjs +218 -76
  36. package/package.json +2 -2
  37. package/dist/tempo-B4h5Ktob.d.mts +0 -104
  38. package/dist/tempo-DgqDEsn0.d.ts +0 -104
@@ -1,4 +1,4 @@
1
- /* WebMusicScore v3.2.0 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
1
+ /* WebMusicScore v4.0.0 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
2
2
  "use strict";
3
3
  var __create = Object.create;
4
4
  var __defProp = Object.defineProperty;
@@ -361,16 +361,16 @@ var DivRect = class _DivRect {
361
361
  };
362
362
 
363
363
  // src/score/pub/document-builder.ts
364
- var import_ts_utils_lib11 = require("@tspro/ts-utils-lib");
364
+ var import_ts_utils_lib13 = require("@tspro/ts-utils-lib");
365
365
 
366
366
  // src/score/pub/types.ts
367
367
  var StaffPreset = /* @__PURE__ */ ((StaffPreset3) => {
368
- StaffPreset3[StaffPreset3["Treble"] = 1] = "Treble";
369
- StaffPreset3[StaffPreset3["Bass"] = 2] = "Bass";
370
- StaffPreset3[StaffPreset3["Grand"] = 3] = "Grand";
371
- StaffPreset3[StaffPreset3["GuitarTreble"] = 4] = "GuitarTreble";
372
- StaffPreset3[StaffPreset3["GuitarTab"] = 8] = "GuitarTab";
373
- StaffPreset3[StaffPreset3["GuitarCombined"] = 12] = "GuitarCombined";
368
+ StaffPreset3["Treble"] = "treble";
369
+ StaffPreset3["Bass"] = "bass";
370
+ StaffPreset3["Grand"] = "grand";
371
+ StaffPreset3["GuitarTreble"] = "guitarTreble";
372
+ StaffPreset3["GuitarTab"] = "guitarTab";
373
+ StaffPreset3["GuitarCombined"] = "guitarCombined";
374
374
  return StaffPreset3;
375
375
  })(StaffPreset || {});
376
376
  var Clef = /* @__PURE__ */ ((Clef2) => {
@@ -385,77 +385,77 @@ function getStringNumbers() {
385
385
  return [1, 2, 3, 4, 5, 6];
386
386
  }
387
387
  var Stem = /* @__PURE__ */ ((Stem2) => {
388
- Stem2[Stem2["Auto"] = 0] = "Auto";
389
- Stem2[Stem2["Up"] = 1] = "Up";
390
- Stem2[Stem2["Down"] = 2] = "Down";
388
+ Stem2["Auto"] = "auto";
389
+ Stem2["Up"] = "up";
390
+ Stem2["Down"] = "down";
391
391
  return Stem2;
392
392
  })(Stem || {});
393
393
  var Arpeggio = /* @__PURE__ */ ((Arpeggio2) => {
394
- Arpeggio2[Arpeggio2["Up"] = 0] = "Up";
395
- Arpeggio2[Arpeggio2["Down"] = 1] = "Down";
394
+ Arpeggio2["Up"] = "up";
395
+ Arpeggio2["Down"] = "down";
396
396
  return Arpeggio2;
397
397
  })(Arpeggio || {});
398
398
  var TieType = /* @__PURE__ */ ((TieType2) => {
399
- TieType2[TieType2["Stub"] = -1] = "Stub";
400
- TieType2[TieType2["ToMeasureEnd"] = -2] = "ToMeasureEnd";
399
+ TieType2["Stub"] = "stub";
400
+ TieType2["ToMeasureEnd"] = "toMeasureEnd";
401
401
  return TieType2;
402
402
  })(TieType || {});
403
403
  var NoteAnchor = /* @__PURE__ */ ((NoteAnchor2) => {
404
- NoteAnchor2[NoteAnchor2["Auto"] = 0] = "Auto";
405
- NoteAnchor2[NoteAnchor2["Above"] = 1] = "Above";
406
- NoteAnchor2[NoteAnchor2["Center"] = 2] = "Center";
407
- NoteAnchor2[NoteAnchor2["Below"] = 3] = "Below";
408
- NoteAnchor2[NoteAnchor2["StemTip"] = 4] = "StemTip";
404
+ NoteAnchor2["Auto"] = "auto";
405
+ NoteAnchor2["Above"] = "above";
406
+ NoteAnchor2["Center"] = "center";
407
+ NoteAnchor2["Below"] = "below";
408
+ NoteAnchor2["StemTip"] = "stemTip";
409
409
  return NoteAnchor2;
410
410
  })(NoteAnchor || {});
411
411
  var Connective = /* @__PURE__ */ ((Connective2) => {
412
- Connective2[Connective2["Tie"] = 0] = "Tie";
413
- Connective2[Connective2["Slur"] = 1] = "Slur";
414
- Connective2[Connective2["Slide"] = 2] = "Slide";
412
+ Connective2["Tie"] = "tie";
413
+ Connective2["Slur"] = "slur";
414
+ Connective2["Slide"] = "slide";
415
415
  return Connective2;
416
416
  })(Connective || {});
417
417
  var VerticalPosition = /* @__PURE__ */ ((VerticalPosition4) => {
418
- VerticalPosition4[VerticalPosition4["Above"] = 0] = "Above";
419
- VerticalPosition4[VerticalPosition4["Below"] = 1] = "Below";
420
- VerticalPosition4[VerticalPosition4["Both"] = 2] = "Both";
421
- VerticalPosition4[VerticalPosition4["Auto"] = 3] = "Auto";
418
+ VerticalPosition4["Auto"] = "auto";
419
+ VerticalPosition4["Above"] = "above";
420
+ VerticalPosition4["Below"] = "below";
421
+ VerticalPosition4["Both"] = "both";
422
422
  return VerticalPosition4;
423
423
  })(VerticalPosition || {});
424
- var PlayState = /* @__PURE__ */ ((PlayState2) => {
425
- PlayState2[PlayState2["Playing"] = 0] = "Playing";
426
- PlayState2[PlayState2["Paused"] = 1] = "Paused";
427
- PlayState2[PlayState2["Stopped"] = 2] = "Stopped";
428
- return PlayState2;
429
- })(PlayState || {});
430
424
  var Fermata = /* @__PURE__ */ ((Fermata2) => {
431
- Fermata2[Fermata2["AtNote"] = 0] = "AtNote";
432
- Fermata2[Fermata2["AtMeasureEnd"] = 1] = "AtMeasureEnd";
425
+ Fermata2["AtNote"] = "atNote";
426
+ Fermata2["AtMeasureEnd"] = "atMeasureEnd";
433
427
  return Fermata2;
434
428
  })(Fermata || {});
435
429
  var Navigation = /* @__PURE__ */ ((Navigation2) => {
436
- Navigation2[Navigation2["DC_al_Fine"] = 0] = "DC_al_Fine";
437
- Navigation2[Navigation2["DC_al_Coda"] = 1] = "DC_al_Coda";
438
- Navigation2[Navigation2["DS_al_Fine"] = 2] = "DS_al_Fine";
439
- Navigation2[Navigation2["DS_al_Coda"] = 3] = "DS_al_Coda";
440
- Navigation2[Navigation2["Coda"] = 4] = "Coda";
441
- Navigation2[Navigation2["toCoda"] = 5] = "toCoda";
442
- Navigation2[Navigation2["Segno"] = 6] = "Segno";
443
- Navigation2[Navigation2["Fine"] = 7] = "Fine";
444
- Navigation2[Navigation2["StartRepeat"] = 8] = "StartRepeat";
445
- Navigation2[Navigation2["EndRepeat"] = 9] = "EndRepeat";
446
- Navigation2[Navigation2["Ending"] = 10] = "Ending";
430
+ Navigation2["DC_al_Fine"] = "D.C. al Fine";
431
+ Navigation2["DC_al_Coda"] = "D.C. al Coda";
432
+ Navigation2["DS_al_Fine"] = "D.S. al Fine";
433
+ Navigation2["DS_al_Coda"] = "D.S. al Coda";
434
+ Navigation2["Coda"] = "Coda";
435
+ Navigation2["toCoda"] = "toCoda";
436
+ Navigation2["Segno"] = "Segno";
437
+ Navigation2["Fine"] = "Fine";
438
+ Navigation2["StartRepeat"] = "startRepeat";
439
+ Navigation2["EndRepeat"] = "endRepeat";
440
+ Navigation2["Ending"] = "ending";
447
441
  return Navigation2;
448
442
  })(Navigation || {});
449
443
  var Annotation = /* @__PURE__ */ ((Annotation2) => {
450
- Annotation2[Annotation2["Dynamics"] = 0] = "Dynamics";
451
- Annotation2[Annotation2["Tempo"] = 1] = "Tempo";
444
+ Annotation2["Dynamics"] = "dynamics";
445
+ Annotation2["Tempo"] = "tempo";
452
446
  return Annotation2;
453
447
  })(Annotation || {});
454
448
  var Label = /* @__PURE__ */ ((Label2) => {
455
- Label2[Label2["Note"] = 0] = "Note";
456
- Label2[Label2["Chord"] = 1] = "Chord";
449
+ Label2["Note"] = "note";
450
+ Label2["Chord"] = "chord";
457
451
  return Label2;
458
452
  })(Label || {});
453
+ var PlayState = /* @__PURE__ */ ((PlayState2) => {
454
+ PlayState2[PlayState2["Playing"] = 0] = "Playing";
455
+ PlayState2[PlayState2["Paused"] = 1] = "Paused";
456
+ PlayState2[PlayState2["Stopped"] = 2] = "Stopped";
457
+ return PlayState2;
458
+ })(PlayState || {});
459
459
 
460
460
  // src/score/engine/music-object.ts
461
461
  var MusicObjectLink = class {
@@ -954,10 +954,10 @@ var Renderer = class {
954
954
 
955
955
  // src/score/engine/obj-staff-and-tab.ts
956
956
  var import_core15 = require("@tspro/web-music-score/core");
957
- var import_ts_utils_lib9 = require("@tspro/ts-utils-lib");
957
+ var import_ts_utils_lib11 = require("@tspro/ts-utils-lib");
958
958
 
959
959
  // src/score/engine/obj-measure.ts
960
- var import_ts_utils_lib8 = require("@tspro/ts-utils-lib");
960
+ var import_ts_utils_lib10 = require("@tspro/ts-utils-lib");
961
961
  var import_theory9 = require("@tspro/web-music-score/theory");
962
962
  var import_theory10 = require("@tspro/web-music-score/theory");
963
963
 
@@ -1546,7 +1546,7 @@ var ObjSignature = class extends MusicObject {
1546
1546
  };
1547
1547
 
1548
1548
  // src/score/engine/player.ts
1549
- var import_ts_utils_lib5 = require("@tspro/ts-utils-lib");
1549
+ var import_ts_utils_lib6 = require("@tspro/ts-utils-lib");
1550
1550
  var import_theory7 = require("@tspro/web-music-score/theory");
1551
1551
  var Audio = __toESM(require("@tspro/web-music-score/audio"));
1552
1552
 
@@ -1576,8 +1576,8 @@ var ObjArpeggio = class extends MusicObject {
1576
1576
  }
1577
1577
  layout(renderer) {
1578
1578
  let { unitSize } = renderer;
1579
- this.topArrowHeight = this.arpeggioDir === 0 /* Up */ ? unitSize : 0;
1580
- this.bottomArrowHeight = this.arpeggioDir === 1 /* Down */ ? unitSize : 0;
1579
+ this.topArrowHeight = this.arpeggioDir === "up" /* Up */ ? unitSize : 0;
1580
+ this.bottomArrowHeight = this.arpeggioDir === "down" /* Down */ ? unitSize : 0;
1581
1581
  let top = this.line.getTopLineY();
1582
1582
  let bottom = this.line.getBottomLineY();
1583
1583
  this.cycleHeight = unitSize * 2;
@@ -1643,7 +1643,7 @@ var ObjStaffRest = class extends MusicObject {
1643
1643
  this.staff = staff;
1644
1644
  this.rest = rest;
1645
1645
  __publicField(this, "restRect", new DivRect());
1646
- __publicField(this, "dotRect");
1646
+ __publicField(this, "dotRects", []);
1647
1647
  __publicField(this, "mi");
1648
1648
  staff.addObject(this);
1649
1649
  this.mi = new MStaffRest(this);
@@ -1655,21 +1655,18 @@ var ObjStaffRest = class extends MusicObject {
1655
1655
  return this.getRect().contains(x, y) ? [this] : [];
1656
1656
  }
1657
1657
  offset(dx, dy) {
1658
- var _a;
1659
1658
  this.restRect.offsetInPlace(dx, dy);
1660
- (_a = this.dotRect) == null ? void 0 : _a.offsetInPlace(dx, dy);
1659
+ this.dotRects.forEach((r) => r.offsetInPlace(dx, dy));
1661
1660
  this.requestRectUpdate();
1662
1661
  this.rest.requestRectUpdate();
1663
1662
  }
1664
1663
  updateRect() {
1665
1664
  this.rect = this.restRect.copy();
1666
- if (this.dotRect) {
1667
- this.rect.expandInPlace(this.dotRect);
1668
- }
1665
+ this.dotRects.forEach((r) => this.rect.expandInPlace(r));
1669
1666
  }
1670
1667
  };
1671
1668
  var ObjRest = class extends MusicObject {
1672
- constructor(col, voiceId, noteLength, options) {
1669
+ constructor(col, voiceId, noteLength, options, tupletRatio) {
1673
1670
  var _a, _b;
1674
1671
  super(col);
1675
1672
  this.col = col;
@@ -1678,6 +1675,7 @@ var ObjRest = class extends MusicObject {
1678
1675
  __publicField(this, "ownDiatonicId");
1679
1676
  __publicField(this, "color");
1680
1677
  __publicField(this, "hide");
1678
+ __publicField(this, "oldStyleTriplet");
1681
1679
  __publicField(this, "rhythmProps");
1682
1680
  __publicField(this, "beamGroup");
1683
1681
  __publicField(this, "staffObjects", []);
@@ -1701,7 +1699,9 @@ var ObjRest = class extends MusicObject {
1701
1699
  }
1702
1700
  this.color = (_a = options == null ? void 0 : options.color) != null ? _a : "black";
1703
1701
  this.hide = (_b = options == null ? void 0 : options.hide) != null ? _b : false;
1704
- this.rhythmProps = new import_theory3.RhythmProps(noteLength, options == null ? void 0 : options.dotted, options == null ? void 0 : options.triplet);
1702
+ this.oldStyleTriplet = tupletRatio === void 0 && ((options == null ? void 0 : options.triplet) === true || import_theory3.NoteLengthProps.get(noteLength).isTriplet);
1703
+ let dotCount = typeof (options == null ? void 0 : options.dotted) === "number" ? options.dotted > 0 ? options.dotted : void 0 : (options == null ? void 0 : options.dotted) === true ? 1 : void 0;
1704
+ this.rhythmProps = import_theory3.RhythmProps.get(noteLength, dotCount, (tupletRatio != null ? tupletRatio : this.oldStyleTriplet) ? import_theory3.Tuplet.Triplet : void 0);
1705
1705
  this.mi = new MRest(this);
1706
1706
  }
1707
1707
  getMusicInterface() {
@@ -1719,15 +1719,9 @@ var ObjRest = class extends MusicObject {
1719
1719
  get noteLength() {
1720
1720
  return this.rhythmProps.noteLength;
1721
1721
  }
1722
- get dotted() {
1723
- return this.rhythmProps.dotted;
1724
- }
1725
1722
  get stemDir() {
1726
1723
  return this.beamGroup ? this.beamGroup.stemDir : this.ownStemDir;
1727
1724
  }
1728
- get triplet() {
1729
- return this.rhythmProps.triplet;
1730
- }
1731
1725
  getStaticObjects(line) {
1732
1726
  let staticObjects = [];
1733
1727
  this.staffObjects.forEach((obj) => {
@@ -1752,8 +1746,8 @@ var ObjRest = class extends MusicObject {
1752
1746
  getBeamGroup() {
1753
1747
  return this.beamGroup;
1754
1748
  }
1755
- setBeamGroup(beam) {
1756
- this.beamGroup = beam;
1749
+ setBeamGroup(beamGroup) {
1750
+ this.beamGroup = beamGroup;
1757
1751
  }
1758
1752
  resetBeamGroup() {
1759
1753
  this.beamGroup = void 0;
@@ -1762,7 +1756,7 @@ var ObjRest = class extends MusicObject {
1762
1756
  return this.staffObjects.map((obj) => {
1763
1757
  let staff = obj.staff;
1764
1758
  let x = obj.getRect().centerX;
1765
- let y = this.stemDir === 1 /* Up */ ? obj.getRect().top : obj.getRect().bottom;
1759
+ let y = this.stemDir === "up" /* Up */ ? obj.getRect().top : obj.getRect().bottom;
1766
1760
  let stemHeight = Math.abs(obj.getRect().centerY - y);
1767
1761
  return { staff, x, y, stemHeight };
1768
1762
  });
@@ -1803,7 +1797,7 @@ var ObjRest = class extends MusicObject {
1803
1797
  }
1804
1798
  let { unitSize } = renderer;
1805
1799
  let { ownDiatonicId } = this;
1806
- let { noteLength, dotted, flagCount } = this.rhythmProps;
1800
+ let { noteLength, dotCount, flagCount } = this.rhythmProps;
1807
1801
  let leftw = 0;
1808
1802
  let rightw = 0;
1809
1803
  let toph = 0;
@@ -1836,11 +1830,11 @@ var ObjRest = class extends MusicObject {
1836
1830
  }
1837
1831
  let obj = new ObjStaffRest(staff, this);
1838
1832
  obj.restRect = new DivRect(-leftw, 0, rightw, -toph, 0, bottomh);
1839
- if (dotted) {
1833
+ for (let i = 0; i < dotCount; i++) {
1840
1834
  let dotWidth = DocumentSettings.DotSize * unitSize;
1841
- let dotX = rightw + (DocumentSettings.RestDotSpace + DocumentSettings.DotSize / 2) * unitSize;
1835
+ let dotX = rightw + (DocumentSettings.RestDotSpace + DocumentSettings.DotSize * unitSize) + i * DocumentSettings.DotSize * unitSize * 1.5;
1842
1836
  let dotY = this.getRestDotVerticalDisplacement(noteLength) * unitSize;
1843
- obj.dotRect = DivRect.createCentered(dotX, dotY, dotWidth, dotWidth);
1837
+ obj.dotRects.push(DivRect.createCentered(dotX, dotY, dotWidth, dotWidth));
1844
1838
  }
1845
1839
  obj.offset(0, staff.getDiatonicIdY(ownDiatonicId));
1846
1840
  this.staffObjects.push(obj);
@@ -1874,7 +1868,7 @@ var ObjRest = class extends MusicObject {
1874
1868
  ctx.strokeStyle = ctx.fillStyle = color;
1875
1869
  ctx.lineWidth = lineWidth;
1876
1870
  this.staffObjects.forEach((obj) => {
1877
- let { dotRect, restRect } = obj;
1871
+ let { dotRects, restRect } = obj;
1878
1872
  let x = restRect.centerX;
1879
1873
  let y = restRect.centerY;
1880
1874
  if (noteLength === import_theory3.NoteLength.Whole) {
@@ -1939,9 +1933,9 @@ var ObjRest = class extends MusicObject {
1939
1933
  ctx.fill();
1940
1934
  }
1941
1935
  }
1942
- if (dotRect) {
1943
- renderer.fillCircle(dotRect.centerX, dotRect.centerY, dotRect.width / 2);
1944
- }
1936
+ dotRects.forEach((r) => {
1937
+ renderer.fillCircle(r.centerX, r.centerY, r.width / 2);
1938
+ });
1945
1939
  });
1946
1940
  }
1947
1941
  };
@@ -1989,8 +1983,8 @@ var ObjStaffBeamGroup = class extends MusicObject {
1989
1983
  super(staff);
1990
1984
  this.staff = staff;
1991
1985
  this.beamGroup = beamGroup;
1992
- __publicField(this, "tripletNumber");
1993
- __publicField(this, "tripletNumberOffsetY", 0);
1986
+ __publicField(this, "tupletNumber");
1987
+ __publicField(this, "tupletNumberOffsetY", 0);
1994
1988
  __publicField(this, "points", []);
1995
1989
  __publicField(this, "mi");
1996
1990
  staff.addObject(this);
@@ -2005,48 +1999,47 @@ var ObjStaffBeamGroup = class extends MusicObject {
2005
1999
  offset(dx, dy) {
2006
2000
  var _a;
2007
2001
  this.points.forEach((p) => p.offset(dx, 0));
2008
- (_a = this.tripletNumber) == null ? void 0 : _a.offset(dx, dy);
2002
+ (_a = this.tupletNumber) == null ? void 0 : _a.offset(dx, dy);
2009
2003
  this.requestRectUpdate();
2010
2004
  this.beamGroup.requestRectUpdate();
2011
2005
  }
2012
2006
  updateRect() {
2013
2007
  if (this.points.length > 0) {
2014
2008
  this.rect = this.points[0].getRect().copy();
2015
- } else if (this.tripletNumber) {
2016
- this.rect = this.tripletNumber.getRect().copy();
2009
+ } else if (this.tupletNumber) {
2010
+ this.rect = this.tupletNumber.getRect().copy();
2017
2011
  }
2018
2012
  this.points.forEach((pt) => this.rect.expandInPlace(pt.getRect()));
2019
- if (this.tripletNumber) {
2020
- this.rect.expandInPlace(this.tripletNumber.getRect());
2013
+ if (this.tupletNumber) {
2014
+ this.rect.expandInPlace(this.tupletNumber.getRect());
2021
2015
  }
2022
2016
  }
2023
2017
  };
2024
2018
  var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2025
- constructor(symbols, triplet) {
2019
+ constructor(symbols, tupletRatio) {
2026
2020
  super(symbols[0].measure);
2027
2021
  this.symbols = symbols;
2022
+ this.tupletRatio = tupletRatio;
2028
2023
  __publicField(this, "mi");
2029
2024
  __publicField(this, "type");
2030
2025
  __publicField(this, "staffObjects", []);
2031
2026
  this.mi = new MBeamGroup(this);
2027
+ let beamGroupName = tupletRatio ? "Tuplet" : "BeamGroup";
2032
2028
  if (!symbols.every((s) => s.measure === symbols[0].measure)) {
2033
- throw new import_core6.MusicError(import_core6.MusicErrorType.Score, "All beam group symbols are not in same measure.");
2029
+ throw new import_core6.MusicError(import_core6.MusicErrorType.Score, `All ${beamGroupName} symbols are not in same measure.`);
2034
2030
  } else if (symbols.length < 2) {
2035
- throw new import_core6.MusicError(import_core6.MusicErrorType.Score, "Beam group need minimum 2 symbols, but " + symbols.length + " given.");
2031
+ throw new import_core6.MusicError(import_core6.MusicErrorType.Score, `${beamGroupName} needs minimum 2 symbols, but ${symbols.length} given.`);
2036
2032
  }
2037
- if (triplet) {
2038
- if (!symbols.every((s) => s.triplet)) {
2039
- throw new import_core6.MusicError(import_core6.MusicErrorType.Score, "Not every symbol's triplet property is true.");
2040
- }
2033
+ if (tupletRatio !== void 0) {
2041
2034
  let isGroup = symbols.length < 3 || symbols.some((s) => !(s instanceof ObjNoteGroup)) || symbols.some((s) => s.rhythmProps.flagCount !== symbols[0].rhythmProps.flagCount);
2042
- if (symbols.length === 3 && symbols[0] instanceof ObjNoteGroup && symbols[symbols.length - 1] instanceof ObjNoteGroup && symbols[0].rhythmProps.flagCount === symbols[symbols.length - 1].rhythmProps.flagCount) {
2035
+ if (symbols.length >= 3 && symbols[0] instanceof ObjNoteGroup && symbols[symbols.length - 1] instanceof ObjNoteGroup && symbols[0].rhythmProps.flagCount === symbols[symbols.length - 1].rhythmProps.flagCount) {
2043
2036
  isGroup = false;
2044
2037
  }
2045
- if (symbols.some((s) => s.rhythmProps.noteLength >= import_theory4.NoteLength.Quarter)) {
2038
+ if (symbols.some((s) => import_theory4.NoteLengthProps.cmp(s.rhythmProps.noteLength, import_theory4.NoteLength.Quarter) >= 0)) {
2046
2039
  isGroup = true;
2047
2040
  }
2048
- this.type = isGroup ? 2 /* TripletGroup */ : 1 /* TripletBeam */;
2049
- ObjNoteGroup.setTripletBeamCounts(this);
2041
+ this.type = isGroup ? 2 /* TupletGroup */ : 1 /* TupletBeam */;
2042
+ ObjNoteGroup.setTupletBeamCounts(this);
2050
2043
  } else {
2051
2044
  this.type = 0 /* RegularBeam */;
2052
2045
  }
@@ -2054,29 +2047,35 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2054
2047
  symbols.forEach((s) => s.setBeamGroup(this));
2055
2048
  symbols[0].measure.addBeamGroup(this);
2056
2049
  } else {
2057
- throw new import_core6.MusicError(import_core6.MusicErrorType.Score, "Cannot add beam group because some symbol already has one.");
2050
+ throw new import_core6.MusicError(import_core6.MusicErrorType.Score, `Cannot add ${beamGroupName} because some symbol already has one.`);
2058
2051
  }
2059
2052
  }
2053
+ get showTupletRatio() {
2054
+ var _a;
2055
+ return ((_a = this.tupletRatio) == null ? void 0 : _a.showRatio) === true;
2056
+ }
2060
2057
  static createBeam(noteGroups) {
2061
2058
  if (noteGroups.length > 1) {
2062
- new _ObjBeamGroup(noteGroups, false);
2059
+ new _ObjBeamGroup(noteGroups, void 0);
2063
2060
  }
2064
2061
  }
2065
- static createTriplet(symbols) {
2066
- let MaxTripletNoteLenght = import_theory4.NoteLength.Half;
2067
- let len = symbols.map((s) => s.rhythmProps.noteLength);
2068
- if (symbols.length == 2) {
2069
- if (len[0] <= MaxTripletNoteLenght && len[1] === len[0] / 2 && len[0] / 2 >= import_theory4.MinNoteLength || len[1] <= MaxTripletNoteLenght && len[0] === len[1] / 2 && len[1] / 2 >= import_theory4.MinNoteLength) {
2070
- new _ObjBeamGroup(symbols, true);
2071
- return true;
2072
- }
2073
- } else if (symbols.length === 3) {
2074
- if (len[0] <= MaxTripletNoteLenght && len.every((l) => l === len[0])) {
2075
- new _ObjBeamGroup(symbols, true);
2076
- return true;
2077
- }
2062
+ static createOldStyleTriplet(symbols) {
2063
+ let s2 = symbols.slice(0, 2);
2064
+ let n2 = s2.map((s) => s.rhythmProps.noteSize);
2065
+ if (s2.length === 2 && s2.every((s) => s.oldStyleTriplet && s.getBeamGroup() === void 0) && (n2[0] * 2 === n2[1] || n2[1] * 2 === n2[0])) {
2066
+ new _ObjBeamGroup(s2, import_theory4.Tuplet.Triplet);
2067
+ return 2;
2078
2068
  }
2079
- return false;
2069
+ let s3 = symbols.slice(0, 3);
2070
+ let n3 = s3.map((s) => s.rhythmProps.noteSize);
2071
+ if (s3.length === 3 && s3.every((s) => s.oldStyleTriplet && s.getBeamGroup() === void 0) && n3.every((n) => n === n3[0])) {
2072
+ new _ObjBeamGroup(s3, import_theory4.Tuplet.Triplet);
2073
+ return 3;
2074
+ }
2075
+ return 0;
2076
+ }
2077
+ static createTuplet(symbols, tupletRatio) {
2078
+ new _ObjBeamGroup(symbols, tupletRatio);
2080
2079
  }
2081
2080
  getMusicInterface() {
2082
2081
  return this.mi;
@@ -2102,8 +2101,8 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2102
2101
  getType() {
2103
2102
  return this.type;
2104
2103
  }
2105
- isTriplet() {
2106
- return this.type === 1 /* TripletBeam */ || this.type === 2 /* TripletGroup */;
2104
+ isTuplet() {
2105
+ return this.type === 1 /* TupletBeam */ || this.type === 2 /* TupletGroup */;
2107
2106
  }
2108
2107
  getSymbols() {
2109
2108
  return this.symbols;
@@ -2165,10 +2164,10 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2165
2164
  }
2166
2165
  let leftStemHeight = (_a = symbolStemHeight[0]) != null ? _a : 0;
2167
2166
  let rightStemHeight = (_b = symbolStemHeight[symbolStemHeight.length - 1]) != null ? _b : 0;
2168
- if (this.type !== 2 /* TripletGroup */) {
2167
+ if (this.type !== 2 /* TupletGroup */) {
2169
2168
  let leftDy = leftStemHeight < rightStemHeight ? Math.sqrt(rightStemHeight - leftStemHeight) : 0;
2170
2169
  let rightDy = rightStemHeight < leftStemHeight ? Math.sqrt(leftStemHeight - rightStemHeight) : 0;
2171
- if (stemDir === 1 /* Up */) {
2170
+ if (stemDir === "up" /* Up */) {
2172
2171
  leftDy *= -1;
2173
2172
  rightDy *= -1;
2174
2173
  }
@@ -2181,7 +2180,7 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2181
2180
  symbolY[symbolY.length - 1] += rightDy;
2182
2181
  }
2183
2182
  }
2184
- let groupLineDy = unitSize * 2 * (stemDir === 1 /* Up */ ? -1 : 1);
2183
+ let groupLineDy = unitSize * 2 * (stemDir === "up" /* Up */ ? -1 : 1);
2185
2184
  let centerY = (rightY + leftY) / 2;
2186
2185
  let halfDy = adjustBeamAngle(rightX - leftX, rightY - leftY) / 2;
2187
2186
  leftY = centerY - halfDy;
@@ -2192,9 +2191,9 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2192
2191
  if (symX !== void 0 && symY !== void 0) {
2193
2192
  let beamY = import_ts_utils_lib3.Utils.Math.interpolateY(leftX, leftY, rightX, rightY, symX);
2194
2193
  let raiseY = symY - beamY;
2195
- if (stemDir === 1 /* Up */ && raiseY < 0) {
2194
+ if (stemDir === "up" /* Up */ && raiseY < 0) {
2196
2195
  raiseBeamY = Math.min(raiseBeamY, raiseY);
2197
- } else if (stemDir === 2 /* Down */ && raiseY > 0) {
2196
+ } else if (stemDir === "down" /* Down */ && raiseY > 0) {
2198
2197
  raiseBeamY = Math.max(raiseBeamY, raiseY);
2199
2198
  }
2200
2199
  }
@@ -2203,21 +2202,21 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2203
2202
  rightY += raiseBeamY;
2204
2203
  symbolY = symbolY.map((y) => y === void 0 ? void 0 : y + raiseBeamY);
2205
2204
  let obj = new ObjStaffBeamGroup(mainStaff, this);
2206
- if (this.type === 2 /* TripletGroup */) {
2205
+ if (this.type === 2 /* TupletGroup */) {
2207
2206
  let ef = unitSize / (rightX - leftX);
2208
2207
  let l = import_ts_utils_lib3.Utils.Math.interpolateCoord(leftX, leftY + groupLineDy, rightX, rightY + groupLineDy, -ef);
2209
2208
  let r = import_ts_utils_lib3.Utils.Math.interpolateCoord(leftX, leftY + groupLineDy, rightX, rightY + groupLineDy, 1 + ef);
2210
2209
  obj.points.push(new BeamPoint(leftStaff, this, leftSymbol, l.x, l.y));
2211
2210
  obj.points.push(new BeamPoint(rightStaff, this, rightSymbol, r.x, r.y));
2212
- obj.tripletNumberOffsetY = 0;
2213
- } else if (this.type === 0 /* RegularBeam */ || this.type === 1 /* TripletBeam */) {
2211
+ obj.tupletNumberOffsetY = 0;
2212
+ } else if (this.type === 0 /* RegularBeam */ || this.type === 1 /* TupletBeam */) {
2214
2213
  raiseBeamY *= 0.5;
2215
2214
  let { beamThickness } = renderer;
2216
2215
  const beamHeight = (i) => {
2217
2216
  let sym = symbols[i];
2218
2217
  if (sym instanceof ObjNoteGroup) {
2219
2218
  let beamCount = sym instanceof ObjNoteGroup ? Math.max(sym.getLeftBeamCount(), sym.getRightBeamCount()) : 0;
2220
- return DocumentSettings.BeamSeparation * unitSize * (this.stemDir === 1 /* Up */ ? beamCount - 1 : 0);
2219
+ return DocumentSettings.BeamSeparation * unitSize * (this.stemDir === "up" /* Up */ ? beamCount - 1 : 0);
2221
2220
  } else {
2222
2221
  return 0;
2223
2222
  }
@@ -2228,17 +2227,18 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2228
2227
  let symY = symbolY[i];
2229
2228
  if (symStaff && symX !== void 0 && symY !== void 0) {
2230
2229
  let pt = new BeamPoint(symStaff, this, sym, symX, symY);
2231
- pt.topBeamsHeight = beamThickness / 2 + (stemDir === 2 /* Down */ ? beamHeight(i) : 0);
2232
- pt.bottomBeamsHeight = beamThickness / 2 + (stemDir === 1 /* Up */ ? beamHeight(i) : 0);
2230
+ pt.topBeamsHeight = beamThickness / 2 + (stemDir === "down" /* Down */ ? beamHeight(i) : 0);
2231
+ pt.bottomBeamsHeight = beamThickness / 2 + (stemDir === "up" /* Up */ ? beamHeight(i) : 0);
2233
2232
  obj.points.push(pt);
2234
2233
  }
2235
2234
  });
2236
- obj.tripletNumberOffsetY = groupLineDy;
2235
+ obj.tupletNumberOffsetY = groupLineDy;
2237
2236
  }
2238
- if (this.isTriplet()) {
2239
- obj.tripletNumber = new ObjText(this, "3", 0.5, 0.5);
2240
- obj.tripletNumber.layout(renderer);
2241
- obj.tripletNumber.offset((leftX + rightX) / 2, (leftY + rightY) / 2 + obj.tripletNumberOffsetY);
2237
+ if (this.isTuplet() && this.tupletRatio) {
2238
+ let txt = this.showTupletRatio ? String(this.tupletRatio.parts) + ":" + String(this.tupletRatio.inTimeOf) : String(this.tupletRatio.parts);
2239
+ obj.tupletNumber = new ObjText(this, txt, 0.5, 0.5);
2240
+ obj.tupletNumber.layout(renderer);
2241
+ obj.tupletNumber.offset((leftX + rightX) / 2, (leftY + rightY) / 2 + obj.tupletNumberOffsetY);
2242
2242
  }
2243
2243
  if (obj.points.length >= 2) {
2244
2244
  this.staffObjects.push(obj);
@@ -2260,7 +2260,7 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2260
2260
  this.staffObjects.forEach((obj) => {
2261
2261
  let left = obj.points[0];
2262
2262
  let right = obj.points[obj.points.length - 1];
2263
- if (this.type !== 2 /* TripletGroup */) {
2263
+ if (this.type !== 2 /* TupletGroup */) {
2264
2264
  obj.points.forEach((pt) => {
2265
2265
  if (pt.symbol instanceof ObjNoteGroup) {
2266
2266
  if (pt !== left && pt !== right) {
@@ -2270,9 +2270,9 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2270
2270
  }
2271
2271
  });
2272
2272
  }
2273
- if (obj.tripletNumber) {
2274
- let y = (left.y + right.y) / 2 + obj.tripletNumberOffsetY;
2275
- obj.tripletNumber.offset(0, -obj.tripletNumber.getRect().centerY + y);
2273
+ if (obj.tupletNumber) {
2274
+ let y = (left.y + right.y) / 2 + obj.tupletNumberOffsetY;
2275
+ obj.tupletNumber.offset(0, -obj.tupletNumber.getRect().centerY + y);
2276
2276
  }
2277
2277
  });
2278
2278
  }
@@ -2284,21 +2284,21 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2284
2284
  let { unitSize, beamThickness, lineWidth } = renderer;
2285
2285
  let color = "black";
2286
2286
  this.staffObjects.forEach((obj) => {
2287
- if (this.type === 2 /* TripletGroup */) {
2287
+ if (this.type === 2 /* TupletGroup */) {
2288
2288
  let l = obj.points[0];
2289
2289
  let r = obj.points[obj.points.length - 1];
2290
2290
  if (l && r) {
2291
- let tf = obj.tripletNumber ? obj.tripletNumber.getRect().width / (r.x - l.x) * 1.2 : 0;
2291
+ let tf = obj.tupletNumber ? obj.tupletNumber.getRect().width / (r.x - l.x) * 1.2 : 0;
2292
2292
  let lc = import_ts_utils_lib3.Utils.Math.interpolateCoord(l.x, l.y, r.x, r.y, 0.5 - tf / 2);
2293
2293
  let rc = import_ts_utils_lib3.Utils.Math.interpolateCoord(l.x, l.y, r.x, r.y, 0.5 + tf / 2);
2294
- let tipH = this.stemDir === 1 /* Up */ ? unitSize : -unitSize;
2294
+ let tipH = this.stemDir === "up" /* Up */ ? unitSize : -unitSize;
2295
2295
  renderer.drawLine(l.x, l.y, lc.x, lc.y, color, lineWidth);
2296
2296
  renderer.drawLine(rc.x, rc.y, r.x, r.y, color, lineWidth);
2297
2297
  renderer.drawLine(l.x, l.y, l.x, l.y + tipH, color, lineWidth);
2298
2298
  renderer.drawLine(r.x, r.y, r.x, r.y + tipH, color, lineWidth);
2299
2299
  }
2300
- } else if (this.type === 0 /* RegularBeam */ || this.type === 1 /* TripletBeam */) {
2301
- let beamSeparation = DocumentSettings.BeamSeparation * unitSize * (this.stemDir === 1 /* Up */ ? 1 : -1);
2300
+ } else if (this.type === 0 /* RegularBeam */ || this.type === 1 /* TupletBeam */) {
2301
+ let beamSeparation = DocumentSettings.BeamSeparation * unitSize * (this.stemDir === "up" /* Up */ ? 1 : -1);
2302
2302
  let noteGroupPoints = obj.points.filter((p) => p.symbol instanceof ObjNoteGroup);
2303
2303
  for (let i = 0; i < noteGroupPoints.length - 1; i++) {
2304
2304
  let left = noteGroupPoints[i];
@@ -2325,8 +2325,8 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2325
2325
  }
2326
2326
  }
2327
2327
  }
2328
- if (obj.tripletNumber) {
2329
- obj.tripletNumber.draw(renderer);
2328
+ if (obj.tupletNumber) {
2329
+ obj.tupletNumber.draw(renderer);
2330
2330
  }
2331
2331
  });
2332
2332
  }
@@ -2334,6 +2334,12 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2334
2334
 
2335
2335
  // src/score/engine/obj-note-group.ts
2336
2336
  var import_core7 = require("@tspro/web-music-score/core");
2337
+ function getStem(stem) {
2338
+ return import_ts_utils_lib4.Utils.Is.isEnumValue(stem, Stem) ? stem : void 0;
2339
+ }
2340
+ function getArpeggio(a) {
2341
+ return import_ts_utils_lib4.Utils.Is.isEnumValue(a, Arpeggio) ? a : a === true ? "up" /* Up */ : void 0;
2342
+ }
2337
2343
  function sortNoteStringData(notes, strings) {
2338
2344
  let stringArr = import_ts_utils_lib4.Utils.Arr.isArray(strings) ? strings : strings !== void 0 ? [strings] : [];
2339
2345
  let noteStringData = notes.map((note, i) => {
@@ -2345,9 +2351,6 @@ function sortNoteStringData(notes, strings) {
2345
2351
  strings: noteStringData.every((e) => e.string === void 0) ? void 0 : noteStringData.map((e) => e.string)
2346
2352
  };
2347
2353
  }
2348
- function solveArpeggio(a) {
2349
- return a === true || a === 0 /* Up */ ? 0 /* Up */ : a === 1 /* Down */ ? 1 /* Down */ : void 0;
2350
- }
2351
2354
  var ObjStaffNoteGroup = class extends MusicObject {
2352
2355
  constructor(staff, noteGroup) {
2353
2356
  super(staff);
@@ -2437,7 +2440,7 @@ var ObjTabNoteGroup = class extends MusicObject {
2437
2440
  }
2438
2441
  };
2439
2442
  var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2440
- constructor(col, voiceId, notes, noteLength, options) {
2443
+ constructor(col, voiceId, notes, noteLength, options, tupletRatio) {
2441
2444
  var _a, _b, _c;
2442
2445
  super(col);
2443
2446
  this.col = col;
@@ -2453,6 +2456,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2453
2456
  __publicField(this, "staccato");
2454
2457
  __publicField(this, "diamond");
2455
2458
  __publicField(this, "arpeggio");
2459
+ __publicField(this, "oldStyleTriplet");
2456
2460
  __publicField(this, "rhythmProps");
2457
2461
  __publicField(this, "startConnnectives", []);
2458
2462
  __publicField(this, "runningConnectives", []);
@@ -2470,13 +2474,15 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2470
2474
  this.minDiatonicId = this.notes[0].diatonicId;
2471
2475
  this.maxDiatonicId = this.notes[this.notes.length - 1].diatonicId;
2472
2476
  this.ownDiatonicId = this.measure.updateOwnDiatonicId(voiceId, Math.round((this.minDiatonicId + this.maxDiatonicId) / 2));
2473
- this.ownStemDir = this.measure.updateOwnStemDir(this, options == null ? void 0 : options.stem);
2477
+ this.ownStemDir = this.measure.updateOwnStemDir(this, getStem(options == null ? void 0 : options.stem));
2474
2478
  this.ownString = this.measure.updateOwnString(this, noteStringData.strings);
2475
2479
  this.color = (_a = options == null ? void 0 : options.color) != null ? _a : "black";
2476
2480
  this.staccato = (_b = options == null ? void 0 : options.staccato) != null ? _b : false;
2477
2481
  this.diamond = (_c = options == null ? void 0 : options.diamond) != null ? _c : false;
2478
- this.arpeggio = solveArpeggio(options == null ? void 0 : options.arpeggio);
2479
- this.rhythmProps = new import_theory5.RhythmProps(noteLength, options == null ? void 0 : options.dotted, options == null ? void 0 : options.triplet);
2482
+ this.arpeggio = getArpeggio(options == null ? void 0 : options.arpeggio);
2483
+ this.oldStyleTriplet = tupletRatio === void 0 && ((options == null ? void 0 : options.triplet) === true || import_theory5.NoteLengthProps.get(noteLength).isTriplet);
2484
+ let dotCount = typeof (options == null ? void 0 : options.dotted) === "number" ? options.dotted > 0 ? options.dotted : void 0 : (options == null ? void 0 : options.dotted) === true ? 1 : void 0;
2485
+ this.rhythmProps = import_theory5.RhythmProps.get(noteLength, dotCount, (tupletRatio != null ? tupletRatio : this.oldStyleTriplet) ? import_theory5.Tuplet.Triplet : void 0);
2480
2486
  this.mi = new MNoteGroup(this);
2481
2487
  }
2482
2488
  getMusicInterface() {
@@ -2494,16 +2500,13 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2494
2500
  get stemDir() {
2495
2501
  return this.beamGroup ? this.beamGroup.stemDir : this.ownStemDir;
2496
2502
  }
2497
- get triplet() {
2498
- return this.rhythmProps.triplet;
2499
- }
2500
2503
  enableConnective(line) {
2501
2504
  return line.containsVoiceId(this.voiceId) && (line instanceof ObjTab || line.containsDiatonicId(this.ownDiatonicId));
2502
2505
  }
2503
2506
  startConnective(connectiveProps) {
2504
- if (!this.row.hasStaff && connectiveProps.connective === 0 /* Tie */) {
2507
+ if (!this.row.hasStaff && connectiveProps.connective === "tie" /* Tie */) {
2505
2508
  throw new import_core7.MusicError(import_core7.MusicErrorType.Score, "Ties not implemented for guitar tabs alone, staff is required!");
2506
- } else if (!this.row.hasStaff && connectiveProps.connective === 1 /* Slur */) {
2509
+ } else if (!this.row.hasStaff && connectiveProps.connective === "slur" /* Slur */) {
2507
2510
  throw new import_core7.MusicError(import_core7.MusicErrorType.Score, "Slurs not implemented for guitar tabs alone, staff is required!");
2508
2511
  }
2509
2512
  this.startConnnectives.push(connectiveProps);
@@ -2562,7 +2565,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2562
2565
  let stemTip = obj.stemTip;
2563
2566
  let stemDir = this.stemDir;
2564
2567
  let hasStem = stemTip !== void 0;
2565
- let stemSide = !hasStem ? void 0 : stemDir === 1 /* Up */ ? "right" : "left";
2568
+ let stemSide = !hasStem ? void 0 : stemDir === "up" /* Up */ ? "right" : "left";
2566
2569
  let padding = noteHeadRect.height / 2;
2567
2570
  let centerX = noteHeadRect.centerX;
2568
2571
  let centerY = noteHeadRect.centerY;
@@ -2570,16 +2573,16 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2570
2573
  let rightX = noteHeadRect.right + padding;
2571
2574
  let aboveY = noteHeadRect.top - padding;
2572
2575
  let belowY = noteHeadRect.bottom + padding;
2573
- if (noteAnchor === 0 /* Auto */) {
2574
- noteAnchor = 3 /* Below */;
2575
- } else if (noteAnchor === 4 /* StemTip */ && !hasStem) {
2576
- noteAnchor = stemDir === 1 /* Up */ ? 1 /* Above */ : 3 /* Below */;
2576
+ if (noteAnchor === "auto" /* Auto */) {
2577
+ noteAnchor = "below" /* Below */;
2578
+ } else if (noteAnchor === "stemTip" /* StemTip */ && !hasStem) {
2579
+ noteAnchor = stemDir === "up" /* Up */ ? "above" /* Above */ : "below" /* Below */;
2577
2580
  }
2578
2581
  switch (noteAnchor) {
2579
- case 2 /* Center */:
2582
+ case "center" /* Center */:
2580
2583
  return side === "left" ? { x: rightX, y: centerY } : { x: leftX, y: centerY };
2581
- case 1 /* Above */:
2582
- if (!hasStem || stemDir === 2 /* Down */) {
2584
+ case "above" /* Above */:
2585
+ if (!hasStem || stemDir === "down" /* Down */) {
2583
2586
  return { x: centerX, y: aboveY };
2584
2587
  } else {
2585
2588
  return {
@@ -2587,8 +2590,8 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2587
2590
  y: aboveY
2588
2591
  };
2589
2592
  }
2590
- case 3 /* Below */:
2591
- if (!hasStem || stemDir === 1 /* Up */) {
2593
+ case "below" /* Below */:
2594
+ if (!hasStem || stemDir === "up" /* Up */) {
2592
2595
  return { x: centerX, y: belowY };
2593
2596
  } else {
2594
2597
  return {
@@ -2596,8 +2599,8 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2596
2599
  y: belowY
2597
2600
  };
2598
2601
  }
2599
- case 4 /* StemTip */:
2600
- return { x: centerX, y: stemTip.centerY + (stemDir === 1 /* Up */ ? -padding : padding) };
2602
+ case "stemTip" /* StemTip */:
2603
+ return { x: centerX, y: stemTip.centerY + (stemDir === "up" /* Up */ ? -padding : padding) };
2601
2604
  default:
2602
2605
  throw new import_core7.MusicError(import_core7.MusicErrorType.Score, "Invalid noteAnchor: " + noteAnchor);
2603
2606
  }
@@ -2612,7 +2615,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2612
2615
  let x = side === "right" ? r.left : r.right;
2613
2616
  let y;
2614
2617
  let s = 0.9;
2615
- if (connectiveProps.connective === 2 /* Slide */) {
2618
+ if (connectiveProps.connective === "slide" /* Slide */) {
2616
2619
  let leftFretNumber = connectiveProps.noteGroups[0].getFretNumber(obj, 0);
2617
2620
  let rightFretNumber = connectiveProps.noteGroups[1].getFretNumber(obj, 0);
2618
2621
  let slideUp = leftFretNumber === void 0 || rightFretNumber === void 0 || leftFretNumber <= rightFretNumber;
@@ -2666,7 +2669,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2666
2669
  this.runningConnectives = [];
2667
2670
  }
2668
2671
  getPlaySlur() {
2669
- let slurs = this.runningConnectives.filter((c) => c.connective === 1 /* Slur */).map((c) => c.startsWith(this) ? "first" : "slurred");
2672
+ let slurs = this.runningConnectives.filter((c) => c.connective === "slur" /* Slur */).map((c) => c.startsWith(this) ? "first" : "slurred");
2670
2673
  if (slurs.indexOf("first") >= 0) {
2671
2674
  return "first";
2672
2675
  } else if (slurs.indexOf("slurred") >= 0) {
@@ -2678,8 +2681,8 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2678
2681
  getBeamGroup() {
2679
2682
  return this.beamGroup;
2680
2683
  }
2681
- setBeamGroup(beam) {
2682
- this.beamGroup = beam;
2684
+ setBeamGroup(beamGroup) {
2685
+ this.beamGroup = beamGroup;
2683
2686
  }
2684
2687
  resetBeamGroup() {
2685
2688
  this.leftBeamCount = this.rightBeamCount = 0;
@@ -2690,19 +2693,19 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2690
2693
  var _a, _b, _c, _d;
2691
2694
  let staff = obj.staff;
2692
2695
  let x = (_b = (_a = obj.stemTip) == null ? void 0 : _a.centerX) != null ? _b : obj.noteHeadRects[0].centerX;
2693
- let y = (_d = (_c = obj.stemTip) == null ? void 0 : _c.centerY) != null ? _d : this.stemDir === 1 /* Up */ ? obj.getRect().top : obj.getRect().bottom;
2694
- let stemHeight = this.stemDir === 1 /* Up */ ? Math.abs(obj.noteHeadRects[0].centerY - y) : Math.abs(obj.noteHeadRects[obj.noteHeadRects.length - 1].centerY - y);
2696
+ let y = (_d = (_c = obj.stemTip) == null ? void 0 : _c.centerY) != null ? _d : this.stemDir === "up" /* Up */ ? obj.getRect().top : obj.getRect().bottom;
2697
+ let stemHeight = this.stemDir === "up" /* Up */ ? Math.abs(obj.noteHeadRects[0].centerY - y) : Math.abs(obj.noteHeadRects[obj.noteHeadRects.length - 1].centerY - y);
2695
2698
  return { staff, x, y, stemHeight };
2696
2699
  });
2697
2700
  }
2698
2701
  getStemHeight(renderer) {
2699
2702
  let { unitSize } = renderer;
2700
- let { noteLength, flagCount } = this.rhythmProps;
2701
- if (noteLength >= import_theory5.NoteLength.Whole) {
2702
- return 0;
2703
- } else {
2703
+ let { flagCount, hasStem } = this.rhythmProps;
2704
+ if (hasStem) {
2704
2705
  let addY = this.hasBeamCount() ? DocumentSettings.BeamSeparation : DocumentSettings.FlagSeparation;
2705
2706
  return (DocumentSettings.StemHeight + Math.max(0, flagCount - 1) * addY) * unitSize;
2707
+ } else {
2708
+ return 0;
2706
2709
  }
2707
2710
  }
2708
2711
  hasBeamCount() {
@@ -2721,13 +2724,13 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2721
2724
  return staff.containsVoiceId(this.voiceId) && this.staffObjects.some((obj) => obj instanceof ObjStaffNoteGroup && obj.staff === staff);
2722
2725
  }
2723
2726
  getPlayTicks(note) {
2724
- let tiedTicks = this.runningConnectives.filter((c) => c.connective === 0 /* Tie */).map((tie) => {
2727
+ let tiedTicks = this.runningConnectives.filter((c) => c.connective === "tie" /* Tie */).map((tie) => {
2725
2728
  let tieNoteGroups = tie.noteGroups;
2726
2729
  let j = tieNoteGroups.indexOf(this);
2727
2730
  if (j < 0) {
2728
2731
  return 0;
2729
2732
  }
2730
- if (tie.span === -1 /* Stub */ || tie.span === -2 /* ToMeasureEnd */) {
2733
+ if (tie.span === "stub" /* Stub */ || tie.span === "toMeasureEnd" /* ToMeasureEnd */) {
2731
2734
  return Math.max(this.rhythmProps.ticks, this.measure.getMeasureTicks() - this.col.positionTicks);
2732
2735
  }
2733
2736
  let prev = tieNoteGroups[j - 1];
@@ -2754,7 +2757,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2754
2757
  this.requestRectUpdate();
2755
2758
  let { unitSize } = renderer;
2756
2759
  let { row, stemDir } = this;
2757
- let { dotted, flagCount } = this.rhythmProps;
2760
+ let { dotCount, flagCount, hasStem } = this.rhythmProps;
2758
2761
  let dotWidth = DocumentSettings.DotSize * unitSize;
2759
2762
  let noteHeadWidth = (this.diamond ? DocumentSettings.DiamondNoteHeadSize : DocumentSettings.NoteHeadWidth) * unitSize;
2760
2763
  let noteHeadHeight = (this.diamond ? DocumentSettings.DiamondNoteHeadSize : DocumentSettings.NoteHeadHeight) * unitSize;
@@ -2774,10 +2777,10 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2774
2777
  let noteX = this.col.getNoteHeadDisplacement(this, note) * noteHeadWidth;
2775
2778
  let noteY = noteStaff.getDiatonicIdY(note.diatonicId);
2776
2779
  let isNoteOnLine = noteStaff.isLine(note.diatonicId);
2777
- if (isBottomNote && stemDir === 1 /* Up */) stemBaseStaff = noteStaff;
2778
- if (isTopNote && stemDir === 1 /* Up */) stemTipStaff = noteStaff;
2779
- if (isBottomNote && stemDir === 2 /* Down */) stemTipStaff = noteStaff;
2780
- if (isTopNote && stemDir === 2 /* Down */) stemBaseStaff = noteStaff;
2780
+ if (isBottomNote && stemDir === "up" /* Up */) stemBaseStaff = noteStaff;
2781
+ if (isTopNote && stemDir === "up" /* Up */) stemTipStaff = noteStaff;
2782
+ if (isBottomNote && stemDir === "down" /* Down */) stemTipStaff = noteStaff;
2783
+ if (isTopNote && stemDir === "down" /* Down */) stemBaseStaff = noteStaff;
2781
2784
  let noteHeadRect = obj.noteHeadRects[noteIndex] = DivRect.createCentered(noteX, noteY, noteHeadWidth, noteHeadHeight);
2782
2785
  noteStaff.addObject(noteHeadRect);
2783
2786
  if (accState.needAccidental(note)) {
@@ -2788,21 +2791,21 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2788
2791
  }
2789
2792
  noteStaff.addObject(acc);
2790
2793
  }
2791
- if (dotted) {
2792
- let dotX = noteHeadRect.right + DocumentSettings.NoteDotSpace * unitSize + dotWidth / 2;
2794
+ for (let i = 0; i < dotCount; i++) {
2795
+ let dotX = noteHeadRect.right + DocumentSettings.NoteDotSpace * unitSize + dotWidth / 2 + i * dotWidth * 1.5;
2793
2796
  let dotY = noteY + this.getDotVerticalDisplacement(staff, note.diatonicId, stemDir) * unitSize;
2794
2797
  let r = DivRect.createCentered(dotX, dotY, dotWidth, dotWidth);
2795
2798
  obj.dotRects.push(r);
2796
2799
  noteStaff.addObject(r);
2797
2800
  }
2798
2801
  if (this.staccato) {
2799
- if (stemDir === 1 /* Up */ && isBottomNote) {
2802
+ if (stemDir === "up" /* Up */ && isBottomNote) {
2800
2803
  let dotX = noteX;
2801
2804
  let dotY = noteY + unitSize * (isNoteOnLine ? 3 : 2);
2802
2805
  let r = DivRect.createCentered(dotX, dotY, dotWidth, dotWidth);
2803
2806
  obj.dotRects.push(r);
2804
2807
  stemBaseStaff.addObject(r);
2805
- } else if (stemDir === 2 /* Down */ && isTopNote) {
2808
+ } else if (stemDir === "down" /* Down */ && isTopNote) {
2806
2809
  let dotX = noteX;
2807
2810
  let dotY = noteY - unitSize * (isNoteOnLine ? 3 : 2);
2808
2811
  let r = DivRect.createCentered(dotX, dotY, dotWidth, dotWidth);
@@ -2813,11 +2816,11 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2813
2816
  });
2814
2817
  let bottomNoteY = obj.noteHeadRects[0].centerY;
2815
2818
  let topNoteY = obj.noteHeadRects[obj.noteHeadRects.length - 1].centerY;
2816
- let stemX = stemDir === 1 /* Up */ ? noteHeadWidth / 2 : -noteHeadWidth / 2;
2819
+ let stemX = stemDir === "up" /* Up */ ? noteHeadWidth / 2 : -noteHeadWidth / 2;
2817
2820
  let stemHeight = this.getStemHeight(renderer);
2818
- let stemTipY = stemDir === 1 /* Up */ ? topNoteY - stemHeight : bottomNoteY + stemHeight;
2819
- let stemBaseY = stemDir === 1 /* Up */ ? bottomNoteY : topNoteY;
2820
- if (this.rhythmProps.hasStem()) {
2821
+ let stemTipY = stemDir === "up" /* Up */ ? topNoteY - stemHeight : bottomNoteY + stemHeight;
2822
+ let stemBaseY = stemDir === "up" /* Up */ ? bottomNoteY : topNoteY;
2823
+ if (hasStem) {
2821
2824
  obj.stemTip = new DivRect(stemX, stemX, stemTipY, stemTipY);
2822
2825
  obj.stemBase = new DivRect(stemX, stemX, stemBaseY, stemBaseY);
2823
2826
  stemTipStaff.addObject(obj.stemTip);
@@ -2828,7 +2831,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2828
2831
  let flagHeight = flagCount === 0 ? 0 : DocumentSettings.FlagHeight * unitSize;
2829
2832
  for (let i = 0; i < flagCount; i++) {
2830
2833
  let flagAddY = i * unitSize * DocumentSettings.FlagSeparation;
2831
- let r = obj.flagRects[i] = stemDir === 1 /* Up */ ? new DivRect(stemX, stemX + flagWidth, stemTipY + flagAddY, stemTipY + flagHeight + flagAddY) : new DivRect(stemX, stemX + flagWidth, stemTipY - flagHeight - flagAddY, stemTipY - flagAddY);
2834
+ let r = obj.flagRects[i] = stemDir === "up" /* Up */ ? new DivRect(stemX, stemX + flagWidth, stemTipY + flagAddY, stemTipY + flagHeight + flagAddY) : new DivRect(stemX, stemX + flagWidth, stemTipY - flagHeight - flagAddY, stemTipY - flagAddY);
2832
2835
  stemTipStaff.addObject(r);
2833
2836
  }
2834
2837
  }
@@ -2841,7 +2844,6 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2841
2844
  }
2842
2845
  let obj = new ObjTabNoteGroup(tab, this);
2843
2846
  this.notes.forEach((note, noteIndex) => {
2844
- var _a, _b;
2845
2847
  if (this.ownString[noteIndex] !== void 0) {
2846
2848
  let stringId = this.ownString[noteIndex] - 1;
2847
2849
  let fretId = note.chromaticId - tab.getTuningStrings()[stringId].chromaticId;
@@ -2849,9 +2851,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2849
2851
  let fretNumber = new ObjText(this, { text: String(fretId), color, bgcolor: "white" }, 0.5, 0.5);
2850
2852
  obj.fretNumbers.push(fretNumber);
2851
2853
  fretNumber.layout(renderer);
2852
- let noteX = this.col.getNoteHeadDisplacement(this, note) * noteHeadWidth;
2853
- let stemX = (_b = (_a = this.staffObjects[0]) == null ? void 0 : _a.stemBase) == null ? void 0 : _b.centerX;
2854
- let x = stemX != null ? stemX : noteX;
2854
+ let x = this.col.getRect().centerX;
2855
2855
  let y = tab.getStringY(stringId);
2856
2856
  fretNumber.offset(x, y);
2857
2857
  }
@@ -2894,15 +2894,22 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2894
2894
  renderer.drawDebugRect(this.getRect());
2895
2895
  let { lineWidth } = renderer;
2896
2896
  let { color, stemDir } = this;
2897
- let { noteLength } = this.rhythmProps;
2897
+ let { isSolidNoteHead } = this.rhythmProps;
2898
2898
  this.staffObjects.forEach((obj) => {
2899
2899
  obj.accidentals.forEach((d) => d.draw(renderer));
2900
2900
  ctx.strokeStyle = ctx.fillStyle = color;
2901
2901
  ctx.lineWidth = lineWidth;
2902
2902
  obj.noteHeadRects.forEach((r) => {
2903
- let outlinedNoteHead = noteLength >= import_theory5.NoteLength.Half;
2904
2903
  if (this.diamond) {
2905
- if (outlinedNoteHead) {
2904
+ if (isSolidNoteHead) {
2905
+ ctx.beginPath();
2906
+ ctx.moveTo(r.centerX, r.top);
2907
+ ctx.lineTo(r.right, r.centerY);
2908
+ ctx.lineTo(r.centerX, r.bottom);
2909
+ ctx.lineTo(r.left, r.centerY);
2910
+ ctx.lineTo(r.centerX, r.top);
2911
+ ctx.fill();
2912
+ } else {
2906
2913
  ctx.beginPath();
2907
2914
  ctx.lineWidth = lineWidth * 2.5;
2908
2915
  ctx.moveTo(r.centerX, r.top);
@@ -2917,22 +2924,14 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2917
2924
  ctx.moveTo(r.centerX, r.top);
2918
2925
  ctx.lineTo(r.left, r.centerY);
2919
2926
  ctx.stroke();
2920
- } else {
2921
- ctx.beginPath();
2922
- ctx.moveTo(r.centerX, r.top);
2923
- ctx.lineTo(r.right, r.centerY);
2924
- ctx.lineTo(r.centerX, r.bottom);
2925
- ctx.lineTo(r.left, r.centerY);
2926
- ctx.lineTo(r.centerX, r.top);
2927
- ctx.fill();
2928
2927
  }
2929
2928
  } else {
2930
2929
  ctx.beginPath();
2931
2930
  ctx.ellipse(r.centerX, r.centerY, r.leftw, r.toph, -0.3, 0, Math.PI * 2);
2932
- if (outlinedNoteHead) {
2933
- ctx.stroke();
2934
- } else {
2931
+ if (isSolidNoteHead) {
2935
2932
  ctx.fill();
2933
+ } else {
2934
+ ctx.stroke();
2936
2935
  }
2937
2936
  }
2938
2937
  });
@@ -2947,8 +2946,8 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2947
2946
  let left = rect.left;
2948
2947
  let right = rect.right;
2949
2948
  let width = right - left;
2950
- let top = stemDir === 1 /* Up */ ? rect.top : rect.bottom;
2951
- let bottom = stemDir === 1 /* Up */ ? rect.bottom : rect.top;
2949
+ let top = stemDir === "up" /* Up */ ? rect.top : rect.bottom;
2950
+ let bottom = stemDir === "up" /* Up */ ? rect.bottom : rect.top;
2952
2951
  ctx.beginPath();
2953
2952
  ctx.moveTo(left, top);
2954
2953
  ctx.bezierCurveTo(
@@ -2962,13 +2961,13 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2962
2961
  ctx.stroke();
2963
2962
  });
2964
2963
  });
2965
- this.tabObjects.forEach((obj) => {
2966
- obj.fretNumbers.forEach((fn) => fn.draw(renderer));
2967
- });
2964
+ this.tabObjects.forEach((obj) => obj.fretNumbers.forEach((fn) => fn.draw(renderer)));
2968
2965
  }
2969
2966
  static setBeamCounts(groupNotes) {
2970
2967
  const isADottedBHalf = (a, b) => {
2971
- return a.rhythmProps.noteLength === b.rhythmProps.noteLength * 2 && a.rhythmProps.dotted && !b.rhythmProps.dotted && a.rhythmProps.flagCount > 0 && b.rhythmProps.flagCount > 0;
2968
+ let { flagCount: aFlagCount, noteSize: aNoteSize, dotCount: aDotCount } = a.rhythmProps;
2969
+ let { flagCount: bFlagCount, noteSize: bNoteSize, dotCount: bDotCount } = b.rhythmProps;
2970
+ return aFlagCount > 0 && bFlagCount > 0 && aDotCount > 0 && bDotCount === 0 && aNoteSize * Math.pow(2, aDotCount) === bNoteSize;
2972
2971
  };
2973
2972
  for (let i = 0; i < groupNotes.length; i++) {
2974
2973
  let center = groupNotes[i];
@@ -3014,29 +3013,27 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
3014
3013
  }
3015
3014
  } while (fixAgain);
3016
3015
  }
3017
- static setTripletBeamCounts(triplet) {
3018
- let type = triplet.getType();
3019
- let symbols = triplet.getSymbols();
3020
- if (type === 1 /* TripletBeam */) {
3016
+ static setTupletBeamCounts(tuplet) {
3017
+ let type = tuplet.getType();
3018
+ let symbols = tuplet.getSymbols();
3019
+ if (type === 1 /* TupletBeam */) {
3021
3020
  symbols.forEach((s, i) => {
3022
3021
  if (s instanceof _ObjNoteGroup) {
3023
3022
  s.leftBeamCount = i === 0 ? 0 : s.rhythmProps.flagCount;
3024
3023
  s.rightBeamCount = i === symbols.length - 1 ? 0 : s.rhythmProps.flagCount;
3025
3024
  }
3026
3025
  });
3027
- } else if (type === 2 /* TripletGroup */) {
3026
+ } else if (type === 2 /* TupletGroup */) {
3028
3027
  symbols.forEach((s) => {
3029
3028
  if (s instanceof _ObjNoteGroup) {
3030
3029
  s.leftBeamCount = s.rightBeamCount = 0;
3031
3030
  }
3032
3031
  });
3033
- } else {
3034
- throw new import_core7.MusicError(import_core7.MusicErrorType.Score, "Cannot set triplet beam count because triplet beam group type is invalid.");
3035
3032
  }
3036
3033
  }
3037
3034
  getDotVerticalDisplacement(staff, diatonicId, stemDir) {
3038
3035
  if (staff.isLine(diatonicId)) {
3039
- return stemDir === 1 /* Up */ ? -1 : 1;
3036
+ return stemDir === "up" /* Up */ ? -1 : 1;
3040
3037
  } else {
3041
3038
  return 0;
3042
3039
  }
@@ -3061,7 +3058,7 @@ var import_core8 = require("@tspro/web-music-score/core");
3061
3058
  var noteHeadDataCompareFunc = (a, b) => {
3062
3059
  let cmp = import_theory6.Note.compareFunc(a.note, b.note);
3063
3060
  if (cmp === 0) {
3064
- cmp = a.noteGroup.stemDir === b.noteGroup.stemDir ? 0 : a.noteGroup.stemDir === 1 /* Up */ ? 1 : -1;
3061
+ cmp = a.noteGroup.stemDir === b.noteGroup.stemDir ? 0 : a.noteGroup.stemDir === "up" /* Up */ ? 1 : -1;
3065
3062
  }
3066
3063
  return cmp;
3067
3064
  };
@@ -3174,16 +3171,14 @@ var ObjRhythmColumn = class extends MusicObject {
3174
3171
  }
3175
3172
  getArpeggioDir() {
3176
3173
  var _a;
3177
- return (_a = this.arpeggioDir) != null ? _a : 0 /* Up */;
3174
+ return (_a = this.arpeggioDir) != null ? _a : "up" /* Up */;
3178
3175
  }
3179
3176
  setVoiceSymbol(voiceId, symbol) {
3180
3177
  validateVoiceId(voiceId);
3181
3178
  this.voiceSymbol[voiceId] = symbol;
3182
- if (symbol instanceof ObjRest) {
3183
- if (!symbol.hide && symbol.noteLength >= import_theory6.NoteLength.Half) {
3184
- this.minDiatonicId = this.minDiatonicId === void 0 ? symbol.ownDiatonicId : Math.min(this.minDiatonicId, symbol.ownDiatonicId);
3185
- this.maxDiatonicId = this.maxDiatonicId === void 0 ? symbol.ownDiatonicId : Math.max(this.maxDiatonicId, symbol.ownDiatonicId);
3186
- }
3179
+ if (symbol instanceof ObjRest && !symbol.hide) {
3180
+ this.minDiatonicId = this.minDiatonicId === void 0 ? symbol.ownDiatonicId : Math.min(this.minDiatonicId, symbol.ownDiatonicId);
3181
+ this.maxDiatonicId = this.maxDiatonicId === void 0 ? symbol.ownDiatonicId : Math.max(this.maxDiatonicId, symbol.ownDiatonicId);
3187
3182
  } else if (symbol instanceof ObjNoteGroup) {
3188
3183
  this.minDiatonicId = this.minDiatonicId === void 0 ? symbol.notes[0].diatonicId : Math.min(this.minDiatonicId, symbol.notes[0].diatonicId);
3189
3184
  this.maxDiatonicId = this.maxDiatonicId === void 0 ? symbol.notes[symbol.notes.length - 1].diatonicId : Math.max(this.maxDiatonicId, symbol.notes[symbol.notes.length - 1].diatonicId);
@@ -3199,15 +3194,18 @@ var ObjRhythmColumn = class extends MusicObject {
3199
3194
  return this.voiceSymbol[voiceId];
3200
3195
  }
3201
3196
  getMinWidth() {
3202
- let maxNoteLength = Math.max(...this.voiceSymbol.map((s) => s.rhythmProps.noteLength));
3197
+ let maxNoteSize = Math.max(...this.voiceSymbol.map((s) => s.rhythmProps.noteSize));
3203
3198
  let w = DocumentSettings.NoteHeadWidth;
3204
- switch (maxNoteLength) {
3205
- case import_theory6.NoteLength.Whole:
3199
+ switch (maxNoteSize) {
3200
+ case 1:
3206
3201
  return w * 5;
3207
- case import_theory6.NoteLength.Half:
3202
+ // whole note
3203
+ case 2:
3208
3204
  return w * 3;
3209
- case import_theory6.NoteLength.Quarter:
3205
+ // half note
3206
+ case 4:
3210
3207
  return w * 2;
3208
+ // quarter note
3211
3209
  default:
3212
3210
  return w;
3213
3211
  }
@@ -3239,7 +3237,7 @@ var ObjRhythmColumn = class extends MusicObject {
3239
3237
  if (cur.displacement !== void 0) {
3240
3238
  continue;
3241
3239
  }
3242
- let d = cur.noteGroup.stemDir === 2 /* Down */ ? -1 : 1;
3240
+ let d = cur.noteGroup.stemDir === "down" /* Down */ ? -1 : 1;
3243
3241
  if (prev && cur.note.diatonicId - prev.note.diatonicId <= 1) {
3244
3242
  cur.displacement = prev.displacement === 0 ? d : 0;
3245
3243
  } else if (next && next.note.diatonicId - cur.note.diatonicId <= 1) {
@@ -3293,7 +3291,7 @@ var ObjRhythmColumn = class extends MusicObject {
3293
3291
  }
3294
3292
  });
3295
3293
  playerNotes.sort((a, b) => import_theory6.Note.compareFunc(a.note, b.note));
3296
- if (this.hasArpeggio() && this.getArpeggioDir() === 1 /* Down */) {
3294
+ if (this.hasArpeggio() && this.getArpeggioDir() === "down" /* Down */) {
3297
3295
  playerNotes.reverse();
3298
3296
  }
3299
3297
  return playerNotes;
@@ -3410,6 +3408,9 @@ var ObjRhythmColumn = class extends MusicObject {
3410
3408
  }
3411
3409
  };
3412
3410
 
3411
+ // src/score/engine/element-data.ts
3412
+ var import_ts_utils_lib5 = require("@tspro/ts-utils-lib");
3413
+
3413
3414
  // src/score/engine/obj-special-text.ts
3414
3415
  var _ObjSpecialText = class _ObjSpecialText extends MusicObject {
3415
3416
  constructor(parent, text) {
@@ -3507,36 +3508,71 @@ __publicField(_ObjSpecialText, "Segno", "\u{1D10B}");
3507
3508
  var ObjSpecialText = _ObjSpecialText;
3508
3509
 
3509
3510
  // src/score/engine/element-data.ts
3510
- function getNavigationString(n) {
3511
- switch (n) {
3512
- case 1 /* DC_al_Coda */:
3511
+ function getNavigationString(navigation) {
3512
+ switch (navigation) {
3513
+ case "D.C. al Coda" /* DC_al_Coda */:
3513
3514
  return "D.C. al Coda";
3514
- case 0 /* DC_al_Fine */:
3515
+ case "D.C. al Fine" /* DC_al_Fine */:
3515
3516
  return "D.C. al Fine";
3516
- case 3 /* DS_al_Coda */:
3517
+ case "D.S. al Coda" /* DS_al_Coda */:
3517
3518
  return "D.S. al Coda";
3518
- case 2 /* DS_al_Fine */:
3519
+ case "D.S. al Fine" /* DS_al_Fine */:
3519
3520
  return "D.S. al Fine";
3520
- case 7 /* Fine */:
3521
+ case "Fine" /* Fine */:
3521
3522
  return "Fine";
3522
- case 6 /* Segno */:
3523
+ case "Segno" /* Segno */:
3523
3524
  return ObjSpecialText.Segno;
3524
- case 4 /* Coda */:
3525
+ case "Coda" /* Coda */:
3525
3526
  return ObjSpecialText.Coda;
3526
- case 5 /* toCoda */:
3527
+ case "toCoda" /* toCoda */:
3527
3528
  return ObjSpecialText.toCoda;
3528
3529
  default:
3529
- return Navigation[n];
3530
+ return navigation[0].toUpperCase() + navigation.substring(1);
3530
3531
  }
3531
3532
  }
3533
+ var DynamicsAnnotations = /* @__PURE__ */ ((DynamicsAnnotations2) => {
3534
+ DynamicsAnnotations2["cresc"] = "cresc.";
3535
+ DynamicsAnnotations2["decresc"] = "decresc.";
3536
+ DynamicsAnnotations2["dim"] = "dim.";
3537
+ DynamicsAnnotations2["ppp"] = "ppp";
3538
+ DynamicsAnnotations2["pp"] = "pp";
3539
+ DynamicsAnnotations2["p"] = "p";
3540
+ DynamicsAnnotations2["mp"] = "mp";
3541
+ DynamicsAnnotations2["m"] = "m";
3542
+ DynamicsAnnotations2["mf"] = "mf";
3543
+ DynamicsAnnotations2["f"] = "f";
3544
+ DynamicsAnnotations2["ff"] = "ff";
3545
+ DynamicsAnnotations2["fff"] = "fff";
3546
+ return DynamicsAnnotations2;
3547
+ })(DynamicsAnnotations || {});
3548
+ var TempoAnnotations = /* @__PURE__ */ ((TempoAnnotations2) => {
3549
+ TempoAnnotations2["accel"] = "accel.";
3550
+ TempoAnnotations2["rit"] = "rit.";
3551
+ TempoAnnotations2["a_tempo"] = "a tempo";
3552
+ return TempoAnnotations2;
3553
+ })(TempoAnnotations || {});
3532
3554
  function isDynamicsText(text) {
3533
- return ["ppp", "pp", "p", "mp", "m", "mf", "f", "ff", "fff", "cresc.", "decresc.", "dim."].indexOf(text) >= 0;
3555
+ return import_ts_utils_lib5.Utils.Is.isEnumValue(text, DynamicsAnnotations);
3534
3556
  }
3535
- function isDynamicsLevelText(text) {
3536
- return ["ppp", "pp", "p", "mp", "m", "mf", "f", "ff", "fff"].indexOf(text) >= 0;
3557
+ function getDynamicsVolume(text) {
3558
+ if (/^(p+|f+|m|mp|mf)$/.test(text)) {
3559
+ let volume = 0.5 - import_ts_utils_lib5.Utils.Str.charCount(text, "p") * 0.1 + import_ts_utils_lib5.Utils.Str.charCount(text, "f") * 0.1;
3560
+ return import_ts_utils_lib5.Utils.Math.clamp(volume, 0, 1);
3561
+ } else {
3562
+ return void 0;
3563
+ }
3537
3564
  }
3538
3565
  function isTempoText(text) {
3539
- return ["accel.", "rit.", "a tempo"].indexOf(text) >= 0;
3566
+ return import_ts_utils_lib5.Utils.Is.isEnumValue(text, TempoAnnotations);
3567
+ }
3568
+ function getAnnotation(text) {
3569
+ if (import_ts_utils_lib5.Utils.Is.isEnumValue(text, DynamicsAnnotations)) {
3570
+ return "dynamics" /* Dynamics */;
3571
+ } else if (import_ts_utils_lib5.Utils.Is.isEnumValue(text, TempoAnnotations)) {
3572
+ return "tempo" /* Tempo */;
3573
+ } else {
3574
+ return void 0;
3575
+ }
3540
3576
  }
3541
3577
 
3542
3578
  // src/score/engine/extension.ts
@@ -3595,7 +3631,7 @@ var Extension = class extends MusicObjectLink {
3595
3631
  if (prevMeasure.hasEndSection() || prevMeasure.hasEndSong()) {
3596
3632
  return "section-break";
3597
3633
  }
3598
- let elemArr = [9 /* EndRepeat */, 10 /* Ending */];
3634
+ let elemArr = ["endRepeat" /* EndRepeat */, "ending" /* Ending */];
3599
3635
  for (let i = 0; i < elemArr.length; i++) {
3600
3636
  if (prevMeasure.hasNavigation(elemArr[i])) {
3601
3637
  return "section-break";
@@ -3656,35 +3692,12 @@ var RitardandoSpeedDiv = 2;
3656
3692
  var CrescendoVolumeAdd = 0.5;
3657
3693
  var DiminuendoVolumeSub = 0.5;
3658
3694
  function calcTicksDuration(ticks, tempo) {
3659
- let beatTicks = new import_theory7.RhythmProps(tempo.options.beatLength, tempo.options.dotted).ticks;
3695
+ let beatTicks = import_theory7.RhythmProps.get(tempo.options.beatLength, tempo.options.dotCount).ticks;
3660
3696
  let ticksPerMinute = tempo.beatsPerMinute * beatTicks;
3661
3697
  return 60 * ticks / ticksPerMinute;
3662
3698
  }
3663
- function getVolume(dynamicsLevelText) {
3664
- switch (dynamicsLevelText) {
3665
- case "fff":
3666
- return 0.9;
3667
- case "ff":
3668
- return 0.8;
3669
- case "f":
3670
- return 0.7;
3671
- case "mf":
3672
- return 0.6;
3673
- default:
3674
- case "m":
3675
- return 0.5;
3676
- case "mp":
3677
- return 0.4;
3678
- case "p":
3679
- return 0.3;
3680
- case "pp":
3681
- return 0.2;
3682
- case "ppp":
3683
- return 0.1;
3684
- }
3685
- }
3686
3699
  function getDefaultVolume() {
3687
- return getVolume("m");
3700
+ return getDynamicsVolume("m");
3688
3701
  }
3689
3702
  function adjustVolume(linearVolume) {
3690
3703
  return linearVolume * 1.25;
@@ -3712,7 +3725,7 @@ var PlayerColumnProps = class {
3712
3725
  return this.speed;
3713
3726
  }
3714
3727
  getTempo() {
3715
- let speed = import_ts_utils_lib5.Utils.Math.clamp(this.getSpeed(), 0.1, 10);
3728
+ let speed = import_ts_utils_lib6.Utils.Math.clamp(this.getSpeed(), 0.1, 10);
3716
3729
  return (0, import_theory7.alterTempoSpeed)(this.measure.getTempo(), speed);
3717
3730
  }
3718
3731
  setVolume(volume) {
@@ -3737,7 +3750,7 @@ var PlayerColumnProps = class {
3737
3750
  if (symbolsTicks.length === 0) {
3738
3751
  return 0;
3739
3752
  } else {
3740
- return import_ts_utils_lib5.Utils.Math.sum(symbolsTicks) / symbolsTicks.length;
3753
+ return import_ts_utils_lib6.Utils.Math.sum(symbolsTicks) / symbolsTicks.length;
3741
3754
  }
3742
3755
  }
3743
3756
  }
@@ -3800,34 +3813,34 @@ var Player = class _Player {
3800
3813
  continue;
3801
3814
  }
3802
3815
  measureSequence.push(curMeasure);
3803
- if (curMeasure.hasNavigation(8 /* StartRepeat */)) {
3816
+ if (curMeasure.hasNavigation("startRepeat" /* StartRepeat */)) {
3804
3817
  startRepeatMeasure = curMeasure;
3805
3818
  }
3806
- if (curMeasure.hasNavigation(6 /* Segno */)) {
3819
+ if (curMeasure.hasNavigation("Segno" /* Segno */)) {
3807
3820
  segnoMeasure = curMeasure;
3808
3821
  }
3809
- if (alCoda && curMeasure.hasNavigation(5 /* toCoda */)) {
3810
- while (curMeasure && !curMeasure.hasNavigation(4 /* Coda */)) {
3822
+ if (alCoda && curMeasure.hasNavigation("toCoda" /* toCoda */)) {
3823
+ while (curMeasure && !curMeasure.hasNavigation("Coda" /* Coda */)) {
3811
3824
  curMeasure = curMeasure.getNextMeasure();
3812
3825
  }
3813
- } else if (alFine && curMeasure.hasNavigation(7 /* Fine */)) {
3826
+ } else if (alFine && curMeasure.hasNavigation("Fine" /* Fine */)) {
3814
3827
  curMeasure = void 0;
3815
- } else if (curMeasure.hasNavigation(1 /* DC_al_Coda */)) {
3828
+ } else if (curMeasure.hasNavigation("D.C. al Coda" /* DC_al_Coda */)) {
3816
3829
  alCoda = true;
3817
3830
  curMeasure = this.doc.getFirstMeasure();
3818
- } else if (curMeasure.hasNavigation(0 /* DC_al_Fine */)) {
3831
+ } else if (curMeasure.hasNavigation("D.C. al Fine" /* DC_al_Fine */)) {
3819
3832
  alFine = true;
3820
3833
  curMeasure = this.doc.getFirstMeasure();
3821
- } else if (curMeasure.hasNavigation(3 /* DS_al_Coda */)) {
3834
+ } else if (curMeasure.hasNavigation("D.S. al Coda" /* DS_al_Coda */)) {
3822
3835
  alCoda = true;
3823
3836
  curMeasure = segnoMeasure;
3824
- } else if (curMeasure.hasNavigation(2 /* DS_al_Fine */)) {
3837
+ } else if (curMeasure.hasNavigation("D.S. al Fine" /* DS_al_Fine */)) {
3825
3838
  alFine = true;
3826
3839
  curMeasure = segnoMeasure;
3827
- } else if (curMeasure.hasNavigation(9 /* EndRepeat */)) {
3840
+ } else if (curMeasure.hasNavigation("endRepeat" /* EndRepeat */)) {
3828
3841
  let passage = curMeasure.getPassCount();
3829
3842
  let repeatCount = curMeasure.getEndRepeatPlayCount() - 1;
3830
- let cannotPassThrough = ((_a = curMeasure.getNextMeasure()) == null ? void 0 : _a.hasNavigation(10 /* Ending */)) === true;
3843
+ let cannotPassThrough = ((_a = curMeasure.getNextMeasure()) == null ? void 0 : _a.hasNavigation("ending" /* Ending */)) === true;
3831
3844
  if (passage <= repeatCount || cannotPassThrough) {
3832
3845
  curMeasure = startRepeatMeasure;
3833
3846
  } else {
@@ -3878,14 +3891,15 @@ var Player = class _Player {
3878
3891
  col.getAnchoredLayoutObjects().forEach((layoutObj) => {
3879
3892
  var _a2;
3880
3893
  let text = (_a2 = layoutObj.getTextContent()) != null ? _a2 : "";
3881
- if (text === "a tempo") {
3894
+ let vol;
3895
+ if (text === "a tempo" /* a_tempo */) {
3882
3896
  curSpeed = 1;
3883
- } else if (isDynamicsLevelText(text)) {
3884
- curVolume = getVolume(text);
3897
+ } else if ((vol = getDynamicsVolume(text)) !== void 0) {
3898
+ curVolume = vol;
3885
3899
  } else if (layoutObj.musicObj.getLink() instanceof Extension) {
3886
3900
  let extension = layoutObj.musicObj.getLink();
3887
3901
  let { columnRange, extensionBreakText } = extension.getExtensionRangeInfo();
3888
- let totalTicks = import_ts_utils_lib5.Utils.Math.sum(columnRange.map((c) => c.getTicksToNextColumn()));
3902
+ let totalTicks = import_ts_utils_lib6.Utils.Math.sum(columnRange.map((c) => c.getTicksToNextColumn()));
3889
3903
  switch (text) {
3890
3904
  case "accel." /* accel */: {
3891
3905
  let startSpeed = curSpeed;
@@ -3910,8 +3924,8 @@ var Player = class _Player {
3910
3924
  case "cresc." /* cresc */: {
3911
3925
  let startVol = curVolume;
3912
3926
  let endVol = startVol + CrescendoVolumeAdd;
3913
- if (extensionBreakText && isDynamicsLevelText(extensionBreakText) && getVolume(extensionBreakText) > startVol) {
3914
- endVol = getVolume(extensionBreakText);
3927
+ if (extensionBreakText && (vol = getDynamicsVolume(extensionBreakText)) !== void 0 && vol > startVol) {
3928
+ endVol = vol;
3915
3929
  }
3916
3930
  let accuTicks = 0;
3917
3931
  columnRange.forEach((c) => {
@@ -3924,8 +3938,8 @@ var Player = class _Player {
3924
3938
  case "dim." /* dim */: {
3925
3939
  let startVol = curVolume;
3926
3940
  let endVol = startVol - DiminuendoVolumeSub;
3927
- if (extensionBreakText && isDynamicsLevelText(extensionBreakText) && getVolume(extensionBreakText) < startVol) {
3928
- endVol = getVolume(extensionBreakText);
3941
+ if (extensionBreakText && (vol = getDynamicsVolume(extensionBreakText)) !== void 0 && vol < startVol) {
3942
+ endVol = vol;
3929
3943
  }
3930
3944
  let accuTicks = 0;
3931
3945
  columnRange.forEach((c) => {
@@ -3939,11 +3953,11 @@ var Player = class _Player {
3939
3953
  });
3940
3954
  let speedArr = (_a = speedMap.get(col)) != null ? _a : [];
3941
3955
  if (speedArr.length > 0) {
3942
- curSpeed = import_ts_utils_lib5.Utils.Math.sum(speedArr) / speedArr.length;
3956
+ curSpeed = import_ts_utils_lib6.Utils.Math.sum(speedArr) / speedArr.length;
3943
3957
  }
3944
3958
  let volumeArr = (_b = volumeMap.get(col)) != null ? _b : [];
3945
3959
  if (volumeArr.length > 0) {
3946
- curVolume = import_ts_utils_lib5.Utils.Math.sum(volumeArr) / volumeArr.length;
3960
+ curVolume = import_ts_utils_lib6.Utils.Math.sum(volumeArr) / volumeArr.length;
3947
3961
  }
3948
3962
  col.getPlayerProps().setSpeed(curSpeed);
3949
3963
  col.getPlayerProps().setVolume(curVolume);
@@ -3956,7 +3970,7 @@ var Player = class _Player {
3956
3970
  return m;
3957
3971
  }
3958
3972
  let next = m == null ? void 0 : m.getNextMeasure();
3959
- if (!m || m.hasEndSong() || m.hasEndSection() || !next || next.hasNavigation(8 /* StartRepeat */)) {
3973
+ if (!m || m.hasEndSong() || m.hasEndSection() || !next || next.hasNavigation("startRepeat" /* StartRepeat */)) {
3960
3974
  return void 0;
3961
3975
  }
3962
3976
  }
@@ -3981,11 +3995,11 @@ var Player = class _Player {
3981
3995
  } else {
3982
3996
  let playerNotes = col.getPlayerNotes();
3983
3997
  playerNotes.forEach((note, i) => {
3984
- let arpeggioDelayTicks = col.hasArpeggio() ? import_theory7.NoteLength.ThirtySecond * i : 0;
3998
+ let arpeggioDelayTicks = col.hasArpeggio() ? import_theory7.RhythmProps.get(import_theory7.NoteLength.ThirtySecond).ticks * i : 0;
3985
3999
  let noteSeconds = getDuration(note.ticks + fermataHoldTicks - arpeggioDelayTicks, tempo);
3986
4000
  if (noteSeconds > 0) {
3987
4001
  if (note.staccato) {
3988
- noteSeconds = Math.min(getDuration(import_theory7.NoteLength.Eighth, tempo) / 2, noteSeconds / 2);
4002
+ noteSeconds = Math.min(getDuration(import_theory7.RhythmProps.get(import_theory7.NoteLength.Eighth).ticks, tempo) / 2, noteSeconds / 2);
3989
4003
  }
3990
4004
  let volume = adjustVolume(col.getPlayerProps().getVolume());
3991
4005
  if (note.slur === "slurred") {
@@ -4223,8 +4237,8 @@ var ObjBarLineLeft = class extends ObjBarLine {
4223
4237
  solveBarLineType() {
4224
4238
  let m = this.measure;
4225
4239
  let prev = m.getPrevMeasure();
4226
- if (m.hasNavigation(8 /* StartRepeat */)) {
4227
- if (prev && prev.row === m.row && prev.hasNavigation(9 /* EndRepeat */)) {
4240
+ if (m.hasNavigation("startRepeat" /* StartRepeat */)) {
4241
+ if (prev && prev.row === m.row && prev.hasNavigation("endRepeat" /* EndRepeat */)) {
4228
4242
  return 0 /* None */;
4229
4243
  } else {
4230
4244
  return 4 /* StartRepeat */;
@@ -4251,8 +4265,8 @@ var ObjBarLineRight = class extends ObjBarLine {
4251
4265
  solveBarLineType() {
4252
4266
  let m = this.measure;
4253
4267
  let next = m.getNextMeasure();
4254
- if (m.hasNavigation(9 /* EndRepeat */)) {
4255
- if (next && next.row === m.row && next.hasNavigation(8 /* StartRepeat */)) {
4268
+ if (m.hasNavigation("endRepeat" /* EndRepeat */)) {
4269
+ if (next && next.row === m.row && next.hasNavigation("startRepeat" /* StartRepeat */)) {
4256
4270
  return 6 /* EndStartRepeat */;
4257
4271
  } else {
4258
4272
  return 5 /* EndRepeat */;
@@ -4262,10 +4276,10 @@ var ObjBarLineRight = class extends ObjBarLine {
4262
4276
  } else if (m.hasEndSection()) {
4263
4277
  return 2 /* Double */;
4264
4278
  }
4265
- if (m === m.row.getLastMeasure() && next && next.row === m.row.getNextRow() && next.hasNavigation(8 /* StartRepeat */)) {
4279
+ if (m === m.row.getLastMeasure() && next && next.row === m.row.getNextRow() && next.hasNavigation("startRepeat" /* StartRepeat */)) {
4266
4280
  return 2 /* Double */;
4267
4281
  }
4268
- if (next && next.hasNavigation(8 /* StartRepeat */)) {
4282
+ if (next && next.hasNavigation("startRepeat" /* StartRepeat */)) {
4269
4283
  return 0 /* None */;
4270
4284
  }
4271
4285
  return 1 /* Single */;
@@ -4273,7 +4287,7 @@ var ObjBarLineRight = class extends ObjBarLine {
4273
4287
  };
4274
4288
 
4275
4289
  // src/score/engine/obj-ending.ts
4276
- var import_ts_utils_lib6 = require("@tspro/ts-utils-lib");
4290
+ var import_ts_utils_lib7 = require("@tspro/ts-utils-lib");
4277
4291
  var import_core10 = require("@tspro/web-music-score/core");
4278
4292
  var ObjEnding = class extends MusicObject {
4279
4293
  constructor(measure, passages) {
@@ -4284,9 +4298,9 @@ var ObjEnding = class extends MusicObject {
4284
4298
  __publicField(this, "shapeRects", []);
4285
4299
  __publicField(this, "mi");
4286
4300
  this.mi = new MEnding(this);
4287
- if (!import_ts_utils_lib6.Utils.Is.isIntegerGte(passages.length, 1)) {
4301
+ if (!import_ts_utils_lib7.Utils.Is.isIntegerGte(passages.length, 1)) {
4288
4302
  throw new import_core10.MusicError(import_core10.MusicErrorType.Score, "Passages is empty.");
4289
- } else if (!this.passages.every((p) => import_ts_utils_lib6.Utils.Is.isIntegerGte(p, 1))) {
4303
+ } else if (!this.passages.every((p) => import_ts_utils_lib7.Utils.Is.isIntegerGte(p, 1))) {
4290
4304
  throw new import_core10.MusicError(import_core10.MusicErrorType.Score, "Invalid passages: " + this.passages);
4291
4305
  }
4292
4306
  this.passages.sort((a, b) => a - b);
@@ -4302,7 +4316,7 @@ var ObjEnding = class extends MusicObject {
4302
4316
  isSingleMeasureEnding() {
4303
4317
  let { measure } = this;
4304
4318
  let next = measure.getNextMeasure();
4305
- return (next == null ? void 0 : next.hasNavigation(10 /* Ending */)) === true || measure.hasNavigation(9 /* EndRepeat */) || measure.isLastMeasure();
4319
+ return (next == null ? void 0 : next.hasNavigation("ending" /* Ending */)) === true || measure.hasNavigation("endRepeat" /* EndRepeat */) || measure.isLastMeasure();
4306
4320
  }
4307
4321
  hasPassage(pass) {
4308
4322
  return this.passages.some((p) => p === pass);
@@ -4501,7 +4515,7 @@ var import_core13 = require("@tspro/web-music-score/core");
4501
4515
  var import_theory8 = require("@tspro/web-music-score/theory");
4502
4516
 
4503
4517
  // src/score/engine/obj-connective.ts
4504
- var import_ts_utils_lib7 = require("@tspro/ts-utils-lib");
4518
+ var import_ts_utils_lib8 = require("@tspro/ts-utils-lib");
4505
4519
  var import_core11 = require("@tspro/web-music-score/core");
4506
4520
  var ObjConnective = class extends MusicObject {
4507
4521
  constructor(connectiveProps, line, measure, leftNoteGroup, leftNoteId, ...args) {
@@ -4530,7 +4544,7 @@ var ObjConnective = class extends MusicObject {
4530
4544
  this.rightNoteGroup = args[0];
4531
4545
  this.rightNoteId = args[1];
4532
4546
  this.tieType = void 0;
4533
- } else if (import_ts_utils_lib7.Utils.Is.isEnumValue(args[0], TieType)) {
4547
+ } else if (import_ts_utils_lib8.Utils.Is.isEnumValue(args[0], TieType)) {
4534
4548
  this.rightNoteGroup = void 0;
4535
4549
  this.rightNoteId = void 0;
4536
4550
  this.tieType = args[0];
@@ -4561,7 +4575,7 @@ var ObjConnective = class extends MusicObject {
4561
4575
  if (rightNoteGroup !== void 0 && rightNoteId !== void 0) {
4562
4576
  rightPos = rightNoteGroup.getConnectiveAnchorPoint(connectiveProps, line, rightNoteId, noteAnchor, "right");
4563
4577
  } else {
4564
- rightPos = this.tieType === -2 /* ToMeasureEnd */ ? { x: measure.getColumnsContentRect().right, y: leftPos.y } : { x: leftPos.x + unitSize * DocumentSettings.StubTieLength, y: leftPos.y };
4578
+ rightPos = this.tieType === "toMeasureEnd" /* ToMeasureEnd */ ? { x: measure.getColumnsContentRect().right, y: leftPos.y } : { x: leftPos.x + unitSize * DocumentSettings.StubTieLength, y: leftPos.y };
4565
4579
  }
4566
4580
  let lx, ly, rx, ry;
4567
4581
  if (rightNoteGroup === void 0) {
@@ -4599,8 +4613,8 @@ var ObjConnective = class extends MusicObject {
4599
4613
  this.ly = ly;
4600
4614
  this.rx = rx;
4601
4615
  this.ry = ry;
4602
- this.arcHeight = this.connectiveProps.connective === 2 /* Slide */ ? 0 : arcHeight;
4603
- let { nx, ny } = import_ts_utils_lib7.Utils.Math.calcNormal(lx, ly, rx, ry);
4616
+ this.arcHeight = this.connectiveProps.connective === "slide" /* Slide */ ? 0 : arcHeight;
4617
+ let { nx, ny } = import_ts_utils_lib8.Utils.Math.calcNormal(lx, ly, rx, ry);
4604
4618
  this.cp1x = lx * 0.7 + rx * 0.3 + nx * this.arcHeight;
4605
4619
  this.cp1y = ly * 0.7 + ry * 0.3 + ny * this.arcHeight;
4606
4620
  this.cp2x = lx * 0.3 + rx * 0.7 + nx * this.arcHeight;
@@ -4661,6 +4675,7 @@ var ObjConnective = class extends MusicObject {
4661
4675
 
4662
4676
  // src/score/engine/connective-props.ts
4663
4677
  var import_core12 = require("@tspro/web-music-score/core");
4678
+ var import_ts_utils_lib9 = require("@tspro/ts-utils-lib");
4664
4679
  var ConnectiveProps = class {
4665
4680
  constructor(connective, span, noteAnchor, startNoteGroup) {
4666
4681
  this.connective = connective;
@@ -4682,7 +4697,7 @@ var ConnectiveProps = class {
4682
4697
  * @returns true if noteGroup was added, false if not.
4683
4698
  */
4684
4699
  addNoteGroup(noteGroup) {
4685
- if (this.span === -1 /* Stub */ || this.span === -2 /* ToMeasureEnd */) {
4700
+ if (this.span === "stub" /* Stub */ || this.span === "toMeasureEnd" /* ToMeasureEnd */) {
4686
4701
  return false;
4687
4702
  } else if (this.span > this.noteGroups.length) {
4688
4703
  this.noteGroups.push(noteGroup);
@@ -4692,29 +4707,29 @@ var ConnectiveProps = class {
4692
4707
  }
4693
4708
  }
4694
4709
  computeParams() {
4695
- let stemDir = this.noteGroups[0].stemDir;
4696
- let hasStem = this.noteGroups[0].rhythmProps.hasStem;
4697
- if (this.noteAnchor === 4 /* StemTip */) {
4698
- this.arcDir = stemDir === 1 /* Up */ ? "up" : "down";
4699
- } else if (this.noteAnchor === 0 /* Auto */) {
4700
- this.arcDir = stemDir === 1 /* Up */ || !hasStem ? "down" : "up";
4710
+ let { stemDir } = this.noteGroups[0];
4711
+ let { hasStem } = this.noteGroups[0].rhythmProps;
4712
+ if (this.noteAnchor === "stemTip" /* StemTip */) {
4713
+ this.arcDir = stemDir === "up" /* Up */ ? "up" : "down";
4714
+ } else if (this.noteAnchor === "auto" /* Auto */) {
4715
+ this.arcDir = stemDir === "up" /* Up */ || !hasStem ? "down" : "up";
4701
4716
  if (this.noteGroups[0].notes.length > 1) {
4702
- this.noteAnchor = 2 /* Center */;
4703
- } else if (this.connective === 2 /* Slide */) {
4704
- this.noteAnchor = 2 /* Center */;
4717
+ this.noteAnchor = "center" /* Center */;
4718
+ } else if (this.connective === "slide" /* Slide */) {
4719
+ this.noteAnchor = "center" /* Center */;
4705
4720
  } else if (this.arcDir === "up") {
4706
- this.noteAnchor = 1 /* Above */;
4721
+ this.noteAnchor = "above" /* Above */;
4707
4722
  } else {
4708
- this.noteAnchor = 3 /* Below */;
4723
+ this.noteAnchor = "below" /* Below */;
4709
4724
  }
4710
- } else if (this.noteAnchor === 2 /* Center */) {
4725
+ } else if (this.noteAnchor === "center" /* Center */) {
4711
4726
  let { row } = this.noteGroups[0].measure;
4712
4727
  let diatonicId = this.noteGroups[0].ownDiatonicId;
4713
4728
  let staff = row.getStaff(diatonicId);
4714
4729
  this.arcDir = !staff || diatonicId < staff.middleLineDiatonicId ? "down" : "up";
4715
- } else if (this.noteAnchor === 1 /* Above */) {
4730
+ } else if (this.noteAnchor === "above" /* Above */) {
4716
4731
  this.arcDir = "up";
4717
- } else if (this.noteAnchor === 3 /* Below */) {
4732
+ } else if (this.noteAnchor === "below" /* Below */) {
4718
4733
  this.arcDir = "down";
4719
4734
  }
4720
4735
  }
@@ -4729,8 +4744,8 @@ var ConnectiveProps = class {
4729
4744
  this.getStartNoteGroup().collectConnectiveProps();
4730
4745
  this.computeParams();
4731
4746
  let { connective, span } = this;
4732
- if (connective === 0 /* Tie */) {
4733
- if (span === -1 /* Stub */ || span === -2 /* ToMeasureEnd */) {
4747
+ if (connective === "tie" /* Tie */) {
4748
+ if (import_ts_utils_lib9.Utils.Is.isEnumValue(span, TieType)) {
4734
4749
  let leftNoteGroup = this.noteGroups[0];
4735
4750
  for (let noteId = 0; noteId < leftNoteGroup.notes.length; noteId++) {
4736
4751
  this.createObjConnectiveWithTieType(leftNoteGroup, noteId, span);
@@ -4747,13 +4762,13 @@ var ConnectiveProps = class {
4747
4762
  });
4748
4763
  }
4749
4764
  }
4750
- } else if (connective === 1 /* Slur */) {
4765
+ } else if (connective === "slur" /* Slur */) {
4751
4766
  if (typeof span === "number" && span >= 2 && this.noteGroups.length === span) {
4752
4767
  let leftNoteGroup = this.noteGroups[0];
4753
4768
  let rightNoteGroup = this.noteGroups[this.noteGroups.length - 1];
4754
4769
  this.createObjConnective(leftNoteGroup, 0, rightNoteGroup, 0);
4755
4770
  }
4756
- } else if (connective === 2 /* Slide */) {
4771
+ } else if (connective === "slide" /* Slide */) {
4757
4772
  if (this.noteGroups.length >= 2) {
4758
4773
  for (let i = 0; i < this.noteGroups.length - 1; i++) {
4759
4774
  let leftNoteGroup = this.noteGroups[i];
@@ -4783,7 +4798,7 @@ var ConnectiveProps = class {
4783
4798
  } else {
4784
4799
  let leftString = leftNoteGroup2.getFretNumberString(leftNoteId2);
4785
4800
  let rightString = rightNoteGroup2.getFretNumberString(rightNoteId2);
4786
- if (leftString !== void 0 && rightString !== void 0 && (leftString === rightString || this.connective === 1 /* Slur */)) {
4801
+ if (leftString !== void 0 && rightString !== void 0 && (leftString === rightString || this.connective === "slur" /* Slur */)) {
4787
4802
  new ObjConnective(this, line, measure, leftNoteGroup2, leftNoteId2, rightNoteGroup2, rightNoteId2);
4788
4803
  }
4789
4804
  }
@@ -4808,6 +4823,32 @@ function validateVoiceId(voiceId) {
4808
4823
  return voiceId;
4809
4824
  }
4810
4825
  }
4826
+ function getExtensionTicks(extensionLength) {
4827
+ if (typeof extensionLength === "string") {
4828
+ extensionLength = [extensionLength];
4829
+ }
4830
+ if (import_ts_utils_lib10.Utils.Is.isArray(extensionLength)) {
4831
+ let totalTicks = 0;
4832
+ for (let i = 0; i < extensionLength.length; ) {
4833
+ let str = extensionLength[i];
4834
+ let num = extensionLength[i + 1];
4835
+ if (typeof str === "string") {
4836
+ i++;
4837
+ let ticks = import_theory9.RhythmProps.get(str).ticks;
4838
+ if (typeof num === "number") {
4839
+ i++;
4840
+ ticks *= num;
4841
+ }
4842
+ totalTicks += ticks;
4843
+ } else {
4844
+ i++;
4845
+ }
4846
+ }
4847
+ return totalTicks;
4848
+ } else {
4849
+ return extensionLength;
4850
+ }
4851
+ }
4811
4852
  var _ObjMeasure = class _ObjMeasure extends MusicObject {
4812
4853
  constructor(row) {
4813
4854
  super(row);
@@ -4911,15 +4952,15 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
4911
4952
  if (setStemDir !== void 0) {
4912
4953
  this.useStemDir[voiceId] = setStemDir;
4913
4954
  } else if (this.useStemDir[voiceId] === void 0) {
4914
- this.useStemDir[voiceId] = (_b = (_a = this.getPrevMeasure()) == null ? void 0 : _a.useStemDir[voiceId]) != null ? _b : 0 /* Auto */;
4955
+ this.useStemDir[voiceId] = (_b = (_a = this.getPrevMeasure()) == null ? void 0 : _a.useStemDir[voiceId]) != null ? _b : "auto" /* Auto */;
4915
4956
  }
4916
4957
  let stemDir = this.useStemDir[voiceId];
4917
- if (stemDir === 0 /* Auto */ || stemDir === void 0) {
4958
+ if (stemDir === "auto" /* Auto */ || stemDir === void 0) {
4918
4959
  let staff = this.row.getStaff(symbol.ownDiatonicId);
4919
4960
  if (staff) {
4920
- return symbol.ownDiatonicId > staff.middleLineDiatonicId ? 2 /* Down */ : 1 /* Up */;
4961
+ return symbol.ownDiatonicId > staff.middleLineDiatonicId ? "down" /* Down */ : "up" /* Up */;
4921
4962
  } else {
4922
- return 1 /* Up */;
4963
+ return "up" /* Up */;
4923
4964
  }
4924
4965
  } else {
4925
4966
  return stemDir;
@@ -5026,6 +5067,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5026
5067
  // See MMeasure interface
5027
5068
  //setKeySignature(tonic: string, scaleType: ScaleType): void;
5028
5069
  //setKeySignature(keySignature: KeySignature): void;
5070
+ //setKeySignature(keySignature: string): void;
5029
5071
  //setKeySignature(scale: Scale): void;
5030
5072
  setKeySignature(...args) {
5031
5073
  var _a;
@@ -5034,13 +5076,17 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5034
5076
  this.alterKeySignature = args[0];
5035
5077
  } else if (args[0] instanceof import_theory9.Scale) {
5036
5078
  this.alterKeySignature = args[0];
5037
- } else {
5038
- try {
5039
- let tonic = "" + args[0];
5040
- let scaleType = (0, import_theory9.validateScaleType)("" + args[1]);
5041
- this.alterKeySignature = (0, import_theory9.getScale)(tonic, scaleType);
5042
- } catch (e) {
5043
- throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Cannot set key signature because invalid args: " + args);
5079
+ } else if (import_ts_utils_lib10.Utils.Is.isNonEmptyString(args[0])) {
5080
+ if (args.length === 1) {
5081
+ this.alterKeySignature = (0, import_theory9.getScale)(args[0]);
5082
+ } else if (args.length === 2) {
5083
+ try {
5084
+ let tonic = "" + args[0];
5085
+ let scaleType = (0, import_theory9.validateScaleType)("" + args[1]);
5086
+ this.alterKeySignature = (0, import_theory9.getScale)(tonic, scaleType);
5087
+ } catch (e) {
5088
+ throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Cannot set key signature because invalid args: " + args);
5089
+ }
5044
5090
  }
5045
5091
  }
5046
5092
  this.updateKeySignature();
@@ -5080,8 +5126,16 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5080
5126
  setTempo(beatsPerMinute, beatLength, dotted) {
5081
5127
  var _a;
5082
5128
  (_a = this.getPrevMeasure()) == null ? void 0 : _a.endSection();
5083
- let options = beatLength !== void 0 ? { beatLength, dotted } : void 0;
5084
- this.alterTempo = { beatsPerMinute, options };
5129
+ if (beatLength === void 0) {
5130
+ this.alterTempo = { beatsPerMinute };
5131
+ } else {
5132
+ let dotCount = typeof dotted === "number" && dotted > 0 ? dotted : dotted === true ? 1 : import_theory9.NoteLengthProps.get(beatLength).dotCount;
5133
+ let options = {
5134
+ beatLength: (0, import_theory9.validateNoteLength)(beatLength),
5135
+ dotCount: dotCount > 0 ? dotCount : void 0
5136
+ };
5137
+ this.alterTempo = { beatsPerMinute, options };
5138
+ }
5085
5139
  this.updateTempo();
5086
5140
  }
5087
5141
  updateTempo() {
@@ -5090,18 +5144,18 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5090
5144
  if (this.alterTempo) {
5091
5145
  let beatsPerMinute = this.alterTempo.beatsPerMinute;
5092
5146
  let beatLength;
5093
- let dotted;
5147
+ let dotCount;
5094
5148
  if (this.alterTempo.options) {
5095
5149
  beatLength = this.alterTempo.options.beatLength;
5096
- dotted = (_a = this.alterTempo.options.dotted) != null ? _a : false;
5150
+ dotCount = (_a = this.alterTempo.options.dotCount) != null ? _a : 0;
5097
5151
  } else if (this.alterTimeSignature) {
5098
5152
  beatLength = this.alterTimeSignature.beatLength;
5099
- dotted = false;
5153
+ dotCount = 0;
5100
5154
  } else {
5101
5155
  beatLength = this.tempo.options.beatLength;
5102
- dotted = this.tempo.options.dotted;
5156
+ dotCount = this.tempo.options.dotCount;
5103
5157
  }
5104
- this.tempo = { beatsPerMinute, options: { beatLength, dotted } };
5158
+ this.tempo = { beatsPerMinute, options: { beatLength, dotCount } };
5105
5159
  }
5106
5160
  if (this.nextMeasure) {
5107
5161
  this.nextMeasure.updateTempo();
@@ -5133,19 +5187,19 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5133
5187
  let grp = this.doc.getStaffGroup(staffTabOrGroup);
5134
5188
  if (grp && !prevGroups.includes(staffTabOrGroup)) {
5135
5189
  let curGroups = [...prevGroups, staffTabOrGroup];
5136
- (import_ts_utils_lib8.Utils.Is.isArray(grp.staffsTabsAndGroups) ? grp.staffsTabsAndGroups : [grp.staffsTabsAndGroups]).forEach((staffTabOrGroup2) => {
5190
+ (import_ts_utils_lib10.Utils.Is.isArray(grp.staffsTabsAndGroups) ? grp.staffsTabsAndGroups : [grp.staffsTabsAndGroups]).forEach((staffTabOrGroup2) => {
5137
5191
  switch (grp.verticalPosition) {
5138
- case 0 /* Above */:
5192
+ case "above" /* Above */:
5139
5193
  addToStaffTabOrGroup(staffTabOrGroup2, 0 /* Above */, curGroups);
5140
5194
  break;
5141
- case 1 /* Below */:
5195
+ case "below" /* Below */:
5142
5196
  addToStaffTabOrGroup(staffTabOrGroup2, 1 /* Below */, curGroups);
5143
5197
  break;
5144
- case 2 /* Both */:
5198
+ case "both" /* Both */:
5145
5199
  addToStaffTabOrGroup(staffTabOrGroup2, 0 /* Above */, curGroups);
5146
5200
  addToStaffTabOrGroup(staffTabOrGroup2, 1 /* Below */, curGroups);
5147
5201
  break;
5148
- case 3 /* Auto */:
5202
+ case "auto" /* Auto */:
5149
5203
  addToStaffTabOrGroup(staffTabOrGroup2, defaultVerticalPos, curGroups);
5150
5204
  break;
5151
5205
  }
@@ -5160,14 +5214,14 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5160
5214
  } else {
5161
5215
  addToStaffTabOrGroup(0, defaultVerticalPos);
5162
5216
  }
5163
- } else if (import_ts_utils_lib8.Utils.Is.isArray(staffTabOrGroups)) {
5217
+ } else if (import_ts_utils_lib10.Utils.Is.isArray(staffTabOrGroups)) {
5164
5218
  staffTabOrGroups.forEach((staffTabOrGroup) => addToStaffTabOrGroup(staffTabOrGroup, defaultVerticalPos));
5165
5219
  } else {
5166
5220
  addToStaffTabOrGroup(staffTabOrGroups, defaultVerticalPos);
5167
5221
  }
5168
5222
  }
5169
5223
  addFermata(staffTabOrGroups, fermata) {
5170
- let anchor = fermata === 1 /* AtMeasureEnd */ ? this.barLineRight : this.lastAddedRhythmColumn;
5224
+ let anchor = fermata === "atMeasureEnd" /* AtMeasureEnd */ ? this.barLineRight : this.lastAddedRhythmColumn;
5171
5225
  if (!anchor) {
5172
5226
  throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Cannot add Fermata because anchor is undefined.");
5173
5227
  }
@@ -5183,7 +5237,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5183
5237
  addNavigation(staffTabOrGroups, navigation, ...args) {
5184
5238
  let addLayoutObjectProps = void 0;
5185
5239
  switch (navigation) {
5186
- case 10 /* Ending */:
5240
+ case "ending" /* Ending */:
5187
5241
  if (this.navigationSet.has(navigation)) {
5188
5242
  throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Cannot add ending beasure measure already has one.");
5189
5243
  }
@@ -5195,10 +5249,10 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5195
5249
  defaultVerticalPos: 0 /* Above */
5196
5250
  };
5197
5251
  break;
5198
- case 1 /* DC_al_Coda */:
5199
- case 0 /* DC_al_Fine */:
5200
- case 3 /* DS_al_Coda */:
5201
- case 2 /* DS_al_Fine */: {
5252
+ case "D.C. al Coda" /* DC_al_Coda */:
5253
+ case "D.C. al Fine" /* DC_al_Fine */:
5254
+ case "D.S. al Coda" /* DS_al_Coda */:
5255
+ case "D.S. al Fine" /* DS_al_Fine */: {
5202
5256
  let anchor2 = this.barLineRight;
5203
5257
  let text = getNavigationString(navigation);
5204
5258
  addLayoutObjectProps = {
@@ -5206,11 +5260,11 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5206
5260
  layoutGroupId: 2 /* Navigation */,
5207
5261
  defaultVerticalPos: 0 /* Above */
5208
5262
  };
5209
- this.addNavigation(staffTabOrGroups, 9 /* EndRepeat */);
5263
+ this.addNavigation(staffTabOrGroups, "endRepeat" /* EndRepeat */);
5210
5264
  this.endSong();
5211
5265
  break;
5212
5266
  }
5213
- case 7 /* Fine */: {
5267
+ case "Fine" /* Fine */: {
5214
5268
  let anchor2 = this.barLineRight;
5215
5269
  let text = getNavigationString(navigation);
5216
5270
  addLayoutObjectProps = {
@@ -5220,8 +5274,8 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5220
5274
  };
5221
5275
  break;
5222
5276
  }
5223
- case 6 /* Segno */:
5224
- case 4 /* Coda */: {
5277
+ case "Segno" /* Segno */:
5278
+ case "Coda" /* Coda */: {
5225
5279
  let anchor2 = this.barLineLeft;
5226
5280
  let text = getNavigationString(navigation);
5227
5281
  addLayoutObjectProps = {
@@ -5231,7 +5285,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5231
5285
  };
5232
5286
  break;
5233
5287
  }
5234
- case 5 /* toCoda */: {
5288
+ case "toCoda" /* toCoda */: {
5235
5289
  let anchor2 = this.barLineRight;
5236
5290
  let text = getNavigationString(navigation);
5237
5291
  addLayoutObjectProps = {
@@ -5241,10 +5295,10 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5241
5295
  };
5242
5296
  break;
5243
5297
  }
5244
- case 9 /* EndRepeat */:
5298
+ case "endRepeat" /* EndRepeat */:
5245
5299
  if (args.length === 0) {
5246
5300
  this.endRepeatPlayCount = 2;
5247
- } else if (import_ts_utils_lib8.Utils.Is.isIntegerGte(args[0], 2)) {
5301
+ } else if (import_ts_utils_lib10.Utils.Is.isIntegerGte(args[0], 2)) {
5248
5302
  this.endRepeatPlayCount = args[0];
5249
5303
  } else {
5250
5304
  throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Invalid end repeat play count (should be 2 or greater integer): " + args[0]);
@@ -5280,17 +5334,18 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5280
5334
  let layoutGroupId;
5281
5335
  let defaultVerticalPos;
5282
5336
  switch (annotation) {
5283
- case 0 /* Dynamics */:
5337
+ case "dynamics" /* Dynamics */:
5284
5338
  layoutGroupId = 5 /* DynamicsAnnotation */;
5285
5339
  defaultVerticalPos = 0 /* Above */;
5286
5340
  textProps.italic = true;
5287
5341
  break;
5288
- case 1 /* Tempo */:
5342
+ case "tempo" /* Tempo */:
5289
5343
  layoutGroupId = 4 /* TempoAnnotation */;
5290
5344
  defaultVerticalPos = 0 /* Above */;
5291
5345
  textProps.italic = true;
5292
5346
  break;
5293
5347
  }
5348
+ this.disableExtension();
5294
5349
  this.forEachStaffGroup(staffTabOrGroups, defaultVerticalPos, (line, vpos) => {
5295
5350
  let textObj = new ObjText(anchor, textProps, 0.5, 1);
5296
5351
  this.addLayoutObject(textObj, line, layoutGroupId, vpos);
@@ -5308,15 +5363,16 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5308
5363
  let layoutGroupId;
5309
5364
  let defaultVerticalPos;
5310
5365
  switch (label) {
5311
- case 0 /* Note */:
5366
+ case "note" /* Note */:
5312
5367
  layoutGroupId = 1 /* NoteLabel */;
5313
5368
  defaultVerticalPos = 1 /* Below */;
5314
5369
  break;
5315
- case 1 /* Chord */:
5370
+ case "chord" /* Chord */:
5316
5371
  layoutGroupId = 6 /* ChordLabel */;
5317
5372
  defaultVerticalPos = 0 /* Above */;
5318
5373
  break;
5319
5374
  }
5375
+ this.disableExtension();
5320
5376
  this.forEachStaffGroup(staffTabOrGroups, defaultVerticalPos, (line, vpos) => {
5321
5377
  let textObj = new ObjText(anchor, textProps, 0.5, 1);
5322
5378
  this.addLayoutObject(textObj, line, layoutGroupId, vpos);
@@ -5328,17 +5384,17 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5328
5384
  if (!(anchor instanceof ObjNoteGroup)) {
5329
5385
  throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Connective can be added to note group only.");
5330
5386
  }
5331
- if (connective === 0 /* Tie */) {
5332
- let tieSpan = import_ts_utils_lib8.Utils.Is.isInteger(args[0]) || import_ts_utils_lib8.Utils.Is.isEnumValue(args[0], TieType) ? args[0] : 2;
5333
- let noteAnchor = import_ts_utils_lib8.Utils.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : 0 /* Auto */;
5334
- anchor.startConnective(new ConnectiveProps(0 /* Tie */, tieSpan, noteAnchor, anchor));
5335
- } else if (connective === 1 /* Slur */) {
5336
- let slurSpan = import_ts_utils_lib8.Utils.Is.isInteger(args[0]) ? args[0] : 2;
5337
- let noteAnchor = import_ts_utils_lib8.Utils.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : 0 /* Auto */;
5338
- anchor.startConnective(new ConnectiveProps(1 /* Slur */, slurSpan, noteAnchor, anchor));
5339
- } else if (connective === 2 /* Slide */) {
5340
- let noteAnchor = import_ts_utils_lib8.Utils.Is.isEnumValue(args[0], NoteAnchor) ? args[0] : 0 /* Auto */;
5341
- anchor.startConnective(new ConnectiveProps(2 /* Slide */, 2, noteAnchor, anchor));
5387
+ if (connective === "tie" /* Tie */) {
5388
+ let tieSpan = import_ts_utils_lib10.Utils.Is.isInteger(args[0]) || import_ts_utils_lib10.Utils.Is.isEnumValue(args[0], TieType) ? args[0] : 2;
5389
+ let noteAnchor = import_ts_utils_lib10.Utils.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : "auto" /* Auto */;
5390
+ anchor.startConnective(new ConnectiveProps("tie" /* Tie */, tieSpan, noteAnchor, anchor));
5391
+ } else if (connective === "slur" /* Slur */) {
5392
+ let slurSpan = import_ts_utils_lib10.Utils.Is.isInteger(args[0]) ? args[0] : 2;
5393
+ let noteAnchor = import_ts_utils_lib10.Utils.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : "auto" /* Auto */;
5394
+ anchor.startConnective(new ConnectiveProps("slur" /* Slur */, slurSpan, noteAnchor, anchor));
5395
+ } else if (connective === "slide" /* Slide */) {
5396
+ let noteAnchor = import_ts_utils_lib10.Utils.Is.isEnumValue(args[0], NoteAnchor) ? args[0] : "auto" /* Auto */;
5397
+ anchor.startConnective(new ConnectiveProps("slide" /* Slide */, 2, noteAnchor, anchor));
5342
5398
  }
5343
5399
  }
5344
5400
  addExtension(extensionLength, extensionVisible) {
@@ -5347,7 +5403,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5347
5403
  if (musicObj instanceof ObjText && anchor instanceof ObjRhythmColumn) {
5348
5404
  let lineStyle = "dashed";
5349
5405
  let linePos = "bottom";
5350
- let extension = new Extension(musicObj, anchor, extensionLength, extensionVisible, lineStyle, linePos);
5406
+ let extension = new Extension(musicObj, anchor, getExtensionTicks(extensionLength), extensionVisible, lineStyle, linePos);
5351
5407
  musicObj.setLink(extension);
5352
5408
  } else {
5353
5409
  throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Cannot add extension becaue no compatible music object to attach it to.");
@@ -5396,21 +5452,25 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5396
5452
  col.setVoiceSymbol(voiceId, symbol);
5397
5453
  this.getVoiceSymbols(voiceId);
5398
5454
  this.voiceSymbols[voiceId].push(symbol);
5399
- if (symbol.triplet) {
5455
+ if (symbol.oldStyleTriplet) {
5400
5456
  this.createOldStyleTriplets(voiceId);
5401
5457
  }
5402
5458
  this.requestBeamsUpdate();
5403
5459
  this.lastAddedRhythmColumn = col;
5404
5460
  this.lastAddedRhythmSymbol = symbol;
5405
5461
  }
5406
- addNoteGroup(voiceId, notes, noteLength, options) {
5407
- let notes2 = notes.map((note) => typeof note === "string" ? import_theory9.Note.getNote(note) : note);
5462
+ addNoteGroup(voiceId, notes, noteLength, options, tupletRatio) {
5463
+ let realNotes = notes.map((note) => typeof note === "string" ? import_theory9.Note.getNote(note) : note);
5408
5464
  let col = this.getRhythmColumn(voiceId);
5409
- this.addRhythmSymbol(voiceId, new ObjNoteGroup(col, voiceId, notes2, noteLength, options));
5465
+ let noteGroup = new ObjNoteGroup(col, voiceId, realNotes, noteLength, options, tupletRatio);
5466
+ this.addRhythmSymbol(voiceId, noteGroup);
5467
+ return noteGroup;
5410
5468
  }
5411
- addRest(voiceId, restLength, options) {
5469
+ addRest(voiceId, restLength, options, tupletRatio) {
5412
5470
  let col = this.getRhythmColumn(voiceId);
5413
- this.addRhythmSymbol(voiceId, new ObjRest(col, voiceId, restLength, options));
5471
+ let rest = new ObjRest(col, voiceId, restLength, options, tupletRatio);
5472
+ this.addRhythmSymbol(voiceId, rest);
5473
+ return rest;
5414
5474
  }
5415
5475
  /**
5416
5476
  *
@@ -5552,18 +5612,13 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5552
5612
  requestBeamsUpdate() {
5553
5613
  this.needBeamsUpdate = true;
5554
5614
  }
5615
+ // Create triplets by triplet property of NoteOptions/RestOptions.
5555
5616
  createOldStyleTriplets(voiceId) {
5556
5617
  let symbols = this.getVoiceSymbols(voiceId);
5557
- if (symbols.length <= 2) {
5558
- return;
5559
- }
5560
5618
  for (let i = 0; i < symbols.length; ) {
5561
- let s2 = symbols.slice(i, i + 2);
5562
- let s3 = symbols.slice(i, i + 3);
5563
- if (s2.length === 2 && s2.every((s) => s.triplet) && s2.every((s) => s.getBeamGroup() === void 0) && ObjBeamGroup.createTriplet(s2)) {
5564
- i += 2;
5565
- } else if (s3.length === 3 && s3.every((s) => s.triplet) && s3.every((s) => s.getBeamGroup() === void 0) && ObjBeamGroup.createTriplet(s3)) {
5566
- i += 3;
5619
+ if (symbols[i].oldStyleTriplet) {
5620
+ let n = ObjBeamGroup.createOldStyleTriplet(symbols.slice(i, i + 3));
5621
+ i += n === 0 ? 1 : n;
5567
5622
  } else {
5568
5623
  i++;
5569
5624
  }
@@ -5575,11 +5630,11 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5575
5630
  return;
5576
5631
  }
5577
5632
  this.beamGroups = this.beamGroups.filter((beamGroup) => {
5578
- if (beamGroup.getType() === 0 /* RegularBeam */) {
5633
+ if (beamGroup.isTuplet()) {
5634
+ return true;
5635
+ } else {
5579
5636
  beamGroup.detach();
5580
5637
  return false;
5581
- } else {
5582
- return true;
5583
5638
  }
5584
5639
  });
5585
5640
  getVoiceIds().forEach((voiceId) => {
@@ -5615,7 +5670,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5615
5670
  static setupBeamGroup(groupSymbols) {
5616
5671
  let groupNotes = groupSymbols.map((s) => {
5617
5672
  var _a;
5618
- return s instanceof ObjNoteGroup && ((_a = s.getBeamGroup()) == null ? void 0 : _a.isTriplet()) !== true ? s : void 0;
5673
+ return s instanceof ObjNoteGroup && ((_a = s.getBeamGroup()) == null ? void 0 : _a.isTuplet()) !== true ? s : void 0;
5619
5674
  });
5620
5675
  ObjNoteGroup.setBeamCounts(groupNotes);
5621
5676
  let beamNotes = [];
@@ -5647,36 +5702,32 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5647
5702
  if (this.getConsumedTicks() === 0) {
5648
5703
  this.completeRests(0);
5649
5704
  } else {
5650
- getVoiceIds().forEach((voiceId2) => {
5651
- if (this.getConsumedTicks(voiceId2) > 0) {
5652
- this.completeRests(voiceId2);
5653
- }
5654
- });
5705
+ this.completeRests(getVoiceIds().filter((id) => this.getConsumedTicks(id) > 0));
5655
5706
  }
5656
5707
  return;
5657
- }
5658
- let measureTicks = this.getMeasureTicks();
5659
- let consumedTicks = this.getConsumedTicks(voiceId);
5660
- let remainingTicks = measureTicks - consumedTicks;
5661
- let rests = [];
5662
- let noteLengthValues = import_ts_utils_lib8.Utils.Enum.getEnumValues(import_theory9.NoteLength);
5663
- while (remainingTicks > 0) {
5664
- noteLengthValues.forEach((restLength) => {
5665
- let restValue = new import_theory9.RhythmProps(restLength, false);
5666
- if (restValue.canDot()) {
5667
- let dottedRestValue = new import_theory9.RhythmProps(restLength, true);
5668
- while (dottedRestValue.ticks <= remainingTicks) {
5669
- rests.push(dottedRestValue);
5670
- remainingTicks -= dottedRestValue.ticks;
5708
+ } else if (import_ts_utils_lib10.Utils.Is.isArray(voiceId)) {
5709
+ voiceId.forEach((id) => this.completeRests(id));
5710
+ return;
5711
+ } else {
5712
+ validateVoiceId(voiceId);
5713
+ let measureTicks = this.getMeasureTicks();
5714
+ let consumedTicks = this.getConsumedTicks(voiceId);
5715
+ let remainingTicks = measureTicks - consumedTicks;
5716
+ let rests = [];
5717
+ while (remainingTicks > 0) {
5718
+ for (let noteSize = import_theory9.NoteLengthProps.LongestNoteSize; noteSize <= import_theory9.NoteLengthProps.ShortestNoteSize; noteSize *= 2) {
5719
+ let restLength = import_theory9.NoteLengthProps.create(noteSize).noteLength;
5720
+ for (let dotCount = import_theory9.NoteLengthProps.get(restLength).maxDotCount; dotCount >= 0; dotCount--) {
5721
+ let restProps = import_theory9.RhythmProps.get(restLength, dotCount);
5722
+ while (restProps.ticks <= remainingTicks) {
5723
+ rests.push(restProps);
5724
+ remainingTicks -= restProps.ticks;
5725
+ }
5671
5726
  }
5672
5727
  }
5673
- while (restValue.ticks <= remainingTicks) {
5674
- rests.push(restValue);
5675
- remainingTicks -= restValue.ticks;
5676
- }
5677
- });
5728
+ }
5729
+ rests.reverse().forEach((rest) => this.addRest(voiceId, rest.noteLength, { dotted: rest.dotCount }));
5678
5730
  }
5679
- rests.reverse().forEach((rest) => this.addRest(voiceId, rest.noteLength, { dotted: rest.dotted }));
5680
5731
  }
5681
5732
  requestLayout() {
5682
5733
  if (!this.needLayout) {
@@ -5769,7 +5820,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5769
5820
  let columnsAreaLeft = this.rect.left + this.leftSolidAreaWidth;
5770
5821
  let columnsAreaRight = this.rect.right - this.rightSolidAreaWidth;
5771
5822
  let columnsAreaWidth = columnsAreaRight - columnsAreaLeft;
5772
- let columnsWidth = import_ts_utils_lib8.Utils.Math.sum(this.columns.map((col) => col.getRect().width));
5823
+ let columnsWidth = import_ts_utils_lib10.Utils.Math.sum(this.columns.map((col) => col.getRect().width));
5773
5824
  let columnScale = columnsAreaWidth / columnsWidth;
5774
5825
  let columnLeft = columnsAreaLeft;
5775
5826
  this.columns.forEach((col) => {
@@ -6109,10 +6160,12 @@ var ObjStaff = class extends ObjNotationLine4 {
6109
6160
  this.clefImageAsset = 0 /* TrebleClefPng */;
6110
6161
  this.clefLineDiatonicId = getDiatonicId("G4", staffConfig.isOctaveDown === true);
6111
6162
  this.middleLineDiatonicId = this.clefLineDiatonicId + 2;
6112
- } else {
6163
+ } else if (staffConfig.clef === "F" /* F */) {
6113
6164
  this.clefImageAsset = 1 /* BassClefPng */;
6114
6165
  this.clefLineDiatonicId = getDiatonicId("F3", staffConfig.isOctaveDown === true);
6115
6166
  this.middleLineDiatonicId = this.clefLineDiatonicId - 2;
6167
+ } else {
6168
+ throw new import_core15.MusicError(import_core15.MusicErrorType.Score, `Invalid staffConfig.clef ${staffConfig.clef}.`);
6116
6169
  }
6117
6170
  this.topLineDiatonicId = this.middleLineDiatonicId + 4;
6118
6171
  this.bottomLineDiatonicId = this.middleLineDiatonicId - 4;
@@ -6248,7 +6301,7 @@ var ObjTab = class extends ObjNotationLine4 {
6248
6301
  __publicField(this, "tuningName");
6249
6302
  __publicField(this, "tuningStrings");
6250
6303
  __publicField(this, "mi");
6251
- if (import_ts_utils_lib9.Utils.Is.isArray(tabConfig.tuning)) {
6304
+ if (import_ts_utils_lib11.Utils.Is.isArray(tabConfig.tuning)) {
6252
6305
  this.tuningName = void 0;
6253
6306
  this.tuningStrings = tabConfig.tuning.map((noteName) => import_theory11.Note.getNote(noteName)).reverse();
6254
6307
  } else if (typeof tabConfig.tuning === "string") {
@@ -6703,7 +6756,7 @@ var ObjHeader = class extends MusicObject {
6703
6756
  };
6704
6757
 
6705
6758
  // src/score/engine/obj-document.ts
6706
- var import_ts_utils_lib10 = require("@tspro/ts-utils-lib");
6759
+ var import_ts_utils_lib12 = require("@tspro/ts-utils-lib");
6707
6760
  var ObjDocument = class extends MusicObject {
6708
6761
  constructor() {
6709
6762
  super(void 0);
@@ -6724,35 +6777,35 @@ var ObjDocument = class extends MusicObject {
6724
6777
  return this.mi;
6725
6778
  }
6726
6779
  setScoreConfiguration(config) {
6727
- if (import_ts_utils_lib10.Utils.Is.isEnumValue(config, StaffPreset)) {
6780
+ if (import_ts_utils_lib12.Utils.Is.isEnumValue(config, StaffPreset)) {
6728
6781
  switch (config) {
6729
6782
  default:
6730
- case 1 /* Treble */:
6783
+ case "treble" /* Treble */:
6731
6784
  this.curScoreConfig = [{ type: "staff", clef: "G" /* G */ }];
6732
6785
  break;
6733
- case 2 /* Bass */:
6786
+ case "bass" /* Bass */:
6734
6787
  this.curScoreConfig = [{ type: "staff", clef: "F" /* F */ }];
6735
6788
  break;
6736
- case 3 /* Grand */:
6789
+ case "grand" /* Grand */:
6737
6790
  this.curScoreConfig = [
6738
6791
  { type: "staff", clef: "G" /* G */, isGrand: true },
6739
6792
  { type: "staff", clef: "F" /* F */, isGrand: true }
6740
6793
  ];
6741
6794
  break;
6742
- case 4 /* GuitarTreble */:
6795
+ case "guitarTreble" /* GuitarTreble */:
6743
6796
  this.curScoreConfig = [{ type: "staff", clef: "G" /* G */, isOctaveDown: true }];
6744
6797
  break;
6745
- case 8 /* GuitarTab */:
6798
+ case "guitarTab" /* GuitarTab */:
6746
6799
  this.curScoreConfig = [{ type: "tab", tuning: "Standard" }];
6747
6800
  break;
6748
- case 12 /* GuitarCombined */:
6801
+ case "guitarCombined" /* GuitarCombined */:
6749
6802
  this.curScoreConfig = [
6750
6803
  { type: "staff", clef: "G" /* G */, isOctaveDown: true },
6751
6804
  { type: "tab", tuning: "Standard" }
6752
6805
  ];
6753
6806
  break;
6754
6807
  }
6755
- } else if (import_ts_utils_lib10.Utils.Is.isArray(config)) {
6808
+ } else if (import_ts_utils_lib12.Utils.Is.isArray(config)) {
6756
6809
  this.curScoreConfig = config;
6757
6810
  } else {
6758
6811
  this.curScoreConfig = [config];
@@ -6994,85 +7047,105 @@ function isNote(note) {
6994
7047
  }
6995
7048
  }
6996
7049
  function isVoiceId(value) {
6997
- return import_ts_utils_lib11.Utils.Is.isNumber(value) && getVoiceIds().indexOf(value) >= 0;
7050
+ return import_ts_utils_lib13.Utils.Is.isNumber(value) && getVoiceIds().indexOf(value) >= 0;
6998
7051
  }
6999
7052
  function isStringNumber(value) {
7000
- return import_ts_utils_lib11.Utils.Is.isNumber(value) && getStringNumbers().indexOf(value) >= 0;
7053
+ return import_ts_utils_lib13.Utils.Is.isNumber(value) && getStringNumbers().indexOf(value) >= 0;
7001
7054
  }
7002
7055
  function assertStaffConfig(staffConfig) {
7003
- assertArg(import_ts_utils_lib11.Utils.Is.isObject(staffConfig), "staffConfig", staffConfig);
7056
+ assertArg(import_ts_utils_lib13.Utils.Is.isObject(staffConfig), "staffConfig", staffConfig);
7004
7057
  assertArg(staffConfig.type === "staff", "staffConfig.type", staffConfig.type);
7005
- assertArg(import_ts_utils_lib11.Utils.Is.isEnumValue(staffConfig.clef, Clef), "staffConfig.clef", staffConfig.clef);
7006
- assertArg(import_ts_utils_lib11.Utils.Is.isBooleanOrUndefined(staffConfig.isOctaveDown), "staffConfig.isOctaveDown", staffConfig.isOctaveDown);
7007
- assertArg(import_ts_utils_lib11.Utils.Is.isUndefined(staffConfig.minNote) || isNote(staffConfig.minNote), "staffConfig.minNote", staffConfig.minNote);
7008
- assertArg(import_ts_utils_lib11.Utils.Is.isUndefined(staffConfig.maxNote) || isNote(staffConfig.maxNote), "staffConfig.maxNote", staffConfig.maxNote);
7009
- assertArg(import_ts_utils_lib11.Utils.Is.isUndefined(staffConfig.voiceIds) || import_ts_utils_lib11.Utils.Is.isArray(staffConfig.voiceIds) && staffConfig.voiceIds.every((voiceId) => import_ts_utils_lib11.Utils.Is.isNumber(voiceId)), "staffConfig.voiceIds", staffConfig.voiceIds);
7010
- assertArg(import_ts_utils_lib11.Utils.Is.isBooleanOrUndefined(staffConfig.isGrand), "staffConfig.isGrand", staffConfig.isGrand);
7058
+ assertArg(import_ts_utils_lib13.Utils.Is.isEnumValue(staffConfig.clef, Clef), "staffConfig.clef", staffConfig.clef);
7059
+ assertArg(import_ts_utils_lib13.Utils.Is.isBooleanOrUndefined(staffConfig.isOctaveDown), "staffConfig.isOctaveDown", staffConfig.isOctaveDown);
7060
+ assertArg(import_ts_utils_lib13.Utils.Is.isUndefined(staffConfig.minNote) || isNote(staffConfig.minNote), "staffConfig.minNote", staffConfig.minNote);
7061
+ assertArg(import_ts_utils_lib13.Utils.Is.isUndefined(staffConfig.maxNote) || isNote(staffConfig.maxNote), "staffConfig.maxNote", staffConfig.maxNote);
7062
+ assertArg(import_ts_utils_lib13.Utils.Is.isUndefined(staffConfig.voiceIds) || import_ts_utils_lib13.Utils.Is.isArray(staffConfig.voiceIds) && staffConfig.voiceIds.every((voiceId) => import_ts_utils_lib13.Utils.Is.isNumber(voiceId)), "staffConfig.voiceIds", staffConfig.voiceIds);
7063
+ assertArg(import_ts_utils_lib13.Utils.Is.isBooleanOrUndefined(staffConfig.isGrand), "staffConfig.isGrand", staffConfig.isGrand);
7011
7064
  }
7012
7065
  function assertTabConfig(tabConfig) {
7013
- assertArg(import_ts_utils_lib11.Utils.Is.isObject(tabConfig), "tabConfig", tabConfig);
7066
+ assertArg(import_ts_utils_lib13.Utils.Is.isObject(tabConfig), "tabConfig", tabConfig);
7014
7067
  assertArg(tabConfig.type === "tab", "tabConfig.type", tabConfig.type);
7015
7068
  if (typeof tabConfig.tuning === "string") {
7016
7069
  assertArg(import_theory13.TuningNameList.includes(tabConfig.tuning), "tabConfig.tuning", tabConfig.tuning);
7017
- } else if (import_ts_utils_lib11.Utils.Is.isArray(tabConfig.tuning)) {
7018
- assertArg(tabConfig.tuning.length === 6 && tabConfig.tuning.every((s) => isNote(s)), "tabConfig.tuning", tabConfig.tuning);
7070
+ } else if (import_ts_utils_lib13.Utils.Is.isArray(tabConfig.tuning)) {
7071
+ assertArg(tabConfig.tuning.length === getStringNumbers().length && tabConfig.tuning.every((s) => isNote(s)), "tabConfig.tuning", tabConfig.tuning);
7019
7072
  }
7020
- assertArg(import_ts_utils_lib11.Utils.Is.isUndefined(tabConfig.voiceIds) || import_ts_utils_lib11.Utils.Is.isArray(tabConfig.voiceIds) && tabConfig.voiceIds.every((voiceId) => import_ts_utils_lib11.Utils.Is.isNumber(voiceId)), "tabConfig.voiceIds", tabConfig.voiceIds);
7073
+ assertArg(import_ts_utils_lib13.Utils.Is.isUndefined(tabConfig.voiceIds) || import_ts_utils_lib13.Utils.Is.isArray(tabConfig.voiceIds) && tabConfig.voiceIds.every((voiceId) => import_ts_utils_lib13.Utils.Is.isNumber(voiceId)), "tabConfig.voiceIds", tabConfig.voiceIds);
7021
7074
  }
7022
7075
  function assertNoteOptions(options) {
7023
- assertArg(import_ts_utils_lib11.Utils.Is.isObject(options), "noteOptions", options);
7024
- assertArg(import_ts_utils_lib11.Utils.Is.isBooleanOrUndefined(options.dotted), "noteOptions.dotted", options.dotted);
7025
- assertArg(import_ts_utils_lib11.Utils.Is.isEnumValueOrUndefined(options.stem, Stem), "noteOptions.stem", options.stem);
7026
- assertArg(import_ts_utils_lib11.Utils.Is.isStringOrUndefined(options.color), "noteOptions.color", options.color);
7027
- assertArg(import_ts_utils_lib11.Utils.Is.isBooleanOrUndefined(options.arpeggio) || import_ts_utils_lib11.Utils.Is.isEnumValue(options.arpeggio, Arpeggio), "noteOptions.arpeggio", options.arpeggio);
7028
- assertArg(import_ts_utils_lib11.Utils.Is.isBooleanOrUndefined(options.staccato), "noteOptions.staccato", options.staccato);
7029
- assertArg(import_ts_utils_lib11.Utils.Is.isBooleanOrUndefined(options.diamond), "noteOptions.diamond", options.diamond);
7030
- assertArg(import_ts_utils_lib11.Utils.Is.isBooleanOrUndefined(options.triplet), "noteOptions.triplet", options.triplet);
7031
- assertArg(import_ts_utils_lib11.Utils.Is.isUndefined(options.string) || isStringNumber(options.string) || import_ts_utils_lib11.Utils.Is.isArray(options.string) && options.string.length > 0 && options.string.every((string) => isStringNumber(string)), "noteOptions.string", options.string);
7076
+ assertArg(import_ts_utils_lib13.Utils.Is.isObject(options), "noteOptions", options);
7077
+ assertArg(import_ts_utils_lib13.Utils.Is.isBooleanOrUndefined(options.dotted) || import_ts_utils_lib13.Utils.Is.isIntegerGte(options.dotted, 0), "noteOptions.dotted", options.dotted);
7078
+ assertArg(import_ts_utils_lib13.Utils.Is.isEnumValueOrUndefined(options.stem, Stem), "noteOptions.stem", options.stem);
7079
+ assertArg(import_ts_utils_lib13.Utils.Is.isStringOrUndefined(options.color), "noteOptions.color", options.color);
7080
+ assertArg(import_ts_utils_lib13.Utils.Is.isBooleanOrUndefined(options.arpeggio) || import_ts_utils_lib13.Utils.Is.isEnumValue(options.arpeggio, Arpeggio), "noteOptions.arpeggio", options.arpeggio);
7081
+ assertArg(import_ts_utils_lib13.Utils.Is.isBooleanOrUndefined(options.staccato), "noteOptions.staccato", options.staccato);
7082
+ assertArg(import_ts_utils_lib13.Utils.Is.isBooleanOrUndefined(options.diamond), "noteOptions.diamond", options.diamond);
7083
+ assertArg(import_ts_utils_lib13.Utils.Is.isBooleanOrUndefined(options.triplet), "noteOptions.triplet", options.triplet);
7084
+ assertArg(import_ts_utils_lib13.Utils.Is.isUndefined(options.string) || isStringNumber(options.string) || import_ts_utils_lib13.Utils.Is.isNonEmptyArray(options.string) && options.string.every((string) => isStringNumber(string)), "noteOptions.string", options.string);
7085
+ assertArg(import_ts_utils_lib13.Utils.Is.isUndefined(options.tieSpan), 'NoteOptions.tieSpan was removed. Use addConnective("tie", tieSpan)', "");
7086
+ assertArg(import_ts_utils_lib13.Utils.Is.isUndefined(options.slurSpan), 'NoteOptions.slurSpan was removed. Use addConnective("slur", slurSpan)', "");
7032
7087
  }
7033
7088
  function assertRestOptions(options) {
7034
- assertArg(import_ts_utils_lib11.Utils.Is.isObject(options), "restOptions", options);
7035
- assertArg(import_ts_utils_lib11.Utils.Is.isBooleanOrUndefined(options.dotted), "restOptions.dotted", options.dotted);
7036
- assertArg(import_ts_utils_lib11.Utils.Is.isStringOrUndefined(options.staffPos) || import_ts_utils_lib11.Utils.Is.isInteger(options.staffPos) || options.staffPos instanceof import_theory13.Note, "restOptions.staffPos", options.staffPos);
7037
- assertArg(import_ts_utils_lib11.Utils.Is.isStringOrUndefined(options.color), "restOptions.color", options.color);
7038
- assertArg(import_ts_utils_lib11.Utils.Is.isBooleanOrUndefined(options.hide), "restOptions.hide", options.hide);
7039
- assertArg(import_ts_utils_lib11.Utils.Is.isBooleanOrUndefined(options.triplet), "restOptions.triplet", options.triplet);
7089
+ assertArg(import_ts_utils_lib13.Utils.Is.isObject(options), "restOptions", options);
7090
+ assertArg(import_ts_utils_lib13.Utils.Is.isBooleanOrUndefined(options.dotted) || import_ts_utils_lib13.Utils.Is.isIntegerGte(options.dotted, 0), "restOptions.dotted", options.dotted);
7091
+ assertArg(import_ts_utils_lib13.Utils.Is.isStringOrUndefined(options.staffPos) || import_ts_utils_lib13.Utils.Is.isInteger(options.staffPos) || options.staffPos instanceof import_theory13.Note, "restOptions.staffPos", options.staffPos);
7092
+ assertArg(import_ts_utils_lib13.Utils.Is.isStringOrUndefined(options.color), "restOptions.color", options.color);
7093
+ assertArg(import_ts_utils_lib13.Utils.Is.isBooleanOrUndefined(options.hide), "restOptions.hide", options.hide);
7094
+ assertArg(import_ts_utils_lib13.Utils.Is.isBooleanOrUndefined(options.triplet), "restOptions.triplet", options.triplet);
7040
7095
  }
7041
7096
  function assertStaffTabOrGRoups(staffTabOrGroups) {
7042
7097
  assertArg(
7043
- import_ts_utils_lib11.Utils.Is.isStringOrUndefined(staffTabOrGroups) || import_ts_utils_lib11.Utils.Is.isIntegerGte(staffTabOrGroups, 0) || import_ts_utils_lib11.Utils.Is.isArray(staffTabOrGroups) && staffTabOrGroups.every(
7044
- (staffTabOrGroup) => import_ts_utils_lib11.Utils.Is.isString(staffTabOrGroup) || import_ts_utils_lib11.Utils.Is.isIntegerGte(staffTabOrGroup, 0)
7098
+ import_ts_utils_lib13.Utils.Is.isStringOrUndefined(staffTabOrGroups) || import_ts_utils_lib13.Utils.Is.isIntegerGte(staffTabOrGroups, 0) || import_ts_utils_lib13.Utils.Is.isNonEmptyArray(staffTabOrGroups) && staffTabOrGroups.every(
7099
+ (staffTabOrGroup) => import_ts_utils_lib13.Utils.Is.isString(staffTabOrGroup) || import_ts_utils_lib13.Utils.Is.isIntegerGte(staffTabOrGroup, 0)
7045
7100
  ),
7046
7101
  "staffTabOrGroup",
7047
7102
  staffTabOrGroups
7048
7103
  );
7049
7104
  }
7105
+ function isNoteLength(noteLen) {
7106
+ try {
7107
+ (0, import_theory13.validateNoteLength)(noteLen);
7108
+ return true;
7109
+ } catch (e) {
7110
+ return false;
7111
+ }
7112
+ }
7113
+ function isTupletRatio(tupletRatio) {
7114
+ try {
7115
+ (0, import_theory13.validateTupletRatio)(tupletRatio);
7116
+ return true;
7117
+ } catch (e) {
7118
+ return false;
7119
+ }
7120
+ }
7050
7121
  var DocumentBuilder = class {
7051
7122
  constructor() {
7052
7123
  __publicField(this, "doc");
7053
7124
  this.doc = new ObjDocument();
7054
7125
  }
7055
7126
  setScoreConfiguration(config) {
7056
- if (import_ts_utils_lib11.Utils.Is.isEnumValue(config, StaffPreset)) {
7057
- } else if (import_ts_utils_lib11.Utils.Is.isObject(config) && config.type === "staff") {
7127
+ if (import_ts_utils_lib13.Utils.Is.isEnumValue(config, StaffPreset)) {
7128
+ this.doc.setScoreConfiguration(config);
7129
+ } else if (import_ts_utils_lib13.Utils.Is.isObject(config) && config.type === "staff") {
7058
7130
  assertStaffConfig(config);
7059
- } else if (import_ts_utils_lib11.Utils.Is.isObject(config) && config.type === "tab") {
7131
+ this.doc.setScoreConfiguration(config);
7132
+ } else if (import_ts_utils_lib13.Utils.Is.isObject(config) && config.type === "tab") {
7060
7133
  assertTabConfig(config);
7061
- } else if (import_ts_utils_lib11.Utils.Is.isArray(config)) {
7062
- assertArg(config.length > 0, "config", config);
7134
+ this.doc.setScoreConfiguration(config);
7135
+ } else if (import_ts_utils_lib13.Utils.Is.isNonEmptyArray(config)) {
7063
7136
  config.forEach((c) => {
7064
- if (import_ts_utils_lib11.Utils.Is.isObject(c) && c.type === "staff") {
7137
+ if (import_ts_utils_lib13.Utils.Is.isObject(c) && c.type === "staff") {
7065
7138
  assertStaffConfig(c);
7066
- } else if (import_ts_utils_lib11.Utils.Is.isObject(c) && c.type === "tab") {
7139
+ } else if (import_ts_utils_lib13.Utils.Is.isObject(c) && c.type === "tab") {
7067
7140
  assertTabConfig(c);
7068
7141
  } else {
7069
7142
  assertArg(false, "config", config);
7070
7143
  }
7071
7144
  });
7145
+ this.doc.setScoreConfiguration(config);
7072
7146
  } else {
7073
7147
  assertArg(false, "config", config);
7074
7148
  }
7075
- this.doc.setScoreConfiguration(config);
7076
7149
  return this;
7077
7150
  }
7078
7151
  getMeasure() {
@@ -7083,14 +7156,14 @@ var DocumentBuilder = class {
7083
7156
  return this.doc.getMusicInterface();
7084
7157
  }
7085
7158
  setHeader(title, composer, arranger) {
7086
- assertArg(import_ts_utils_lib11.Utils.Is.isStringOrUndefined(title), "title", title);
7087
- assertArg(import_ts_utils_lib11.Utils.Is.isStringOrUndefined(composer), "composer", composer);
7088
- assertArg(import_ts_utils_lib11.Utils.Is.isStringOrUndefined(arranger), "arranger", arranger);
7159
+ assertArg(import_ts_utils_lib13.Utils.Is.isStringOrUndefined(title), "title", title);
7160
+ assertArg(import_ts_utils_lib13.Utils.Is.isStringOrUndefined(composer), "composer", composer);
7161
+ assertArg(import_ts_utils_lib13.Utils.Is.isStringOrUndefined(arranger), "arranger", arranger);
7089
7162
  this.doc.setHeader(title, composer, arranger);
7090
7163
  return this;
7091
7164
  }
7092
7165
  setMeasuresPerRow(measuresPerRow) {
7093
- assertArg(import_ts_utils_lib11.Utils.Is.isIntegerGte(measuresPerRow, 1) || measuresPerRow === Infinity, "measuresPerRow", measuresPerRow);
7166
+ assertArg(import_ts_utils_lib13.Utils.Is.isIntegerGte(measuresPerRow, 1) || import_ts_utils_lib13.Utils.Is.isPosInfinity(measuresPerRow), "measuresPerRow", measuresPerRow);
7094
7167
  this.doc.setMeasuresPerRow(measuresPerRow);
7095
7168
  return this;
7096
7169
  }
@@ -7099,30 +7172,30 @@ var DocumentBuilder = class {
7099
7172
  return this;
7100
7173
  }
7101
7174
  setKeySignature(...args) {
7102
- assertArg(args[0] instanceof import_theory13.Scale || args[0] instanceof import_theory13.KeySignature || import_ts_utils_lib11.Utils.Is.isString(args[0]) && import_ts_utils_lib11.Utils.Is.isEnumValue(args[1], import_theory13.ScaleType), "keySignature", args);
7175
+ assertArg(args[0] instanceof import_theory13.Scale || args[0] instanceof import_theory13.KeySignature || import_ts_utils_lib13.Utils.Is.isNonEmptyString(args[0]) && (args.length === 1 || import_ts_utils_lib13.Utils.Is.isEnumValue(args[1], import_theory13.ScaleType)), "keySignature", args);
7103
7176
  this.getMeasure().setKeySignature(...args);
7104
7177
  return this;
7105
7178
  }
7106
7179
  setTimeSignature(timeSignature) {
7107
- assertArg(timeSignature instanceof import_theory13.TimeSignature || import_ts_utils_lib11.Utils.Is.isString(timeSignature), "timeSignature", timeSignature);
7180
+ assertArg(timeSignature instanceof import_theory13.TimeSignature || import_ts_utils_lib13.Utils.Is.isNonEmptyString(timeSignature), "timeSignature", timeSignature);
7108
7181
  this.getMeasure().setTimeSignature(timeSignature);
7109
7182
  return this;
7110
7183
  }
7111
7184
  setTempo(beatsPerMinute, beatLength, dotted) {
7112
- assertArg(import_ts_utils_lib11.Utils.Is.isIntegerGte(beatsPerMinute, 1), "beatsPerMinute", beatsPerMinute);
7185
+ assertArg(import_ts_utils_lib13.Utils.Is.isIntegerGte(beatsPerMinute, 1), "beatsPerMinute", beatsPerMinute);
7113
7186
  if (beatLength === void 0) {
7114
- assertArg(import_ts_utils_lib11.Utils.Is.isUndefined(dotted), "dotted", dotted);
7187
+ assertArg(import_ts_utils_lib13.Utils.Is.isUndefined(dotted), "dotted", dotted);
7115
7188
  } else {
7116
- assertArg(import_ts_utils_lib11.Utils.Is.isEnumValue(beatLength, import_theory13.NoteLength), "beatLength", beatLength);
7117
- assertArg(import_ts_utils_lib11.Utils.Is.isBooleanOrUndefined(dotted), "dotted", dotted);
7189
+ assertArg(import_ts_utils_lib13.Utils.Is.isEnumValue(beatLength, import_theory13.NoteLength) || isNoteLength(beatLength), "beatLength", beatLength);
7190
+ assertArg(import_ts_utils_lib13.Utils.Is.isBooleanOrUndefined(dotted) || import_ts_utils_lib13.Utils.Is.isIntegerGte(dotted, 0), "dotted", dotted);
7118
7191
  }
7119
7192
  this.getMeasure().setTempo(beatsPerMinute, beatLength, dotted);
7120
7193
  return this;
7121
7194
  }
7122
7195
  addNote(voiceId, note, noteLength, options) {
7123
7196
  assertArg(isVoiceId(voiceId), "voiceId", voiceId);
7124
- assertArg(note instanceof import_theory13.Note || import_ts_utils_lib11.Utils.Is.isString(note), "note", note);
7125
- assertArg(import_ts_utils_lib11.Utils.Is.isEnumValue(noteLength, import_theory13.NoteLength), "noteLength", noteLength);
7197
+ assertArg(note instanceof import_theory13.Note || import_ts_utils_lib13.Utils.Is.isNonEmptyString(note), "note", note);
7198
+ assertArg(import_ts_utils_lib13.Utils.Is.isEnumValue(noteLength, import_theory13.NoteLength) || isNoteLength(noteLength), "noteLength", noteLength);
7126
7199
  if (options !== void 0) {
7127
7200
  assertNoteOptions(options);
7128
7201
  }
@@ -7131,8 +7204,8 @@ var DocumentBuilder = class {
7131
7204
  }
7132
7205
  addChord(voiceId, notes, noteLength, options) {
7133
7206
  assertArg(isVoiceId(voiceId), "voiceId", voiceId);
7134
- assertArg(import_ts_utils_lib11.Utils.Is.isArray(notes) && notes.length >= 1 && notes.every((note) => note instanceof import_theory13.Note || import_ts_utils_lib11.Utils.Is.isString(note)), "notes", notes);
7135
- assertArg(import_ts_utils_lib11.Utils.Is.isEnumValue(noteLength, import_theory13.NoteLength), "noteLength", noteLength);
7207
+ assertArg(import_ts_utils_lib13.Utils.Is.isNonEmptyArray(notes) && notes.every((note) => note instanceof import_theory13.Note || import_ts_utils_lib13.Utils.Is.isNonEmptyString(note)), "notes", notes);
7208
+ assertArg(import_ts_utils_lib13.Utils.Is.isEnumValue(noteLength, import_theory13.NoteLength) || isNoteLength(noteLength), "noteLength", noteLength);
7136
7209
  if (options !== void 0) {
7137
7210
  assertNoteOptions(options);
7138
7211
  }
@@ -7141,33 +7214,91 @@ var DocumentBuilder = class {
7141
7214
  }
7142
7215
  addRest(voiceId, restLength, options) {
7143
7216
  assertArg(isVoiceId(voiceId), "voiceId", voiceId);
7144
- assertArg(import_ts_utils_lib11.Utils.Is.isEnumValue(restLength, import_theory13.NoteLength), "restLength", restLength);
7217
+ assertArg(import_ts_utils_lib13.Utils.Is.isEnumValue(restLength, import_theory13.NoteLength) || isNoteLength(restLength), "restLength", restLength);
7145
7218
  if (options !== void 0) {
7146
7219
  assertRestOptions(options);
7147
7220
  }
7148
7221
  this.getMeasure().addRest(voiceId, restLength, options);
7149
7222
  return this;
7150
7223
  }
7224
+ /**
7225
+ * Usage:
7226
+ * <pre>
7227
+ * addTuplet(0, Theory.Tuplet.Triplet, notes => {
7228
+ * notes.addNote("G3", Theory.NoteLength.Eighth);
7229
+ * notes.addNote("B3", Theory.NoteLength.Eighth);
7230
+ * notes.addNote("D4", Theory.NoteLength.Eighth);
7231
+ * });
7232
+ * </pre>
7233
+ *
7234
+ * @param voiceId
7235
+ * @param tupletRatio - You can also use Theory.Tuplet presets (e.g. Theory.Tuplet.Triplet).
7236
+ * @param tupletBuilder
7237
+ * @returns
7238
+ */
7239
+ addTuplet(voiceId, tupletRatio, tupletBuilder) {
7240
+ assertArg(isVoiceId(voiceId), "voiceId", voiceId);
7241
+ assertArg(import_ts_utils_lib13.Utils.Is.isFunction(tupletBuilder), "tupletBuilder", tupletBuilder);
7242
+ assertArg(isTupletRatio(tupletRatio) && import_ts_utils_lib13.Utils.Is.isBooleanOrUndefined(tupletRatio.showRatio), "tupletRatio", tupletRatio);
7243
+ let tupletSymbols = [];
7244
+ const helper = {
7245
+ addNote: (note, noteLength, options) => {
7246
+ assertArg(note instanceof import_theory13.Note || import_ts_utils_lib13.Utils.Is.isNonEmptyString(note), "note", note);
7247
+ assertArg(import_ts_utils_lib13.Utils.Is.isEnumValue(noteLength, import_theory13.NoteLength) || isNoteLength(noteLength), "noteLength", noteLength);
7248
+ if (options !== void 0) {
7249
+ delete options.triplet;
7250
+ assertNoteOptions(options);
7251
+ }
7252
+ let s = this.getMeasure().addNoteGroup(voiceId, [note], noteLength, options, tupletRatio);
7253
+ tupletSymbols.push(s);
7254
+ return helper;
7255
+ },
7256
+ addChord: (notes, noteLength, options) => {
7257
+ assertArg(import_ts_utils_lib13.Utils.Is.isNonEmptyArray(notes) && notes.every((note) => note instanceof import_theory13.Note || import_ts_utils_lib13.Utils.Is.isNonEmptyString(note)), "notes", notes);
7258
+ assertArg(import_ts_utils_lib13.Utils.Is.isEnumValue(noteLength, import_theory13.NoteLength) || isNoteLength(noteLength), "noteLength", noteLength);
7259
+ if (options !== void 0) {
7260
+ delete options.triplet;
7261
+ assertNoteOptions(options);
7262
+ }
7263
+ let s = this.getMeasure().addNoteGroup(voiceId, notes, noteLength, options, tupletRatio);
7264
+ tupletSymbols.push(s);
7265
+ return helper;
7266
+ },
7267
+ addRest: (restLength, options) => {
7268
+ assertArg(import_ts_utils_lib13.Utils.Is.isEnumValue(restLength, import_theory13.NoteLength) || isNoteLength(restLength), "restLength", restLength);
7269
+ if (options !== void 0) {
7270
+ delete options.triplet;
7271
+ assertRestOptions(options);
7272
+ }
7273
+ let s = this.getMeasure().addRest(voiceId, restLength, options, tupletRatio);
7274
+ tupletSymbols.push(s);
7275
+ return helper;
7276
+ }
7277
+ };
7278
+ tupletBuilder(helper);
7279
+ ObjBeamGroup.createTuplet(tupletSymbols, tupletRatio);
7280
+ return this;
7281
+ }
7151
7282
  addFermataInternal(staffTabOrGroups, fermata) {
7152
7283
  assertStaffTabOrGRoups(staffTabOrGroups);
7153
- assertArg(import_ts_utils_lib11.Utils.Is.isEnumValue(fermata, Fermata), "fermata", fermata);
7284
+ assertArg(import_ts_utils_lib13.Utils.Is.isEnumValue(fermata, Fermata), "fermata", fermata);
7154
7285
  this.getMeasure().addFermata(staffTabOrGroups, fermata);
7155
7286
  return this;
7156
7287
  }
7157
- addFermata(fermata = 0 /* AtNote */) {
7288
+ addFermata(fermata = "atNote" /* AtNote */) {
7158
7289
  return this.addFermataInternal(void 0, fermata);
7159
7290
  }
7160
7291
  /** @param staffTabOrGroups - staff/tab index (0=top), staff/tab name, or staff group name. */
7161
- addFermataTo(staffTabOrGroups, fermata = 0 /* AtNote */) {
7292
+ addFermataTo(staffTabOrGroups, fermata = "atNote" /* AtNote */) {
7162
7293
  return this.addFermataInternal(staffTabOrGroups, fermata);
7163
7294
  }
7164
7295
  addNavigationInternal(staffTabOrGroups, navigation, ...args) {
7165
7296
  assertStaffTabOrGRoups(staffTabOrGroups);
7166
- assertArg(import_ts_utils_lib11.Utils.Is.isEnumValue(navigation, Navigation), "navigation", navigation);
7167
- if (navigation === 9 /* EndRepeat */ && args.length > 0) {
7168
- assertArg(import_ts_utils_lib11.Utils.Is.isIntegerGte(args[0], 1), "playCount", args[0]);
7169
- } else if (navigation === 10 /* Ending */ && args.length > 0) {
7170
- assertArg(args.every((passage) => import_ts_utils_lib11.Utils.Is.isIntegerGte(passage, 1)), "passages", args);
7297
+ assertArg(import_ts_utils_lib13.Utils.Is.isEnumValue(navigation, Navigation), "navigation", navigation);
7298
+ if (navigation === "endRepeat" /* EndRepeat */ && args.length > 0) {
7299
+ assertArg(import_ts_utils_lib13.Utils.Is.isIntegerGte(args[0], 1), "playCount", args[0]);
7300
+ } else if (navigation === "ending" /* Ending */ && args.length > 0) {
7301
+ assertArg(args.every((passage) => import_ts_utils_lib13.Utils.Is.isIntegerGte(passage, 1)), "passages", args);
7171
7302
  }
7172
7303
  this.getMeasure().addNavigation(staffTabOrGroups, navigation, ...args);
7173
7304
  return this;
@@ -7178,10 +7309,35 @@ var DocumentBuilder = class {
7178
7309
  addNavigationTo(staffTabOrGroups, navigation, ...args) {
7179
7310
  return this.addNavigationInternal(staffTabOrGroups, navigation, ...args);
7180
7311
  }
7312
+ addAnnotationInternal(staffTabOrGroups, annotation, text) {
7313
+ annotation != null ? annotation : annotation = getAnnotation(text);
7314
+ if (annotation === void 0) {
7315
+ throw new import_core17.MusicError(import_core17.MusicErrorType.Score, `Annotation text "${text}" is not known annotation.`);
7316
+ }
7317
+ assertStaffTabOrGRoups(staffTabOrGroups);
7318
+ assertArg(import_ts_utils_lib13.Utils.Is.isEnumValue(annotation, Annotation), "annotation", annotation);
7319
+ assertArg(import_ts_utils_lib13.Utils.Is.isNonEmptyString(text), "text", text);
7320
+ this.getMeasure().addAnnotation(staffTabOrGroups, annotation, text);
7321
+ return this;
7322
+ }
7323
+ addAnnotation(...args) {
7324
+ if (args.length === 1) {
7325
+ return this.addAnnotationInternal(void 0, void 0, args[0]);
7326
+ } else {
7327
+ return this.addAnnotationInternal(void 0, args[0], args[1]);
7328
+ }
7329
+ }
7330
+ addAnnotationTo(staffTabOrGroups, ...args) {
7331
+ if (args.length === 1) {
7332
+ return this.addAnnotationInternal(staffTabOrGroups, void 0, args[0]);
7333
+ } else {
7334
+ return this.addAnnotationInternal(staffTabOrGroups, args[0], args[1]);
7335
+ }
7336
+ }
7181
7337
  addLabelInternal(staffTabOrGroups, label, text) {
7182
7338
  assertStaffTabOrGRoups(staffTabOrGroups);
7183
- assertArg(import_ts_utils_lib11.Utils.Is.isEnumValue(label, Label), "label", label);
7184
- assertArg(import_ts_utils_lib11.Utils.Is.isString(text), "text", text);
7339
+ assertArg(import_ts_utils_lib13.Utils.Is.isEnumValue(label, Label), "label", label);
7340
+ assertArg(import_ts_utils_lib13.Utils.Is.isNonEmptyString(text), "text", text);
7185
7341
  this.getMeasure().addLabel(staffTabOrGroups, label, text);
7186
7342
  return this;
7187
7343
  }
@@ -7192,45 +7348,70 @@ var DocumentBuilder = class {
7192
7348
  addLabelTo(staffTabOrGroups, label, text) {
7193
7349
  return this.addLabelInternal(staffTabOrGroups, label, text);
7194
7350
  }
7195
- addAnnotationInternal(staffTabOrGroups, annotation, text) {
7196
- assertStaffTabOrGRoups(staffTabOrGroups);
7197
- assertArg(import_ts_utils_lib11.Utils.Is.isEnumValue(annotation, Annotation), "annotation", annotation);
7198
- assertArg(import_ts_utils_lib11.Utils.Is.isString(text), "text", text);
7199
- this.getMeasure().addAnnotation(staffTabOrGroups, annotation, text);
7200
- return this;
7201
- }
7202
- addAnnotation(annotation, text) {
7203
- return this.addAnnotationInternal(void 0, annotation, text);
7204
- }
7205
- /** @param staffTabOrGroups - staff/tab index (0=top), staff/tab name, or staff group name. */
7206
- addAnnotationTo(staffTabOrGroups, annotation, text) {
7207
- return this.addAnnotationInternal(staffTabOrGroups, annotation, text);
7208
- }
7209
7351
  addConnective(connective, ...args) {
7210
- assertArg(import_ts_utils_lib11.Utils.Is.isEnumValue(connective, Connective), "connective", connective);
7211
- if (connective === 0 /* Tie */) {
7212
- assertArg(import_ts_utils_lib11.Utils.Is.isUndefined(args[0]) || import_ts_utils_lib11.Utils.Is.isInteger(args[0]) || import_ts_utils_lib11.Utils.Is.isEnumValue(args[0], TieType), "tieSpan", args[0]);
7213
- assertArg(import_ts_utils_lib11.Utils.Is.isEnumValueOrUndefined(args[1], NoteAnchor), "noteAnchor", args[1]);
7352
+ assertArg(import_ts_utils_lib13.Utils.Is.isEnumValue(connective, Connective), "connective", connective);
7353
+ if (connective === "tie" /* Tie */) {
7354
+ assertArg(import_ts_utils_lib13.Utils.Is.isIntegerOrUndefined(args[0]) || import_ts_utils_lib13.Utils.Is.isEnumValue(args[0], TieType), "tieSpan", args[0]);
7355
+ assertArg(import_ts_utils_lib13.Utils.Is.isEnumValueOrUndefined(args[1], NoteAnchor), "noteAnchor", args[1]);
7214
7356
  let tieSpan = args[0];
7215
7357
  let noteAnchor = args[1];
7216
7358
  this.getMeasure().addConnective(connective, tieSpan, noteAnchor);
7217
- } else if (connective === 1 /* Slur */) {
7218
- assertArg(import_ts_utils_lib11.Utils.Is.isUndefined(args[0]) || import_ts_utils_lib11.Utils.Is.isInteger(args[0]), "slurSpan", args[0]);
7219
- assertArg(import_ts_utils_lib11.Utils.Is.isEnumValueOrUndefined(args[1], NoteAnchor), "noteAnchor", args[1]);
7359
+ } else if (connective === "slur" /* Slur */) {
7360
+ assertArg(import_ts_utils_lib13.Utils.Is.isIntegerOrUndefined(args[0]), "slurSpan", args[0]);
7361
+ assertArg(import_ts_utils_lib13.Utils.Is.isEnumValueOrUndefined(args[1], NoteAnchor), "noteAnchor", args[1]);
7220
7362
  let slurSpan = args[0];
7221
7363
  let noteAnchor = args[1];
7222
7364
  this.getMeasure().addConnective(connective, slurSpan, noteAnchor);
7223
- } else if (connective === 2 /* Slide */) {
7224
- assertArg(import_ts_utils_lib11.Utils.Is.isEnumValueOrUndefined(args[0], NoteAnchor), "noteAnchor", args[0]);
7365
+ } else if (connective === "slide" /* Slide */) {
7366
+ assertArg(import_ts_utils_lib13.Utils.Is.isEnumValueOrUndefined(args[0], NoteAnchor), "noteAnchor", args[0]);
7225
7367
  let noteAnchor = args[0];
7226
7368
  this.getMeasure().addConnective(connective, noteAnchor);
7227
7369
  }
7228
7370
  return this;
7229
7371
  }
7230
- addExtension(extensionLength, extensionVisible) {
7231
- assertArg(import_ts_utils_lib11.Utils.Is.isIntegerGte(extensionLength, 0) || extensionLength === Infinity || import_ts_utils_lib11.Utils.Is.isEnumValue(extensionLength, import_theory13.NoteLength), "extendionLength", extensionLength);
7232
- assertArg(import_ts_utils_lib11.Utils.Is.isBooleanOrUndefined(extensionVisible), "extensionVisible", extensionVisible);
7233
- this.getMeasure().addExtension(extensionLength, extensionVisible != null ? extensionVisible : true);
7372
+ /**
7373
+ * Extension length example:
7374
+ * <pre>
7375
+ * addExtension(ext => ext.notes("1n", 2)) // length is 2 whole notes
7376
+ * addExtension(ext => ext.measures(3).hide()) // length is 3 measures, hidden
7377
+ * addExtension(ext => ext.measures(1).notes("8n")) // length is 1 measure + 1 eigth note
7378
+ * addExtension(ext => ext.infinity()) // length is as long as possible
7379
+ * </pre>
7380
+ * @param extensionLength
7381
+ * @param extensionVisible
7382
+ * @returns
7383
+ */
7384
+ addExtension(extensionBuilder) {
7385
+ assertArg(import_ts_utils_lib13.Utils.Is.isFunctionOrUndefined(extensionBuilder), "addExtension() has new usage, for e.g. addExtension(ext => ext.measures(2)). Please refer to README or API Reference.", extensionBuilder);
7386
+ let ticks = 0;
7387
+ let visible = true;
7388
+ const helper = {
7389
+ notes: (noteLength, noteCount) => {
7390
+ assertArg(import_ts_utils_lib13.Utils.Is.isEnumValue(noteLength, import_theory13.NoteLength) || isNoteLength(noteLength), "noteLength", noteLength);
7391
+ assertArg(import_ts_utils_lib13.Utils.Is.isUndefined(noteCount) || import_ts_utils_lib13.Utils.Is.isNumber(noteCount) && noteCount >= 0, "noteCount", noteCount);
7392
+ ticks += import_theory13.RhythmProps.get(noteLength).ticks * (noteCount != null ? noteCount : 1);
7393
+ return helper;
7394
+ },
7395
+ measures: (measureCount) => {
7396
+ assertArg(import_ts_utils_lib13.Utils.Is.isNumber(measureCount) && measureCount >= 1, "measureCount", measureCount);
7397
+ ticks += this.getMeasure().getMeasureTicks() * measureCount;
7398
+ return helper;
7399
+ },
7400
+ infinity: () => {
7401
+ ticks = Infinity;
7402
+ return helper;
7403
+ },
7404
+ hide: () => {
7405
+ visible = false;
7406
+ return helper;
7407
+ }
7408
+ };
7409
+ if (extensionBuilder) {
7410
+ extensionBuilder(helper);
7411
+ } else {
7412
+ ticks = Infinity;
7413
+ }
7414
+ this.getMeasure().addExtension(ticks, visible);
7234
7415
  return this;
7235
7416
  }
7236
7417
  /**
@@ -7240,14 +7421,14 @@ var DocumentBuilder = class {
7240
7421
  * @param verticalPosition - Vertical position, are elements added above, below or both.
7241
7422
  * @returns
7242
7423
  */
7243
- addStaffGroup(groupName, staffsTabsAndGroups, verticalPosition = 3 /* Auto */) {
7244
- assertArg(import_ts_utils_lib11.Utils.Is.isString(groupName) && groupName.length > 0, "groupName", groupName);
7424
+ addStaffGroup(groupName, staffsTabsAndGroups, verticalPosition = "auto" /* Auto */) {
7425
+ assertArg(import_ts_utils_lib13.Utils.Is.isNonEmptyString(groupName), "groupName", groupName);
7245
7426
  assertArg(
7246
- import_ts_utils_lib11.Utils.Is.isString(staffsTabsAndGroups) && staffsTabsAndGroups.length > 0 || import_ts_utils_lib11.Utils.Is.isIntegerGte(staffsTabsAndGroups, 0) || import_ts_utils_lib11.Utils.Is.isArray(staffsTabsAndGroups) && staffsTabsAndGroups.every((line) => import_ts_utils_lib11.Utils.Is.isString(line) && line.length > 0 || import_ts_utils_lib11.Utils.Is.isIntegerGte(line, 0)),
7427
+ import_ts_utils_lib13.Utils.Is.isNonEmptyString(staffsTabsAndGroups) || import_ts_utils_lib13.Utils.Is.isIntegerGte(staffsTabsAndGroups, 0) || import_ts_utils_lib13.Utils.Is.isNonEmptyArray(staffsTabsAndGroups) && staffsTabsAndGroups.every((line) => import_ts_utils_lib13.Utils.Is.isNonEmptyString(line) || import_ts_utils_lib13.Utils.Is.isIntegerGte(line, 0)),
7247
7428
  "staffsTabsAndGroups",
7248
7429
  staffsTabsAndGroups
7249
7430
  );
7250
- assertArg(import_ts_utils_lib11.Utils.Is.isEnumValue(verticalPosition, VerticalPosition), "verticalPosition", verticalPosition);
7431
+ assertArg(import_ts_utils_lib13.Utils.Is.isEnumValue(verticalPosition, VerticalPosition), "verticalPosition", verticalPosition);
7251
7432
  this.doc.addStaffGroup(groupName, staffsTabsAndGroups, verticalPosition);
7252
7433
  return this;
7253
7434
  }
@@ -7265,13 +7446,13 @@ var DocumentBuilder = class {
7265
7446
  return this;
7266
7447
  }
7267
7448
  completeRests(voiceId) {
7268
- assertArg(import_ts_utils_lib11.Utils.Is.isUndefined(voiceId) || isVoiceId(voiceId), "voiceId", voiceId);
7449
+ assertArg(import_ts_utils_lib13.Utils.Is.isUndefined(voiceId) || isVoiceId(voiceId) || import_ts_utils_lib13.Utils.Is.isArray(voiceId) && voiceId.every((id) => isVoiceId(id)), "voiceId", voiceId);
7269
7450
  this.getMeasure().completeRests(voiceId);
7270
7451
  return this;
7271
7452
  }
7272
7453
  addScaleArpeggio(scale, bottomNote, numOctaves) {
7273
- assertArg(import_ts_utils_lib11.Utils.Is.isString(bottomNote), "bottomNote", bottomNote);
7274
- assertArg(import_ts_utils_lib11.Utils.Is.isIntegerGte(numOctaves, 1), "numOctaves", numOctaves);
7454
+ assertArg(import_ts_utils_lib13.Utils.Is.isNonEmptyString(bottomNote), "bottomNote", bottomNote);
7455
+ assertArg(import_ts_utils_lib13.Utils.Is.isIntegerGte(numOctaves, 1), "numOctaves", numOctaves);
7275
7456
  let ts = this.getMeasure().getTimeSignature();
7276
7457
  let notes = scale.getScaleNotes(bottomNote, numOctaves);
7277
7458
  for (let i = 0; i < notes.length; i++) {
@@ -7280,7 +7461,7 @@ var DocumentBuilder = class {
7280
7461
  }
7281
7462
  let note = notes[i];
7282
7463
  this.addNote(0, note, ts.beatLength);
7283
- this.addLabel(0 /* Note */, note.formatOmitOctave(import_theory13.SymbolSet.Unicode));
7464
+ this.addLabel("note" /* Note */, note.formatOmitOctave(import_theory13.SymbolSet.Unicode));
7284
7465
  }
7285
7466
  return this;
7286
7467
  }
@@ -7320,7 +7501,7 @@ var ScoreObjectEvent = class extends ScoreEvent {
7320
7501
 
7321
7502
  // src/score/pub/interface.ts
7322
7503
  var Audio2 = __toESM(require("@tspro/web-music-score/audio"));
7323
- var import_ts_utils_lib12 = require("@tspro/ts-utils-lib");
7504
+ var import_ts_utils_lib14 = require("@tspro/ts-utils-lib");
7324
7505
  var import_core19 = require("@tspro/web-music-score/core");
7325
7506
  function assertArg2(condition, argName, argValue) {
7326
7507
  if (!condition) {
@@ -7335,7 +7516,7 @@ function require_t(t, message) {
7335
7516
  }
7336
7517
  }
7337
7518
  function isVoiceId2(value) {
7338
- return import_ts_utils_lib12.Utils.Is.isNumber(value) && getVoiceIds().indexOf(value) >= 0;
7519
+ return import_ts_utils_lib14.Utils.Is.isNumber(value) && getVoiceIds().indexOf(value) >= 0;
7339
7520
  }
7340
7521
  function getNotationLine(line) {
7341
7522
  if (line instanceof ObjStaff || line instanceof ObjTab) {
@@ -7457,7 +7638,7 @@ var _MDocument = class _MDocument extends MusicInterface6 {
7457
7638
  return this.obj.getMeasures().map((m) => m.getMusicInterface());
7458
7639
  }
7459
7640
  play(fn) {
7460
- assertArg2(import_ts_utils_lib12.Utils.Is.isFunctionOrUndefined(fn), "playStateChangeListener", fn);
7641
+ assertArg2(import_ts_utils_lib14.Utils.Is.isFunctionOrUndefined(fn), "playStateChangeListener", fn);
7461
7642
  return new MPlayer(this, fn).play();
7462
7643
  }
7463
7644
  };
@@ -7477,7 +7658,7 @@ var _MEnding = class _MEnding extends MusicInterface6 {
7477
7658
  return this.obj.passages;
7478
7659
  }
7479
7660
  hasPassage(passage) {
7480
- assertArg2(import_ts_utils_lib12.Utils.Is.isIntegerGte(passage, 1), "passage", passage);
7661
+ assertArg2(import_ts_utils_lib14.Utils.Is.isIntegerGte(passage, 1), "passage", passage);
7481
7662
  return this.obj.hasPassage(passage);
7482
7663
  }
7483
7664
  };
@@ -7881,7 +8062,7 @@ var _MPlayer = class _MPlayer {
7881
8062
  constructor(doc, fn) {
7882
8063
  __publicField(this, "player");
7883
8064
  assertArg2(doc instanceof MDocument2, "doc", doc);
7884
- assertArg2(import_ts_utils_lib12.Utils.Is.isFunctionOrUndefined(fn), "playStateChangeListener", fn);
8065
+ assertArg2(import_ts_utils_lib14.Utils.Is.isFunctionOrUndefined(fn), "playStateChangeListener", fn);
7885
8066
  this.player = new Player();
7886
8067
  this.player.setDocument(doc.getMusicObject());
7887
8068
  this.player.setCursorPositionChangeListener((cursorRect) => doc.getMusicObject().updateCursorRect(cursorRect));
@@ -7916,17 +8097,17 @@ var MRenderer2 = class {
7916
8097
  this.renderer = new Renderer(this);
7917
8098
  }
7918
8099
  setDocument(doc) {
7919
- assertArg2(import_ts_utils_lib12.Utils.Is.isUndefined(doc) || doc instanceof MDocument2, "doc", doc);
8100
+ assertArg2(import_ts_utils_lib14.Utils.Is.isUndefined(doc) || doc instanceof MDocument2, "doc", doc);
7920
8101
  this.renderer.setDocument(doc);
7921
8102
  return this;
7922
8103
  }
7923
8104
  setCanvas(canvas) {
7924
- canvas = require_t(import_ts_utils_lib12.Utils.Dom.getCanvas(canvas), typeof canvas === "string" ? "Cannot set renderer canvas because invalid canvas id: " + canvas : "Cannot set renderer canvas because given canvas is undefined.");
8105
+ canvas = require_t(import_ts_utils_lib14.Utils.Dom.getCanvas(canvas), typeof canvas === "string" ? "Cannot set renderer canvas because invalid canvas id: " + canvas : "Cannot set renderer canvas because given canvas is undefined.");
7925
8106
  this.renderer.setCanvas(canvas);
7926
8107
  return this;
7927
8108
  }
7928
8109
  setScoreEventListener(fn) {
7929
- assertArg2(import_ts_utils_lib12.Utils.Is.isFunctionOrUndefined(fn), "scoreEventListener", fn);
8110
+ assertArg2(import_ts_utils_lib14.Utils.Is.isFunctionOrUndefined(fn), "scoreEventListener", fn);
7930
8111
  this.renderer.setScoreEventListener(fn);
7931
8112
  }
7932
8113
  hilightObject(obj) {
@@ -7981,7 +8162,7 @@ var _MPlaybackButtons = class _MPlaybackButtons {
7981
8162
  this.updateButtons();
7982
8163
  }
7983
8164
  setDocument(doc) {
7984
- assertArg2(import_ts_utils_lib12.Utils.Is.isUndefined(doc) || doc instanceof MDocument2, "doc", doc);
8165
+ assertArg2(import_ts_utils_lib14.Utils.Is.isUndefined(doc) || doc instanceof MDocument2, "doc", doc);
7985
8166
  this.onStop();
7986
8167
  if (doc) {
7987
8168
  this.player = new MPlayer(doc, (playState) => {
@@ -8016,9 +8197,9 @@ var _MPlaybackButtons = class _MPlaybackButtons {
8016
8197
  }
8017
8198
  }
8018
8199
  setPlayButton(btn, btnLabel) {
8019
- assertArg2(import_ts_utils_lib12.Utils.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
8200
+ assertArg2(import_ts_utils_lib14.Utils.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
8020
8201
  _MPlaybackButtons.removeOnClickListeners(this.playButton, this.onPlay);
8021
- this.playButton = require_t(import_ts_utils_lib12.Utils.Dom.getButton(btn), "Play button required!");
8202
+ this.playButton = require_t(import_ts_utils_lib14.Utils.Dom.getButton(btn), "Play button required!");
8022
8203
  this.playLabel = btnLabel != null ? btnLabel : "Play";
8023
8204
  _MPlaybackButtons.removeOnClickListeners(this.playButton, "all");
8024
8205
  _MPlaybackButtons.addOnClickListener(this.playButton, this.onPlay);
@@ -8026,9 +8207,9 @@ var _MPlaybackButtons = class _MPlaybackButtons {
8026
8207
  return this;
8027
8208
  }
8028
8209
  setStopButton(btn, btnLabel) {
8029
- assertArg2(import_ts_utils_lib12.Utils.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
8210
+ assertArg2(import_ts_utils_lib14.Utils.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
8030
8211
  _MPlaybackButtons.removeOnClickListeners(this.stopButton, this.onStop);
8031
- this.stopButton = require_t(import_ts_utils_lib12.Utils.Dom.getButton(btn), "Stop button required!");
8212
+ this.stopButton = require_t(import_ts_utils_lib14.Utils.Dom.getButton(btn), "Stop button required!");
8032
8213
  this.stopLabel = btnLabel != null ? btnLabel : "Stop";
8033
8214
  _MPlaybackButtons.removeOnClickListeners(this.stopButton, "all");
8034
8215
  _MPlaybackButtons.addOnClickListener(this.stopButton, this.onStop);
@@ -8036,10 +8217,10 @@ var _MPlaybackButtons = class _MPlaybackButtons {
8036
8217
  return this;
8037
8218
  }
8038
8219
  setPlayStopButton(btn, playLabel, stopLabel) {
8039
- assertArg2(import_ts_utils_lib12.Utils.Is.isStringOrUndefined(playLabel), "playLabel", playLabel);
8040
- assertArg2(import_ts_utils_lib12.Utils.Is.isStringOrUndefined(stopLabel), "stopLabel", stopLabel);
8220
+ assertArg2(import_ts_utils_lib14.Utils.Is.isStringOrUndefined(playLabel), "playLabel", playLabel);
8221
+ assertArg2(import_ts_utils_lib14.Utils.Is.isStringOrUndefined(stopLabel), "stopLabel", stopLabel);
8041
8222
  _MPlaybackButtons.removeOnClickListeners(this.playStopButton, this.onPlayStop);
8042
- this.playStopButton = require_t(import_ts_utils_lib12.Utils.Dom.getButton(btn), "Play/stop button required!");
8223
+ this.playStopButton = require_t(import_ts_utils_lib14.Utils.Dom.getButton(btn), "Play/stop button required!");
8043
8224
  this.playLabel = playLabel != null ? playLabel : "Play";
8044
8225
  this.stopLabel = stopLabel != null ? stopLabel : "Stop";
8045
8226
  _MPlaybackButtons.removeOnClickListeners(this.playStopButton, "all");
@@ -8048,9 +8229,9 @@ var _MPlaybackButtons = class _MPlaybackButtons {
8048
8229
  return this;
8049
8230
  }
8050
8231
  setPauseButton(btn, btnLabel) {
8051
- assertArg2(import_ts_utils_lib12.Utils.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
8232
+ assertArg2(import_ts_utils_lib14.Utils.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
8052
8233
  _MPlaybackButtons.removeOnClickListeners(this.pauseButton, this.onPause);
8053
- this.pauseButton = require_t(import_ts_utils_lib12.Utils.Dom.getButton(btn), "Pause button required!");
8234
+ this.pauseButton = require_t(import_ts_utils_lib14.Utils.Dom.getButton(btn), "Pause button required!");
8054
8235
  this.pauseLabel = btnLabel != null ? btnLabel : "Pause";
8055
8236
  _MPlaybackButtons.removeOnClickListeners(this.pauseButton, "all");
8056
8237
  _MPlaybackButtons.addOnClickListener(this.pauseButton, this.onPause);
@@ -8072,7 +8253,7 @@ var _MPlaybackButtons = class _MPlaybackButtons {
8072
8253
  }
8073
8254
  }
8074
8255
  static addOnClickListener(btn, onClick) {
8075
- assertArg2(import_ts_utils_lib12.Utils.Is.isFunction(onClick), "onClick", onClick);
8256
+ assertArg2(import_ts_utils_lib14.Utils.Is.isFunction(onClick), "onClick", onClick);
8076
8257
  btn.addEventListener("click", onClick);
8077
8258
  let clickListeners = this.savedOnClickListeners.get(btn) || [];
8078
8259
  this.savedOnClickListeners.set(btn, [...clickListeners, onClick]);