@tspro/web-music-score 5.0.0 → 5.2.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 (43) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +16 -13
  3. package/dist/audio/index.d.mts +15 -2
  4. package/dist/audio/index.d.ts +16 -3
  5. package/dist/audio/index.js +37 -78
  6. package/dist/audio/index.mjs +34 -68
  7. package/dist/audio-cg/index.d.mts +6 -1
  8. package/dist/audio-cg/index.d.ts +6 -1
  9. package/dist/audio-cg/index.js +1 -1
  10. package/dist/audio-cg/index.mjs +3 -3
  11. package/dist/audio-synth/index.d.mts +15 -0
  12. package/dist/audio-synth/index.d.ts +15 -0
  13. package/dist/audio-synth/index.js +95 -0
  14. package/dist/audio-synth/index.mjs +58 -0
  15. package/dist/{chunk-AAL3CMRO.mjs → chunk-6S5BDSCM.mjs} +2 -2
  16. package/dist/{chunk-J3KU3U4W.mjs → chunk-LC5JMIVF.mjs} +2 -2
  17. package/dist/{chunk-EYFT3RWB.mjs → chunk-XUGM7SCC.mjs} +5 -6
  18. package/dist/core/index.js +2 -2
  19. package/dist/core/index.mjs +3 -3
  20. package/dist/{guitar-CaZJDA05.d.ts → guitar-BsSayRsH.d.ts} +1 -1
  21. package/dist/iife/audio-cg.global.js +9 -2
  22. package/dist/iife/index.global.js +11 -11
  23. package/dist/{music-objects-3Hxlkxy6.d.mts → music-objects-CB05XryE.d.mts} +121 -45
  24. package/dist/{music-objects-CI7IjsjE.d.ts → music-objects-CwPOlqFi.d.ts} +123 -47
  25. package/dist/{note-eA2xPPiG.d.ts → note-CgCIBwvR.d.ts} +1 -1
  26. package/dist/pieces/index.d.mts +1 -1
  27. package/dist/pieces/index.d.ts +3 -3
  28. package/dist/pieces/index.js +1 -1
  29. package/dist/pieces/index.mjs +2 -2
  30. package/dist/react-ui/index.d.mts +34 -15
  31. package/dist/react-ui/index.d.ts +38 -19
  32. package/dist/react-ui/index.js +41 -32
  33. package/dist/react-ui/index.mjs +42 -33
  34. package/dist/{scale-DGx3tJH4.d.ts → scale-CBW4eTz7.d.ts} +2 -2
  35. package/dist/score/index.d.mts +2 -2
  36. package/dist/score/index.d.ts +5 -5
  37. package/dist/score/index.js +1951 -1514
  38. package/dist/score/index.mjs +1664 -1226
  39. package/dist/{tempo-GrstpD9G.d.ts → tempo-DMt3iwz9.d.ts} +1 -1
  40. package/dist/theory/index.d.ts +6 -6
  41. package/dist/theory/index.js +3 -4
  42. package/dist/theory/index.mjs +3 -3
  43. package/package.json +12 -2
@@ -1,10 +1,12 @@
1
- /* WebMusicScore v5.0.0 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
1
+ /* WebMusicScore v5.2.0 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
2
2
  import {
3
- RhythmProps
4
- } from "../chunk-EYFT3RWB.mjs";
3
+ NoteLengthProps,
4
+ RhythmProps,
5
+ validateNoteLength
6
+ } from "../chunk-XUGM7SCC.mjs";
5
7
  import {
6
8
  __publicField
7
- } from "../chunk-J3KU3U4W.mjs";
9
+ } from "../chunk-LC5JMIVF.mjs";
8
10
 
9
11
  // src/score/pub/div-rect.ts
10
12
  import { Utils } from "@tspro/ts-utils-lib";
@@ -286,7 +288,7 @@ var DivRect = class _DivRect {
286
288
  };
287
289
 
288
290
  // src/score/pub/document-builder.ts
289
- import { Utils as Utils14 } from "@tspro/ts-utils-lib";
291
+ import { Utils as Utils15 } from "@tspro/ts-utils-lib";
290
292
 
291
293
  // src/score/pub/types.ts
292
294
  var StaffPreset = /* @__PURE__ */ ((StaffPreset3) => {
@@ -298,10 +300,10 @@ var StaffPreset = /* @__PURE__ */ ((StaffPreset3) => {
298
300
  StaffPreset3["GuitarCombined"] = "guitarCombined";
299
301
  return StaffPreset3;
300
302
  })(StaffPreset || {});
301
- var Clef = /* @__PURE__ */ ((Clef2) => {
302
- Clef2["G"] = "G";
303
- Clef2["F"] = "F";
304
- return Clef2;
303
+ var Clef = /* @__PURE__ */ ((Clef4) => {
304
+ Clef4["G"] = "G";
305
+ Clef4["F"] = "F";
306
+ return Clef4;
305
307
  })(Clef || {});
306
308
  function getVoiceIds() {
307
309
  return [0, 1, 2, 3];
@@ -910,15 +912,140 @@ var Renderer = class {
910
912
  }
911
913
  }
912
914
  }
915
+ getRestRect(restSize) {
916
+ let { unitSize } = this;
917
+ let { flagCount } = NoteLengthProps.get(validateNoteLength(restSize + "n"));
918
+ let leftw = 0;
919
+ let rightw = 0;
920
+ let toph = 0;
921
+ let bottomh = 0;
922
+ if (NoteLengthProps.equals(restSize, "1n" /* Whole */)) {
923
+ leftw = unitSize;
924
+ rightw = unitSize;
925
+ toph = 0;
926
+ bottomh = unitSize;
927
+ } else if (NoteLengthProps.equals(restSize, "2n" /* Half */)) {
928
+ leftw = unitSize;
929
+ rightw = unitSize;
930
+ toph = unitSize;
931
+ bottomh = 0;
932
+ } else if (NoteLengthProps.equals(restSize, "4n" /* Quarter */)) {
933
+ leftw = unitSize * 1;
934
+ rightw = unitSize * 1;
935
+ toph = unitSize * 3.2;
936
+ bottomh = unitSize * 3;
937
+ } else {
938
+ let adj = 1 - flagCount % 2;
939
+ leftw = unitSize * (1 + flagCount * 0.25);
940
+ rightw = unitSize * (1 + flagCount * 0.125);
941
+ toph = unitSize * (0.5 + flagCount - adj);
942
+ bottomh = unitSize * (1 + flagCount + adj);
943
+ }
944
+ return new DivRect(-leftw, 0, rightw, -toph, 0, bottomh);
945
+ }
946
+ drawRest(restSize, x, y, color) {
947
+ let ctx = this.getCanvasContext();
948
+ if (!ctx) {
949
+ return;
950
+ }
951
+ let { unitSize, lineWidth } = this;
952
+ let { flagCount } = NoteLengthProps.get(validateNoteLength(restSize + "n"));
953
+ ctx.strokeStyle = ctx.fillStyle = color;
954
+ ctx.lineWidth = lineWidth;
955
+ if (NoteLengthProps.equals(restSize, "1n" /* Whole */)) {
956
+ ctx.fillRect(x - unitSize, y, unitSize * 2, unitSize);
957
+ } else if (NoteLengthProps.equals(restSize, "2n" /* Half */)) {
958
+ ctx.fillRect(x - unitSize, y - unitSize, unitSize * 2, unitSize);
959
+ } else if (NoteLengthProps.equals(restSize, "4n" /* Quarter */)) {
960
+ ctx.beginPath();
961
+ ctx.moveTo(x - unitSize * 0.6, y - unitSize * 3.2);
962
+ ctx.lineTo(x + unitSize * 0.7, y - unitSize * 1.5);
963
+ ctx.quadraticCurveTo(
964
+ x - unitSize * 0.8,
965
+ y - unitSize * 0.5,
966
+ x + unitSize * 1,
967
+ y + unitSize * 1.5
968
+ );
969
+ ctx.lineTo(x - unitSize * 1, y - unitSize * 0.75);
970
+ ctx.quadraticCurveTo(
971
+ x + unitSize * 0.2,
972
+ y - unitSize * 1.5,
973
+ x - unitSize * 0.6,
974
+ y - unitSize * 3.2
975
+ );
976
+ ctx.moveTo(x + unitSize * 1, y + unitSize * 1.5);
977
+ ctx.quadraticCurveTo(
978
+ x - unitSize * 0.8,
979
+ y + unitSize * 1,
980
+ x - unitSize * 0.2,
981
+ y + unitSize * 2.8
982
+ );
983
+ ctx.bezierCurveTo(
984
+ x - unitSize * 1.8,
985
+ y + unitSize * 1.5,
986
+ x - unitSize * 0.6,
987
+ y - unitSize * 0.2,
988
+ x + unitSize * 0.9,
989
+ y + unitSize * 1.5
990
+ );
991
+ ctx.fill();
992
+ ctx.stroke();
993
+ } else if (flagCount > 0) {
994
+ let adj = 1 - flagCount % 2;
995
+ let fx = (p) => x + (-p * 0.25 + 0.5) * unitSize;
996
+ let fy = (p) => y + (p + adj) * unitSize;
997
+ ctx.beginPath();
998
+ ctx.moveTo(fx(1 + flagCount), fy(1 + flagCount));
999
+ ctx.lineTo(fx(-0.5 - flagCount), fy(-0.5 - flagCount));
1000
+ ctx.stroke();
1001
+ for (let i = 0; i < flagCount; i++) {
1002
+ let t = flagCount - i * 2;
1003
+ ctx.beginPath();
1004
+ ctx.moveTo(fx(t - 2.5), fy(t - 2.5));
1005
+ ctx.quadraticCurveTo(
1006
+ fx(t - 0.5) + unitSize * 0.25,
1007
+ fy(t - 1.5),
1008
+ fx(t - 1.5) - unitSize * 1.5,
1009
+ fy(t - 1.5)
1010
+ );
1011
+ ctx.stroke();
1012
+ ctx.beginPath();
1013
+ ctx.arc(fx(t - 2) - unitSize * 1.5, fy(t - 2), unitSize * 0.5, 0, Math.PI * 2);
1014
+ ctx.fill();
1015
+ }
1016
+ }
1017
+ }
1018
+ drawFlag(rect, dir) {
1019
+ let ctx = this.getCanvasContext();
1020
+ if (!ctx) {
1021
+ return;
1022
+ }
1023
+ let left = rect.left;
1024
+ let right = rect.right;
1025
+ let width = right - left;
1026
+ let top = dir === "up" ? rect.top : rect.bottom;
1027
+ let bottom = dir === "up" ? rect.bottom : rect.top;
1028
+ ctx.beginPath();
1029
+ ctx.moveTo(left, top);
1030
+ ctx.bezierCurveTo(
1031
+ left,
1032
+ top * 0.75 + bottom * 0.25,
1033
+ left + width * 1.5,
1034
+ top * 0.5 + bottom * 0.5,
1035
+ left + width * 0.5,
1036
+ bottom
1037
+ );
1038
+ ctx.stroke();
1039
+ }
913
1040
  };
914
1041
 
915
1042
  // src/score/engine/obj-staff-and-tab.ts
916
1043
  import { MusicError as MusicError15, MusicErrorType as MusicErrorType15 } from "@tspro/web-music-score/core";
917
- import { Utils as Utils12 } from "@tspro/ts-utils-lib";
1044
+ import { Utils as Utils13 } from "@tspro/ts-utils-lib";
918
1045
 
919
1046
  // src/score/engine/obj-measure.ts
920
- import { Utils as Utils11 } from "@tspro/ts-utils-lib";
921
- import { getScale, Scale, validateScaleType, Note as Note7, RhythmProps as RhythmProps5, KeySignature as KeySignature2, getDefaultKeySignature, PitchNotation, SymbolSet, validateNoteLength as validateNoteLength2, NoteLengthProps as NoteLengthProps4 } from "@tspro/web-music-score/theory";
1047
+ import { Utils as Utils12 } from "@tspro/ts-utils-lib";
1048
+ import { getScale, Scale, validateScaleType, Note as Note7, RhythmProps as RhythmProps5, KeySignature as KeySignature2, getDefaultKeySignature, PitchNotation, SymbolSet, validateNoteLength as validateNoteLength3, NoteLengthProps as NoteLengthProps5 } from "@tspro/web-music-score/theory";
922
1049
  import { getDefaultTempo, getDefaultTimeSignature } from "@tspro/web-music-score/theory";
923
1050
 
924
1051
  // src/score/engine/acc-state.ts
@@ -1241,7 +1368,7 @@ var ObjText = class extends MusicObject {
1241
1368
 
1242
1369
  // src/score/engine/obj-signature.ts
1243
1370
  import { MusicError as MusicError4, MusicErrorType as MusicErrorType4 } from "@tspro/web-music-score/core";
1244
- var ObjSignature = class extends MusicObject {
1371
+ var ObjStaffSignature = class extends MusicObject {
1245
1372
  constructor(measure, staff) {
1246
1373
  super(measure);
1247
1374
  this.measure = measure;
@@ -1255,7 +1382,7 @@ var ObjSignature = class extends MusicObject {
1255
1382
  __publicField(this, "beatSizeText");
1256
1383
  __publicField(this, "tempoText");
1257
1384
  __publicField(this, "mi");
1258
- this.mi = new MSignature(this);
1385
+ this.mi = new MStaffSignature(this);
1259
1386
  }
1260
1387
  getMusicInterface() {
1261
1388
  return this.mi;
@@ -1454,66 +1581,169 @@ var ObjSignature = class extends MusicObject {
1454
1581
  }
1455
1582
  x = right;
1456
1583
  if (this.tempoText) {
1584
+ let tempoBottom = Math.min(
1585
+ this.clefImage ? this.clefImage.getRect().top : staff.getTopLineY(),
1586
+ ...this.ksNeutralizeAccidentals.map((o) => o.getRect().top),
1587
+ ...this.ksNewAccidentals.map((o) => o.getRect().top)
1588
+ );
1457
1589
  this.tempoText.layout(renderer);
1458
- this.tempoText.offset(x, Math.min(this.rect.top, staff.getTopLineY()));
1590
+ this.tempoText.offset(x, tempoBottom);
1459
1591
  this.rect.expandInPlace(this.tempoText.getRect());
1460
1592
  }
1461
1593
  this.rect.right += paddingX;
1462
1594
  }
1463
1595
  offset(dx, dy) {
1464
- if (this.clefImage) {
1465
- this.clefImage.offset(dx, dy);
1596
+ var _a, _b, _c, _d, _e, _f;
1597
+ (_a = this.clefImage) == null ? void 0 : _a.offset(dx, dy);
1598
+ (_b = this.eightBelowClef) == null ? void 0 : _b.offset(dx, dy);
1599
+ (_c = this.measureNumber) == null ? void 0 : _c.offset(dx, dy);
1600
+ this.ksNeutralizeAccidentals.forEach((acc) => acc.offset(dx, dy));
1601
+ this.ksNewAccidentals.forEach((acc) => acc.offset(dx, dy));
1602
+ (_d = this.beatCountText) == null ? void 0 : _d.offset(dx, dy);
1603
+ (_e = this.beatSizeText) == null ? void 0 : _e.offset(dx, dy);
1604
+ (_f = this.tempoText) == null ? void 0 : _f.offset(dx, dy);
1605
+ this.rect.offsetInPlace(dx, dy);
1606
+ }
1607
+ draw(renderer) {
1608
+ var _a, _b, _c, _d, _e, _f;
1609
+ (_a = this.clefImage) == null ? void 0 : _a.draw(renderer);
1610
+ (_b = this.eightBelowClef) == null ? void 0 : _b.draw(renderer);
1611
+ (_c = this.measureNumber) == null ? void 0 : _c.draw(renderer);
1612
+ this.ksNeutralizeAccidentals.forEach((acc) => acc.draw(renderer));
1613
+ this.ksNewAccidentals.forEach((acc) => acc.draw(renderer));
1614
+ (_d = this.beatCountText) == null ? void 0 : _d.draw(renderer);
1615
+ (_e = this.beatSizeText) == null ? void 0 : _e.draw(renderer);
1616
+ (_f = this.tempoText) == null ? void 0 : _f.draw(renderer);
1617
+ }
1618
+ };
1619
+ var ObjTabSignature = class extends MusicObject {
1620
+ constructor(measure, tab) {
1621
+ super(measure);
1622
+ this.measure = measure;
1623
+ this.tab = tab;
1624
+ __publicField(this, "measureNumber");
1625
+ __publicField(this, "beatCountText");
1626
+ __publicField(this, "beatSizeText");
1627
+ __publicField(this, "tempoText");
1628
+ __publicField(this, "mi");
1629
+ this.mi = new MTabSignature(this);
1630
+ }
1631
+ getMusicInterface() {
1632
+ return this.mi;
1633
+ }
1634
+ updateMeasureNumber(showMeasureNumber) {
1635
+ if (showMeasureNumber) {
1636
+ let text = this.measure.getMeasureNumber().toString();
1637
+ this.measureNumber = new ObjText(this, text, 0, 1);
1638
+ } else {
1639
+ this.measureNumber = void 0;
1466
1640
  }
1467
- if (this.eightBelowClef) {
1468
- this.eightBelowClef.offset(dx, dy);
1641
+ }
1642
+ updateTimeSignature(showTimeSignature) {
1643
+ if (showTimeSignature) {
1644
+ let timeSignature = this.measure.getTimeSignature();
1645
+ let beatCount = timeSignature.beatCount.toString();
1646
+ this.beatCountText = new ObjText(this, { text: beatCount, scale: 1.4 }, 0.5, 0.5);
1647
+ let beatSize = timeSignature.beatSize.toString();
1648
+ this.beatSizeText = new ObjText(this, { text: beatSize, scale: 1.4 }, 0.5, 0.5);
1649
+ } else {
1650
+ this.beatCountText = this.beatSizeText = void 0;
1469
1651
  }
1470
- if (this.measureNumber) {
1471
- this.measureNumber.offset(dx, dy);
1652
+ }
1653
+ updateTempo(showTempo) {
1654
+ if (showTempo) {
1655
+ let tempoStr = getTempoString(this.measure.getTempo());
1656
+ this.tempoText = new ObjText(this, tempoStr, 0, 1);
1657
+ } else {
1658
+ this.tempoText = void 0;
1659
+ }
1660
+ }
1661
+ pick(x, y) {
1662
+ if (!this.rect.contains(x, y)) {
1663
+ return [];
1472
1664
  }
1473
- this.ksNeutralizeAccidentals.forEach((acc) => acc.offset(dx, dy));
1474
- this.ksNewAccidentals.forEach((acc) => acc.offset(dx, dy));
1475
1665
  if (this.beatCountText) {
1476
- this.beatCountText.offset(dx, dy);
1666
+ let arr = this.beatCountText.pick(x, y);
1667
+ if (arr.length > 0) {
1668
+ return [this, ...arr];
1669
+ }
1477
1670
  }
1478
1671
  if (this.beatSizeText) {
1479
- this.beatSizeText.offset(dx, dy);
1672
+ let arr = this.beatSizeText.pick(x, y);
1673
+ if (arr.length > 0) {
1674
+ return [this, ...arr];
1675
+ }
1480
1676
  }
1481
1677
  if (this.tempoText) {
1482
- this.tempoText.offset(dx, dy);
1483
- }
1484
- this.rect.offsetInPlace(dx, dy);
1485
- }
1486
- draw(renderer) {
1487
- if (this.clefImage) {
1488
- this.clefImage.draw(renderer);
1678
+ let arr = this.tempoText.pick(x, y);
1679
+ if (arr.length > 0) {
1680
+ return [this, ...arr];
1681
+ }
1489
1682
  }
1490
- if (this.eightBelowClef) {
1491
- this.eightBelowClef.draw(renderer);
1683
+ if (this.measureNumber) {
1684
+ let arr = this.measureNumber.pick(x, y);
1685
+ if (arr.length > 0) {
1686
+ return [this, ...arr];
1687
+ }
1492
1688
  }
1689
+ return [this];
1690
+ }
1691
+ layout(renderer) {
1692
+ var _a, _b, _c, _d, _e, _f;
1693
+ let { unitSize } = renderer;
1694
+ let { tab } = this;
1695
+ let paddingX = unitSize;
1696
+ let x = 0;
1697
+ let topLineY = tab.getTopLineY();
1698
+ this.rect = new DivRect();
1493
1699
  if (this.measureNumber) {
1494
- this.measureNumber.draw(renderer);
1700
+ this.measureNumber.layout(renderer);
1701
+ this.measureNumber.offset(0, topLineY);
1702
+ this.rect.expandInPlace(this.measureNumber.getRect());
1703
+ x = Math.max(x, this.rect.right);
1495
1704
  }
1496
- this.ksNeutralizeAccidentals.forEach((acc) => acc.draw(renderer));
1497
- this.ksNewAccidentals.forEach((acc) => acc.draw(renderer));
1705
+ (_a = this.beatCountText) == null ? void 0 : _a.layout(renderer);
1706
+ (_b = this.beatSizeText) == null ? void 0 : _b.layout(renderer);
1707
+ let tsWidth = Math.max((_d = (_c = this.beatCountText) == null ? void 0 : _c.getRect().width) != null ? _d : 0, (_f = (_e = this.beatSizeText) == null ? void 0 : _e.getRect().width) != null ? _f : 0);
1498
1708
  if (this.beatCountText) {
1499
- this.beatCountText.draw(renderer);
1709
+ this.beatCountText.offset(0 + tsWidth / 2 + paddingX, tab.getRect().centerY - this.beatCountText.getRect().bottomh);
1710
+ this.rect.expandInPlace(this.beatCountText.getRect());
1500
1711
  }
1501
1712
  if (this.beatSizeText) {
1502
- this.beatSizeText.draw(renderer);
1713
+ this.beatSizeText.offset(0 + tsWidth / 2 + paddingX, tab.getRect().centerY + this.beatSizeText.getRect().toph);
1714
+ this.rect.expandInPlace(this.beatSizeText.getRect());
1503
1715
  }
1504
1716
  if (this.tempoText) {
1505
- this.tempoText.draw(renderer);
1717
+ this.tempoText.layout(renderer);
1718
+ this.tempoText.offset(x + unitSize * 2, topLineY);
1719
+ this.rect.expandInPlace(this.tempoText.getRect());
1506
1720
  }
1721
+ this.rect.right += paddingX;
1722
+ }
1723
+ offset(dx, dy) {
1724
+ var _a, _b, _c, _d;
1725
+ (_a = this.measureNumber) == null ? void 0 : _a.offset(dx, dy);
1726
+ (_b = this.beatCountText) == null ? void 0 : _b.offset(dx, dy);
1727
+ (_c = this.beatSizeText) == null ? void 0 : _c.offset(dx, dy);
1728
+ (_d = this.tempoText) == null ? void 0 : _d.offset(dx, dy);
1729
+ this.rect.offsetInPlace(dx, dy);
1730
+ }
1731
+ draw(renderer) {
1732
+ var _a, _b, _c, _d;
1733
+ (_a = this.measureNumber) == null ? void 0 : _a.draw(renderer);
1734
+ (_b = this.beatCountText) == null ? void 0 : _b.draw(renderer);
1735
+ (_c = this.beatSizeText) == null ? void 0 : _c.draw(renderer);
1736
+ (_d = this.tempoText) == null ? void 0 : _d.draw(renderer);
1507
1737
  }
1508
1738
  };
1509
1739
 
1510
1740
  // src/score/engine/player.ts
1511
- import { Utils as Utils7 } from "@tspro/ts-utils-lib";
1741
+ import { Utils as Utils6 } from "@tspro/ts-utils-lib";
1512
1742
  import { NoteLength as NoteLength6, RhythmProps as RhythmProps4, alterTempoSpeed } from "@tspro/web-music-score/theory";
1513
1743
  import * as Audio from "@tspro/web-music-score/audio";
1514
1744
 
1515
1745
  // src/score/engine/obj-rhythm-column.ts
1516
- import { Note as Note5, validateNoteLength } from "@tspro/web-music-score/theory";
1746
+ import { Note as Note5, validateNoteLength as validateNoteLength2 } from "@tspro/web-music-score/theory";
1517
1747
 
1518
1748
  // src/score/engine/obj-arpeggio.ts
1519
1749
  var ObjArpeggio = class extends MusicObject {
@@ -1586,7 +1816,7 @@ var ObjArpeggio = class extends MusicObject {
1586
1816
  };
1587
1817
 
1588
1818
  // src/score/engine/obj-rest.ts
1589
- import { Note as Note3, NoteLength, NoteLengthProps, RhythmProps as RhythmProps2, Tuplet } from "@tspro/web-music-score/theory";
1819
+ import { Note as Note3, NoteLengthProps as NoteLengthProps2, RhythmProps as RhythmProps2, Tuplet } from "@tspro/web-music-score/theory";
1590
1820
  import { MusicError as MusicError5, MusicErrorType as MusicErrorType5 } from "@tspro/web-music-score/core";
1591
1821
  function getDiatonicIdFromStaffPos(staffPos) {
1592
1822
  if (typeof staffPos === "number") {
@@ -1661,7 +1891,7 @@ var ObjRest = class extends MusicObject {
1661
1891
  }
1662
1892
  this.color = (_a = options == null ? void 0 : options.color) != null ? _a : "black";
1663
1893
  this.hide = (_b = options == null ? void 0 : options.hide) != null ? _b : false;
1664
- this.oldStyleTriplet = tupletRatio === void 0 && ((options == null ? void 0 : options.triplet) === true || NoteLengthProps.get(noteLength).isTriplet);
1894
+ this.oldStyleTriplet = tupletRatio === void 0 && ((options == null ? void 0 : options.triplet) === true || NoteLengthProps2.get(noteLength).isTriplet);
1665
1895
  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;
1666
1896
  this.rhythmProps = RhythmProps2.get(noteLength, dotCount, (tupletRatio != null ? tupletRatio : this.oldStyleTriplet) ? Tuplet.Triplet : void 0);
1667
1897
  this.mi = new MRest(this);
@@ -1723,6 +1953,9 @@ var ObjRest = class extends MusicObject {
1723
1953
  return { staff, x, y, stemHeight };
1724
1954
  });
1725
1955
  }
1956
+ hasTuplet() {
1957
+ return this.rhythmProps.tupletRatio !== void 0;
1958
+ }
1726
1959
  isEmpty() {
1727
1960
  return this.staffObjects.length === 0;
1728
1961
  }
@@ -1759,42 +1992,16 @@ var ObjRest = class extends MusicObject {
1759
1992
  }
1760
1993
  let { unitSize } = renderer;
1761
1994
  let { ownDiatonicId } = this;
1762
- let { noteSize, dotCount, flagCount } = this.rhythmProps;
1763
- let leftw = 0;
1764
- let rightw = 0;
1765
- let toph = 0;
1766
- let bottomh = 0;
1767
- if (NoteLengthProps.equals(noteSize, NoteLength.Whole)) {
1768
- leftw = unitSize;
1769
- rightw = unitSize;
1770
- toph = 0;
1771
- bottomh = unitSize;
1772
- } else if (NoteLengthProps.equals(noteSize, NoteLength.Half)) {
1773
- leftw = unitSize;
1774
- rightw = unitSize;
1775
- toph = unitSize;
1776
- bottomh = 0;
1777
- } else if (NoteLengthProps.equals(noteSize, NoteLength.Quarter)) {
1778
- leftw = unitSize * 1;
1779
- rightw = unitSize * 1;
1780
- toph = unitSize * 3.2;
1781
- bottomh = unitSize * 3;
1782
- } else {
1783
- let adj = 1 - flagCount % 2;
1784
- leftw = unitSize * (1 + flagCount * 0.25);
1785
- rightw = unitSize * (1 + flagCount * 0.125);
1786
- toph = unitSize * (0.5 + flagCount - adj);
1787
- bottomh = unitSize * (1 + flagCount + adj);
1788
- }
1995
+ let { noteSize, dotCount } = this.rhythmProps;
1789
1996
  this.row.getStaves().forEach((staff) => {
1790
1997
  if (!staff.containsDiatonicId(ownDiatonicId) || !staff.containsVoiceId(this.voiceId)) {
1791
1998
  return;
1792
1999
  }
1793
2000
  let obj = new ObjStaffRest(staff, this);
1794
- obj.restRect = new DivRect(-leftw, 0, rightw, -toph, 0, bottomh);
2001
+ obj.restRect = renderer.getRestRect(noteSize);
1795
2002
  for (let i = 0; i < dotCount; i++) {
1796
2003
  let dotWidth = DocumentSettings.DotSize * unitSize;
1797
- let dotX = rightw + (DocumentSettings.RestDotSpace + DocumentSettings.DotSize * unitSize) + i * DocumentSettings.DotSize * unitSize * 1.5;
2004
+ let dotX = obj.restRect.rightw + (DocumentSettings.RestDotSpace + DocumentSettings.DotSize * unitSize) + i * DocumentSettings.DotSize * unitSize * 1.5;
1798
2005
  let dotY = this.getRestDotVerticalDisplacement(noteSize) * unitSize;
1799
2006
  obj.dotRects.push(DivRect.createCentered(dotX, dotY, dotWidth, dotWidth));
1800
2007
  }
@@ -1824,77 +2031,16 @@ var ObjRest = class extends MusicObject {
1824
2031
  return;
1825
2032
  }
1826
2033
  renderer.drawDebugRect(this.getRect());
1827
- let { unitSize, lineWidth } = renderer;
2034
+ let { lineWidth } = renderer;
1828
2035
  let { color } = this;
1829
- let { noteSize, flagCount } = this.rhythmProps;
2036
+ let { noteSize } = this.rhythmProps;
1830
2037
  ctx.strokeStyle = ctx.fillStyle = color;
1831
2038
  ctx.lineWidth = lineWidth;
1832
2039
  this.staffObjects.forEach((obj) => {
1833
2040
  let { dotRects, restRect } = obj;
1834
2041
  let x = restRect.centerX;
1835
2042
  let y = restRect.centerY;
1836
- if (NoteLengthProps.equals(noteSize, NoteLength.Whole)) {
1837
- ctx.fillRect(x - unitSize, y, unitSize * 2, unitSize);
1838
- } else if (NoteLengthProps.equals(noteSize, NoteLength.Half)) {
1839
- ctx.fillRect(x - unitSize, y - unitSize, unitSize * 2, unitSize);
1840
- } else if (NoteLengthProps.equals(noteSize, NoteLength.Quarter)) {
1841
- ctx.beginPath();
1842
- ctx.moveTo(x - unitSize * 0.6, y - unitSize * 3.2);
1843
- ctx.lineTo(x + unitSize * 0.7, y - unitSize * 1.5);
1844
- ctx.quadraticCurveTo(
1845
- x - unitSize * 0.8,
1846
- y - unitSize * 0.5,
1847
- x + unitSize * 1,
1848
- y + unitSize * 1.5
1849
- );
1850
- ctx.lineTo(x - unitSize * 1, y - unitSize * 0.75);
1851
- ctx.quadraticCurveTo(
1852
- x + unitSize * 0.2,
1853
- y - unitSize * 1.5,
1854
- x - unitSize * 0.6,
1855
- y - unitSize * 3.2
1856
- );
1857
- ctx.moveTo(x + unitSize * 1, y + unitSize * 1.5);
1858
- ctx.quadraticCurveTo(
1859
- x - unitSize * 0.8,
1860
- y + unitSize * 1,
1861
- x - unitSize * 0.2,
1862
- y + unitSize * 2.8
1863
- );
1864
- ctx.bezierCurveTo(
1865
- x - unitSize * 1.8,
1866
- y + unitSize * 1.5,
1867
- x - unitSize * 0.6,
1868
- y - unitSize * 0.2,
1869
- x + unitSize * 0.9,
1870
- y + unitSize * 1.5
1871
- );
1872
- ctx.fill();
1873
- ctx.stroke();
1874
- } else if (flagCount > 0) {
1875
- let adj = 1 - flagCount % 2;
1876
- let fx = (p) => x + (-p * 0.25 + 0.5) * unitSize;
1877
- let fy = (p) => y + (p + adj) * unitSize;
1878
- ctx.beginPath();
1879
- ctx.moveTo(fx(1 + flagCount), fy(1 + flagCount));
1880
- ctx.lineTo(fx(-0.5 - flagCount), fy(-0.5 - flagCount));
1881
- ctx.stroke();
1882
- for (let i = 0; i < flagCount; i++) {
1883
- let t = flagCount - i * 2;
1884
- ctx.beginPath();
1885
- ctx.moveTo(fx(t - 2.5), fy(t - 2.5));
1886
- ctx.quadraticCurveTo(
1887
- fx(t - 0.5) + unitSize * 0.25,
1888
- fy(t - 1.5),
1889
- fx(t - 1.5) - unitSize * 1.5,
1890
- fy(t - 1.5)
1891
- );
1892
- ctx.stroke();
1893
- ctx.beginPath();
1894
- ctx.arc(fx(t - 2) - unitSize * 1.5, fy(t - 2), unitSize * 0.5, 0, Math.PI * 2);
1895
- ctx.fill();
1896
- }
1897
- }
2043
+ renderer.drawRest(noteSize, x, y, color);
1898
2044
  dotRects.forEach((r) => {
1899
2045
  renderer.fillCircle(r.centerX, r.centerY, r.width / 2);
1900
2046
  });
@@ -1903,54 +2049,97 @@ var ObjRest = class extends MusicObject {
1903
2049
  };
1904
2050
 
1905
2051
  // src/score/engine/obj-note-group.ts
1906
- import { Utils as Utils4 } from "@tspro/ts-utils-lib";
1907
- import { Note as Note4, NoteLengthProps as NoteLengthProps3, RhythmProps as RhythmProps3, Tuplet as Tuplet3 } from "@tspro/web-music-score/theory";
1908
-
1909
- // src/score/engine/obj-beam-group.ts
1910
2052
  import { Utils as Utils3 } from "@tspro/ts-utils-lib";
1911
- import { NoteLength as NoteLength2, Tuplet as Tuplet2, NoteLengthProps as NoteLengthProps2 } from "@tspro/web-music-score/theory";
2053
+ import { Note as Note4, NoteLengthProps as NoteLengthProps3, RhythmProps as RhythmProps3, Tuplet as Tuplet2 } from "@tspro/web-music-score/theory";
1912
2054
  import { MusicError as MusicError6, MusicErrorType as MusicErrorType6 } from "@tspro/web-music-score/core";
1913
- var adjustBeamAngle = (dx, dy) => {
1914
- let T = DocumentSettings.BeamAngleFactor;
1915
- if (!Number.isFinite(T) || T === 0) {
1916
- return dy;
1917
- } else {
1918
- let k = dx / dy / T;
1919
- k = Math.sign(k) * Math.sqrt(Math.abs(k));
1920
- return dx / k * T;
1921
- }
1922
- };
1923
- var BeamPoint = class {
1924
- constructor(staff, beamGroup, symbol, x, y) {
2055
+ function getStem(stem) {
2056
+ return Utils3.Is.isEnumValue(stem, Stem) ? stem : void 0;
2057
+ }
2058
+ function getArpeggio(a) {
2059
+ return Utils3.Is.isEnumValue(a, Arpeggio) ? a : a === true ? "up" /* Up */ : void 0;
2060
+ }
2061
+ function sortNoteStringData(notes, strings) {
2062
+ let stringArr = Utils3.Arr.isArray(strings) ? strings : strings !== void 0 ? [strings] : [];
2063
+ let noteStringData = notes.map((note, i) => {
2064
+ return { note, string: stringArr[i] };
2065
+ });
2066
+ noteStringData = Utils3.Arr.removeDuplicatesCmp(noteStringData, (a, b) => Note4.equals(a.note, b.note)).sort((a, b) => Note4.compareFunc(a.note, b.note));
2067
+ return {
2068
+ notes: noteStringData.map((e) => e.note),
2069
+ strings: noteStringData.every((e) => e.string === void 0) ? void 0 : noteStringData.map((e) => e.string)
2070
+ };
2071
+ }
2072
+ var ObjStaffNoteGroup = class extends MusicObject {
2073
+ constructor(staff, noteGroup) {
2074
+ super(staff);
1925
2075
  this.staff = staff;
1926
- this.beamGroup = beamGroup;
1927
- this.symbol = symbol;
1928
- this.x = x;
1929
- this.y = y;
1930
- __publicField(this, "topBeamsHeight", 0);
1931
- __publicField(this, "bottomBeamsHeight", 0);
1932
- staff.addObject(this);
1933
- }
1934
- offset(dx, dy) {
1935
- this.x += dx;
1936
- this.y += dy;
1937
- this.beamGroup.requestRectUpdate();
2076
+ this.noteGroup = noteGroup;
2077
+ __publicField(this, "noteHeadRects", []);
2078
+ __publicField(this, "dotRects", []);
2079
+ __publicField(this, "accidentals", []);
2080
+ __publicField(this, "stemTip");
2081
+ __publicField(this, "stemBase");
2082
+ __publicField(this, "flagRects", []);
2083
+ __publicField(this, "prevTopNoteY", 0);
2084
+ __publicField(this, "prevBottomNoteY", 0);
2085
+ __publicField(this, "mi");
2086
+ this.mi = new MStaffNoteGroup(this);
2087
+ }
2088
+ getMusicInterface() {
2089
+ return this.mi;
2090
+ }
2091
+ pick(x, y) {
2092
+ if (!this.getRect().contains(x, y)) {
2093
+ return [];
2094
+ }
2095
+ for (let i = 0; i < this.accidentals.length; i++) {
2096
+ let arr = this.accidentals[i].pick(x, y);
2097
+ if (arr.length > 0) {
2098
+ return [this, ...arr];
2099
+ }
2100
+ }
2101
+ return [this];
2102
+ }
2103
+ updateRect() {
2104
+ this.rect = this.noteHeadRects[0].copy();
2105
+ this.noteHeadRects.forEach((r) => this.rect.expandInPlace(r));
2106
+ if (this.stemTip) this.rect.expandInPlace(this.stemTip);
2107
+ if (this.stemBase) this.rect.expandInPlace(this.stemBase);
2108
+ this.dotRects.forEach((r) => this.rect.expandInPlace(r));
2109
+ this.flagRects.forEach((r) => this.rect.expandInPlace(r));
2110
+ this.accidentals.forEach((a) => this.rect.expandInPlace(a.getRect()));
1938
2111
  }
1939
2112
  getRect() {
1940
- return new DivRect(this.x, this.x, this.x, this.y - this.topBeamsHeight, this.y, this.y + this.bottomBeamsHeight);
2113
+ let bottomNoteRect = this.noteHeadRects[0];
2114
+ let topNoteRect = this.noteHeadRects[this.noteHeadRects.length - 1];
2115
+ if (this.prevTopNoteY !== topNoteRect.centerY || this.prevBottomNoteY !== bottomNoteRect.centerY) {
2116
+ this.prevTopNoteY = topNoteRect.centerY;
2117
+ this.prevBottomNoteY = bottomNoteRect.centerY;
2118
+ this.requestRectUpdate();
2119
+ }
2120
+ return super.getRect();
2121
+ }
2122
+ offset(dx, dy) {
2123
+ var _a, _b;
2124
+ this.noteHeadRects.forEach((n) => n.offsetInPlace(dx, dy));
2125
+ this.dotRects.forEach((n) => n.offsetInPlace(dx, dy));
2126
+ this.accidentals.forEach((n) => n.offset(dx, dy));
2127
+ (_a = this.stemTip) == null ? void 0 : _a.offsetInPlace(dx, dy);
2128
+ (_b = this.stemBase) == null ? void 0 : _b.offsetInPlace(dx, dy);
2129
+ this.flagRects.forEach((n) => n.offsetInPlace(dx, dy));
2130
+ this.requestRectUpdate();
2131
+ this.noteGroup.requestRectUpdate();
1941
2132
  }
1942
2133
  };
1943
- var ObjStaffBeamGroup = class extends MusicObject {
1944
- constructor(staff, beamGroup) {
1945
- super(staff);
1946
- this.staff = staff;
1947
- this.beamGroup = beamGroup;
1948
- __publicField(this, "tupletNumber");
1949
- __publicField(this, "tupletNumberOffsetY", 0);
1950
- __publicField(this, "points", []);
2134
+ var ObjTabNoteGroup = class extends MusicObject {
2135
+ constructor(tab, noteGroup) {
2136
+ super(tab);
2137
+ this.tab = tab;
2138
+ this.noteGroup = noteGroup;
2139
+ __publicField(this, "fretNumbers", []);
1951
2140
  __publicField(this, "mi");
1952
- staff.addObject(this);
1953
- this.mi = new MStaffBeamGroup(this);
2141
+ tab.addObject(this);
2142
+ this.mi = new MTabNoteGroup(this);
1954
2143
  }
1955
2144
  getMusicInterface() {
1956
2145
  return this.mi;
@@ -1958,95 +2147,102 @@ var ObjStaffBeamGroup = class extends MusicObject {
1958
2147
  pick(x, y) {
1959
2148
  return this.getRect().contains(x, y) ? [this] : [];
1960
2149
  }
2150
+ updateRect() {
2151
+ this.rect = this.fretNumbers[0].getRect().copy();
2152
+ this.fretNumbers.forEach((fn) => this.rect.expandInPlace(fn.getRect()));
2153
+ }
1961
2154
  offset(dx, dy) {
1962
- var _a;
1963
- this.points.forEach((p) => p.offset(dx, 0));
1964
- (_a = this.tupletNumber) == null ? void 0 : _a.offset(dx, dy);
2155
+ this.fretNumbers.forEach((f) => f.offset(dx, dy));
1965
2156
  this.requestRectUpdate();
1966
- this.beamGroup.requestRectUpdate();
1967
- }
1968
- updateRect() {
1969
- if (this.points.length > 0) {
1970
- this.rect = this.points[0].getRect().copy();
1971
- } else if (this.tupletNumber) {
1972
- this.rect = this.tupletNumber.getRect().copy();
1973
- }
1974
- this.points.forEach((pt) => this.rect.expandInPlace(pt.getRect()));
1975
- if (this.tupletNumber) {
1976
- this.rect.expandInPlace(this.tupletNumber.getRect());
1977
- }
2157
+ this.noteGroup.requestRectUpdate();
1978
2158
  }
1979
2159
  };
1980
- var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
1981
- constructor(symbols, tupletRatio) {
1982
- super(symbols[0].measure);
1983
- this.symbols = symbols;
1984
- this.tupletRatio = tupletRatio;
1985
- __publicField(this, "mi");
1986
- __publicField(this, "type");
2160
+ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2161
+ constructor(col, voiceId, notes, noteLength, options, tupletRatio) {
2162
+ var _a, _b, _c;
2163
+ super(col);
2164
+ this.col = col;
2165
+ this.voiceId = voiceId;
2166
+ this.notes = notes;
2167
+ __publicField(this, "minDiatonicId");
2168
+ __publicField(this, "maxDiatonicId");
2169
+ __publicField(this, "ownDiatonicId");
2170
+ // Average diatonicId of notes.
2171
+ __publicField(this, "ownStemDir");
2172
+ __publicField(this, "ownString");
2173
+ __publicField(this, "color");
2174
+ __publicField(this, "staccato");
2175
+ __publicField(this, "diamond");
2176
+ __publicField(this, "arpeggio");
2177
+ __publicField(this, "oldStyleTriplet");
2178
+ __publicField(this, "rhythmProps");
2179
+ __publicField(this, "startConnnectives", []);
2180
+ __publicField(this, "runningConnectives", []);
2181
+ __publicField(this, "leftBeamCount", 0);
2182
+ __publicField(this, "rightBeamCount", 0);
2183
+ __publicField(this, "beamGroup");
1987
2184
  __publicField(this, "staffObjects", []);
1988
- this.mi = new MBeamGroup(this);
1989
- let beamGroupName = tupletRatio ? "Tuplet" : "BeamGroup";
1990
- if (!symbols.every((s) => s.measure === symbols[0].measure)) {
1991
- throw new MusicError6(MusicErrorType6.Score, `All ${beamGroupName} symbols are not in same measure.`);
1992
- } else if (symbols.length < 2) {
1993
- throw new MusicError6(MusicErrorType6.Score, `${beamGroupName} needs minimum 2 symbols, but ${symbols.length} given.`);
1994
- }
1995
- if (tupletRatio !== void 0) {
1996
- let isGroup = symbols.length < 3 || symbols.some((s) => !(s instanceof ObjNoteGroup)) || symbols.some((s) => s.rhythmProps.flagCount !== symbols[0].rhythmProps.flagCount);
1997
- if (symbols.length >= 3 && symbols[0] instanceof ObjNoteGroup && symbols[symbols.length - 1] instanceof ObjNoteGroup && symbols[0].rhythmProps.flagCount === symbols[symbols.length - 1].rhythmProps.flagCount) {
1998
- isGroup = false;
1999
- }
2000
- if (symbols.some((s) => NoteLengthProps2.cmp(s.rhythmProps.noteLength, NoteLength2.Quarter) >= 0)) {
2001
- isGroup = true;
2002
- }
2003
- this.type = isGroup ? 2 /* TupletGroup */ : 1 /* TupletBeam */;
2004
- ObjNoteGroup.setTupletBeamCounts(this);
2005
- } else {
2006
- this.type = 0 /* RegularBeam */;
2007
- }
2008
- if (symbols.every((s) => s.getBeamGroup() === void 0)) {
2009
- symbols.forEach((s) => s.setBeamGroup(this));
2010
- symbols[0].measure.addBeamGroup(this);
2011
- } else {
2012
- throw new MusicError6(MusicErrorType6.Score, `Cannot add ${beamGroupName} because some symbol already has one.`);
2185
+ __publicField(this, "tabObjects", []);
2186
+ __publicField(this, "mi");
2187
+ if (!Utils3.Is.isIntegerGte(notes.length, 1)) {
2188
+ throw new MusicError6(MusicErrorType6.Score, "Cannot create note group object because notes array is empty.");
2013
2189
  }
2190
+ let noteStringData = sortNoteStringData(notes, options == null ? void 0 : options.string);
2191
+ this.notes = noteStringData.notes;
2192
+ this.minDiatonicId = this.notes[0].diatonicId;
2193
+ this.maxDiatonicId = this.notes[this.notes.length - 1].diatonicId;
2194
+ this.ownDiatonicId = this.measure.updateOwnDiatonicId(voiceId, Math.round((this.minDiatonicId + this.maxDiatonicId) / 2));
2195
+ this.ownStemDir = this.measure.updateOwnStemDir(this, getStem(options == null ? void 0 : options.stem));
2196
+ this.ownString = this.measure.updateOwnString(this, noteStringData.strings);
2197
+ this.color = (_a = options == null ? void 0 : options.color) != null ? _a : "black";
2198
+ this.staccato = (_b = options == null ? void 0 : options.staccato) != null ? _b : false;
2199
+ this.diamond = (_c = options == null ? void 0 : options.diamond) != null ? _c : false;
2200
+ this.arpeggio = getArpeggio(options == null ? void 0 : options.arpeggio);
2201
+ this.oldStyleTriplet = tupletRatio === void 0 && ((options == null ? void 0 : options.triplet) === true || NoteLengthProps3.get(noteLength).isTriplet);
2202
+ 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;
2203
+ this.rhythmProps = RhythmProps3.get(noteLength, dotCount, (tupletRatio != null ? tupletRatio : this.oldStyleTriplet) ? Tuplet2.Triplet : void 0);
2204
+ this.mi = new MNoteGroup(this);
2014
2205
  }
2015
- get showTupletRatio() {
2016
- var _a;
2017
- return ((_a = this.tupletRatio) == null ? void 0 : _a.showRatio) === true;
2206
+ getMusicInterface() {
2207
+ return this.mi;
2018
2208
  }
2019
- static createBeam(noteGroups) {
2020
- if (noteGroups.length > 1) {
2021
- new _ObjBeamGroup(noteGroups, void 0);
2022
- }
2209
+ get doc() {
2210
+ return this.col.doc;
2023
2211
  }
2024
- static createOldStyleTriplet(symbols) {
2025
- let s2 = symbols.slice(0, 2);
2026
- let n2 = s2.map((s) => s.rhythmProps.noteSize);
2027
- if (s2.length === 2 && s2.every((s) => s.oldStyleTriplet && s.getBeamGroup() === void 0) && (n2[0] * 2 === n2[1] || n2[1] * 2 === n2[0])) {
2028
- new _ObjBeamGroup(s2, Tuplet2.Triplet);
2029
- return 2;
2030
- }
2031
- let s3 = symbols.slice(0, 3);
2032
- let n3 = s3.map((s) => s.rhythmProps.noteSize);
2033
- if (s3.length === 3 && s3.every((s) => s.oldStyleTriplet && s.getBeamGroup() === void 0) && n3.every((n) => n === n3[0])) {
2034
- new _ObjBeamGroup(s3, Tuplet2.Triplet);
2035
- return 3;
2036
- }
2037
- return 0;
2212
+ get measure() {
2213
+ return this.col.measure;
2038
2214
  }
2039
- static createTuplet(symbols, tupletRatio) {
2040
- new _ObjBeamGroup(symbols, tupletRatio);
2215
+ get row() {
2216
+ return this.col.row;
2041
2217
  }
2042
- getMusicInterface() {
2043
- return this.mi;
2218
+ get stemDir() {
2219
+ return this.beamGroup ? this.beamGroup.stemDir : this.ownStemDir;
2044
2220
  }
2045
- detach() {
2046
- this.getSymbols().forEach((s) => s.resetBeamGroup());
2221
+ enableConnective(line) {
2222
+ return line.containsVoiceId(this.voiceId) && (line instanceof ObjTab || line.containsDiatonicId(this.ownDiatonicId));
2047
2223
  }
2048
- isEmpty() {
2049
- return this.staffObjects.length === 0;
2224
+ startConnective(connectiveProps) {
2225
+ if (!this.row.hasStaff && connectiveProps.connective === "tie" /* Tie */) {
2226
+ throw new MusicError6(MusicErrorType6.Score, "Ties not implemented for guitar tabs alone, staff is required!");
2227
+ } else if (!this.row.hasStaff && connectiveProps.connective === "slur" /* Slur */) {
2228
+ throw new MusicError6(MusicErrorType6.Score, "Slurs not implemented for guitar tabs alone, staff is required!");
2229
+ }
2230
+ this.startConnnectives.push(connectiveProps);
2231
+ this.doc.addConnectiveProps(connectiveProps);
2232
+ }
2233
+ getStaticObjects(line) {
2234
+ let staticObjects = [];
2235
+ this.staffObjects.forEach((obj) => {
2236
+ if (obj.staff === line) {
2237
+ staticObjects.push(obj);
2238
+ }
2239
+ });
2240
+ this.tabObjects.forEach((obj) => {
2241
+ if (obj.tab === line) {
2242
+ staticObjects.push(obj);
2243
+ }
2244
+ });
2245
+ return staticObjects;
2050
2246
  }
2051
2247
  pick(x, y) {
2052
2248
  if (!this.getRect().contains(x, y)) {
@@ -2058,465 +2254,25 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2058
2254
  return [this, ...arr];
2059
2255
  }
2060
2256
  }
2061
- return [this];
2062
- }
2063
- getType() {
2064
- return this.type;
2065
- }
2066
- isTuplet() {
2067
- return this.type === 1 /* TupletBeam */ || this.type === 2 /* TupletGroup */;
2068
- }
2069
- getSymbols() {
2070
- return this.symbols;
2071
- }
2072
- getFirstSymbol() {
2073
- return this.symbols[0];
2257
+ for (let i = 0; i < this.tabObjects.length; i++) {
2258
+ let arr = this.tabObjects[i].pick(x, y);
2259
+ if (arr.length > 0) {
2260
+ return [this, ...arr];
2261
+ }
2262
+ }
2263
+ return [];
2074
2264
  }
2075
- getLastSymbol() {
2076
- return this.symbols[this.symbols.length - 1];
2265
+ getTopNote() {
2266
+ return this.notes[this.notes.length - 1];
2077
2267
  }
2078
- get stemDir() {
2079
- return this.symbols[0].ownStemDir;
2080
- }
2081
- layout(renderer) {
2082
- this.requestRectUpdate();
2083
- this.staffObjects.length = 0;
2084
- let symbols = this.getSymbols();
2085
- if (symbols.length === 0) {
2086
- return;
2087
- }
2088
- let voiceId = symbols[0].voiceId;
2089
- if (symbols.some((symbol) => symbol.voiceId !== voiceId)) {
2090
- return;
2091
- }
2092
- let { unitSize } = renderer;
2093
- let { stemDir } = this;
2094
- let symbolsBeamCoords = symbols.map((s) => s.getBeamCoords());
2095
- symbolsBeamCoords[0].map((s) => s == null ? void 0 : s.staff).forEach((mainStaff, index) => {
2096
- var _a, _b;
2097
- if (!mainStaff) {
2098
- return;
2099
- }
2100
- let symbolX = symbolsBeamCoords.map((s) => {
2101
- var _a2;
2102
- return (_a2 = s[index]) == null ? void 0 : _a2.x;
2103
- });
2104
- let symbolY = symbolsBeamCoords.map((s) => {
2105
- var _a2;
2106
- return (_a2 = s[index]) == null ? void 0 : _a2.y;
2107
- });
2108
- let symbolStaff = symbolsBeamCoords.map((s) => {
2109
- var _a2;
2110
- return (_a2 = s[index]) == null ? void 0 : _a2.staff;
2111
- });
2112
- let symbolStemHeight = symbolsBeamCoords.map((s) => {
2113
- var _a2;
2114
- return (_a2 = s[index]) == null ? void 0 : _a2.stemHeight;
2115
- });
2116
- let leftSymbol = symbols[0];
2117
- let leftX = symbolX[0];
2118
- let leftY = symbolY[0];
2119
- let leftStaff = symbolStaff[0];
2120
- let rightSymbol = symbols[symbols.length - 1];
2121
- let rightX = symbolX[symbolX.length - 1];
2122
- let rightY = symbolY[symbolY.length - 1];
2123
- let rightStaff = symbolStaff[symbolY.length - 1];
2124
- if (leftX === void 0 || leftY === void 0 || leftStaff === void 0 || rightX === void 0 || rightY === void 0 || rightStaff === void 0) {
2125
- return;
2126
- }
2127
- let leftStemHeight = (_a = symbolStemHeight[0]) != null ? _a : 0;
2128
- let rightStemHeight = (_b = symbolStemHeight[symbolStemHeight.length - 1]) != null ? _b : 0;
2129
- if (this.type !== 2 /* TupletGroup */) {
2130
- let leftDy = leftStemHeight < rightStemHeight ? Math.sqrt(rightStemHeight - leftStemHeight) : 0;
2131
- let rightDy = rightStemHeight < leftStemHeight ? Math.sqrt(leftStemHeight - rightStemHeight) : 0;
2132
- if (stemDir === "up" /* Up */) {
2133
- leftDy *= -1;
2134
- rightDy *= -1;
2135
- }
2136
- if (leftDy !== 0) {
2137
- leftY += leftDy;
2138
- symbolY[0] += leftDy;
2139
- }
2140
- if (rightDy !== 0) {
2141
- rightY += rightDy;
2142
- symbolY[symbolY.length - 1] += rightDy;
2143
- }
2144
- }
2145
- let groupLineDy = unitSize * 2 * (stemDir === "up" /* Up */ ? -1 : 1);
2146
- let centerY = (rightY + leftY) / 2;
2147
- let halfDy = adjustBeamAngle(rightX - leftX, rightY - leftY) / 2;
2148
- leftY = centerY - halfDy;
2149
- rightY = centerY + halfDy;
2150
- let raiseBeamY = 0;
2151
- symbolY.forEach((symY, i) => {
2152
- let symX = symbolX[i];
2153
- if (symX !== void 0 && symY !== void 0) {
2154
- let beamY = Utils3.Math.interpolateY(leftX, leftY, rightX, rightY, symX);
2155
- let raiseY = symY - beamY;
2156
- if (stemDir === "up" /* Up */ && raiseY < 0) {
2157
- raiseBeamY = Math.min(raiseBeamY, raiseY);
2158
- } else if (stemDir === "down" /* Down */ && raiseY > 0) {
2159
- raiseBeamY = Math.max(raiseBeamY, raiseY);
2160
- }
2161
- }
2162
- });
2163
- leftY += raiseBeamY;
2164
- rightY += raiseBeamY;
2165
- symbolY = symbolY.map((y) => y === void 0 ? void 0 : y + raiseBeamY);
2166
- let obj = new ObjStaffBeamGroup(mainStaff, this);
2167
- if (this.type === 2 /* TupletGroup */) {
2168
- let ef = unitSize / (rightX - leftX);
2169
- let l = Utils3.Math.interpolateCoord(leftX, leftY + groupLineDy, rightX, rightY + groupLineDy, -ef);
2170
- let r = Utils3.Math.interpolateCoord(leftX, leftY + groupLineDy, rightX, rightY + groupLineDy, 1 + ef);
2171
- obj.points.push(new BeamPoint(leftStaff, this, leftSymbol, l.x, l.y));
2172
- obj.points.push(new BeamPoint(rightStaff, this, rightSymbol, r.x, r.y));
2173
- obj.tupletNumberOffsetY = 0;
2174
- } else if (this.type === 0 /* RegularBeam */ || this.type === 1 /* TupletBeam */) {
2175
- raiseBeamY *= 0.5;
2176
- let { beamThickness } = renderer;
2177
- const beamHeight = (i) => {
2178
- let sym = symbols[i];
2179
- if (sym instanceof ObjNoteGroup) {
2180
- let beamCount = sym instanceof ObjNoteGroup ? Math.max(sym.getLeftBeamCount(), sym.getRightBeamCount()) : 0;
2181
- return DocumentSettings.BeamSeparation * unitSize * (this.stemDir === "up" /* Up */ ? beamCount - 1 : 0);
2182
- } else {
2183
- return 0;
2184
- }
2185
- };
2186
- symbols.forEach((sym, i) => {
2187
- let symStaff = symbolStaff[i];
2188
- let symX = symbolX[i];
2189
- let symY = symbolY[i];
2190
- if (symStaff && symX !== void 0 && symY !== void 0) {
2191
- let pt = new BeamPoint(symStaff, this, sym, symX, symY);
2192
- pt.topBeamsHeight = beamThickness / 2 + (stemDir === "down" /* Down */ ? beamHeight(i) : 0);
2193
- pt.bottomBeamsHeight = beamThickness / 2 + (stemDir === "up" /* Up */ ? beamHeight(i) : 0);
2194
- obj.points.push(pt);
2195
- }
2196
- });
2197
- obj.tupletNumberOffsetY = groupLineDy;
2198
- }
2199
- if (this.isTuplet() && this.tupletRatio) {
2200
- let txt = this.showTupletRatio ? String(this.tupletRatio.parts) + ":" + String(this.tupletRatio.inTimeOf) : String(this.tupletRatio.parts);
2201
- obj.tupletNumber = new ObjText(this, txt, 0.5, 0.5);
2202
- obj.tupletNumber.layout(renderer);
2203
- obj.tupletNumber.offset((leftX + rightX) / 2, (leftY + rightY) / 2 + obj.tupletNumberOffsetY);
2204
- }
2205
- if (obj.points.length >= 2) {
2206
- this.staffObjects.push(obj);
2207
- }
2208
- });
2209
- }
2210
- updateRect() {
2211
- if (this.staffObjects.length === 0) {
2212
- this.rect = new DivRect();
2213
- } else {
2214
- this.staffObjects.forEach((obj) => obj.updateRect());
2215
- this.rect = this.staffObjects[0].getRect().copy();
2216
- for (let i = 1; i < this.staffObjects.length; i++) {
2217
- this.rect.expandInPlace(this.staffObjects[i].getRect());
2218
- }
2219
- }
2220
- }
2221
- updateStemTips() {
2222
- this.staffObjects.forEach((obj) => {
2223
- let left = obj.points[0];
2224
- let right = obj.points[obj.points.length - 1];
2225
- if (this.type !== 2 /* TupletGroup */) {
2226
- obj.points.forEach((pt) => {
2227
- if (pt.symbol instanceof ObjNoteGroup) {
2228
- if (pt !== left && pt !== right) {
2229
- pt.y = Utils3.Math.interpolateY(left.x, left.y, right.x, right.y, pt.x);
2230
- }
2231
- pt.symbol.setStemTipY(pt.staff, pt.y);
2232
- }
2233
- });
2234
- }
2235
- if (obj.tupletNumber) {
2236
- let y = (left.y + right.y) / 2 + obj.tupletNumberOffsetY;
2237
- obj.tupletNumber.offset(0, -obj.tupletNumber.getRect().centerY + y);
2238
- }
2239
- });
2240
- }
2241
- offset(dx, dy) {
2242
- this.staffObjects.forEach((obj) => obj.offset(dx, 0));
2243
- this.requestRectUpdate();
2244
- }
2245
- draw(renderer) {
2246
- let { unitSize, beamThickness, lineWidth } = renderer;
2247
- let color = "black";
2248
- this.staffObjects.forEach((obj) => {
2249
- if (this.type === 2 /* TupletGroup */) {
2250
- let l = obj.points[0];
2251
- let r = obj.points[obj.points.length - 1];
2252
- if (l && r) {
2253
- let tf = obj.tupletNumber ? obj.tupletNumber.getRect().width / (r.x - l.x) * 1.2 : 0;
2254
- let lc = Utils3.Math.interpolateCoord(l.x, l.y, r.x, r.y, 0.5 - tf / 2);
2255
- let rc = Utils3.Math.interpolateCoord(l.x, l.y, r.x, r.y, 0.5 + tf / 2);
2256
- let tipH = this.stemDir === "up" /* Up */ ? unitSize : -unitSize;
2257
- renderer.drawLine(l.x, l.y, lc.x, lc.y, color, lineWidth);
2258
- renderer.drawLine(rc.x, rc.y, r.x, r.y, color, lineWidth);
2259
- renderer.drawLine(l.x, l.y, l.x, l.y + tipH, color, lineWidth);
2260
- renderer.drawLine(r.x, r.y, r.x, r.y + tipH, color, lineWidth);
2261
- }
2262
- } else if (this.type === 0 /* RegularBeam */ || this.type === 1 /* TupletBeam */) {
2263
- let beamSeparation = DocumentSettings.BeamSeparation * unitSize * (this.stemDir === "up" /* Up */ ? 1 : -1);
2264
- let noteGroupPoints = obj.points.filter((p) => p.symbol instanceof ObjNoteGroup);
2265
- for (let i = 0; i < noteGroupPoints.length - 1; i++) {
2266
- let left = noteGroupPoints[i];
2267
- let right = noteGroupPoints[i + 1];
2268
- if (!(left.symbol instanceof ObjNoteGroup && right.symbol instanceof ObjNoteGroup)) {
2269
- continue;
2270
- }
2271
- let leftBeamCount = left.symbol.getRightBeamCount();
2272
- let rightBeamCount = right.symbol.getLeftBeamCount();
2273
- let lx = left.x;
2274
- let ly = left.y;
2275
- let rx = right.x;
2276
- let ry = right.y;
2277
- for (let beamId = 0; beamId < Math.max(leftBeamCount, rightBeamCount); beamId++) {
2278
- if (beamId < leftBeamCount && beamId < rightBeamCount) {
2279
- renderer.drawLine(lx, ly, rx, ry, color, beamThickness);
2280
- } else if (leftBeamCount > rightBeamCount) {
2281
- renderer.drawPartialLine(lx, ly, rx, ry, 0, 0.25, color, beamThickness);
2282
- } else if (rightBeamCount > leftBeamCount) {
2283
- renderer.drawPartialLine(lx, ly, rx, ry, 0.75, 1, color, beamThickness);
2284
- }
2285
- ly += beamSeparation;
2286
- ry += beamSeparation;
2287
- }
2288
- }
2289
- }
2290
- if (obj.tupletNumber) {
2291
- obj.tupletNumber.draw(renderer);
2292
- }
2293
- });
2294
- }
2295
- };
2296
-
2297
- // src/score/engine/obj-note-group.ts
2298
- import { MusicError as MusicError7, MusicErrorType as MusicErrorType7 } from "@tspro/web-music-score/core";
2299
- function getStem(stem) {
2300
- return Utils4.Is.isEnumValue(stem, Stem) ? stem : void 0;
2301
- }
2302
- function getArpeggio(a) {
2303
- return Utils4.Is.isEnumValue(a, Arpeggio) ? a : a === true ? "up" /* Up */ : void 0;
2304
- }
2305
- function sortNoteStringData(notes, strings) {
2306
- let stringArr = Utils4.Arr.isArray(strings) ? strings : strings !== void 0 ? [strings] : [];
2307
- let noteStringData = notes.map((note, i) => {
2308
- return { note, string: stringArr[i] };
2309
- });
2310
- noteStringData = Utils4.Arr.removeDuplicatesCmp(noteStringData, (a, b) => Note4.equals(a.note, b.note)).sort((a, b) => Note4.compareFunc(a.note, b.note));
2311
- return {
2312
- notes: noteStringData.map((e) => e.note),
2313
- strings: noteStringData.every((e) => e.string === void 0) ? void 0 : noteStringData.map((e) => e.string)
2314
- };
2315
- }
2316
- var ObjStaffNoteGroup = class extends MusicObject {
2317
- constructor(staff, noteGroup) {
2318
- super(staff);
2319
- this.staff = staff;
2320
- this.noteGroup = noteGroup;
2321
- __publicField(this, "noteHeadRects", []);
2322
- __publicField(this, "dotRects", []);
2323
- __publicField(this, "accidentals", []);
2324
- __publicField(this, "stemTip");
2325
- __publicField(this, "stemBase");
2326
- __publicField(this, "flagRects", []);
2327
- __publicField(this, "prevTopNoteY", 0);
2328
- __publicField(this, "prevBottomNoteY", 0);
2329
- __publicField(this, "mi");
2330
- this.mi = new MStaffNoteGroup(this);
2331
- }
2332
- getMusicInterface() {
2333
- return this.mi;
2334
- }
2335
- pick(x, y) {
2336
- if (!this.getRect().contains(x, y)) {
2337
- return [];
2338
- }
2339
- for (let i = 0; i < this.accidentals.length; i++) {
2340
- let arr = this.accidentals[i].pick(x, y);
2341
- if (arr.length > 0) {
2342
- return [this, ...arr];
2343
- }
2344
- }
2345
- return [this];
2346
- }
2347
- updateRect() {
2348
- this.rect = this.noteHeadRects[0].copy();
2349
- this.noteHeadRects.forEach((r) => this.rect.expandInPlace(r));
2350
- if (this.stemTip) this.rect.expandInPlace(this.stemTip);
2351
- if (this.stemBase) this.rect.expandInPlace(this.stemBase);
2352
- this.dotRects.forEach((r) => this.rect.expandInPlace(r));
2353
- this.flagRects.forEach((r) => this.rect.expandInPlace(r));
2354
- this.accidentals.forEach((a) => this.rect.expandInPlace(a.getRect()));
2355
- }
2356
- getRect() {
2357
- let bottomNoteRect = this.noteHeadRects[0];
2358
- let topNoteRect = this.noteHeadRects[this.noteHeadRects.length - 1];
2359
- if (this.prevTopNoteY !== topNoteRect.centerY || this.prevBottomNoteY !== bottomNoteRect.centerY) {
2360
- this.prevTopNoteY = topNoteRect.centerY;
2361
- this.prevBottomNoteY = bottomNoteRect.centerY;
2362
- this.requestRectUpdate();
2363
- }
2364
- return super.getRect();
2365
- }
2366
- offset(dx, dy) {
2367
- var _a, _b;
2368
- this.noteHeadRects.forEach((n) => n.offsetInPlace(dx, dy));
2369
- this.dotRects.forEach((n) => n.offsetInPlace(dx, dy));
2370
- this.accidentals.forEach((n) => n.offset(dx, dy));
2371
- (_a = this.stemTip) == null ? void 0 : _a.offsetInPlace(dx, dy);
2372
- (_b = this.stemBase) == null ? void 0 : _b.offsetInPlace(dx, dy);
2373
- this.flagRects.forEach((n) => n.offsetInPlace(dx, dy));
2374
- this.requestRectUpdate();
2375
- this.noteGroup.requestRectUpdate();
2376
- }
2377
- };
2378
- var ObjTabNoteGroup = class extends MusicObject {
2379
- constructor(tab, noteGroup) {
2380
- super(tab);
2381
- this.tab = tab;
2382
- this.noteGroup = noteGroup;
2383
- __publicField(this, "fretNumbers", []);
2384
- __publicField(this, "mi");
2385
- tab.addObject(this);
2386
- this.mi = new MTabNoteGroup(this);
2387
- }
2388
- getMusicInterface() {
2389
- return this.mi;
2390
- }
2391
- pick(x, y) {
2392
- return this.getRect().contains(x, y) ? [this] : [];
2393
- }
2394
- updateRect() {
2395
- this.rect = this.fretNumbers[0].getRect().copy();
2396
- this.fretNumbers.forEach((fn) => this.rect.expandInPlace(fn.getRect()));
2397
- }
2398
- offset(dx, dy) {
2399
- this.fretNumbers.forEach((f) => f.offset(dx, dy));
2400
- this.requestRectUpdate();
2401
- this.noteGroup.requestRectUpdate();
2402
- }
2403
- };
2404
- var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2405
- constructor(col, voiceId, notes, noteLength, options, tupletRatio) {
2406
- var _a, _b, _c;
2407
- super(col);
2408
- this.col = col;
2409
- this.voiceId = voiceId;
2410
- this.notes = notes;
2411
- __publicField(this, "minDiatonicId");
2412
- __publicField(this, "maxDiatonicId");
2413
- __publicField(this, "ownDiatonicId");
2414
- // Average diatonicId of notes.
2415
- __publicField(this, "ownStemDir");
2416
- __publicField(this, "ownString");
2417
- __publicField(this, "color");
2418
- __publicField(this, "staccato");
2419
- __publicField(this, "diamond");
2420
- __publicField(this, "arpeggio");
2421
- __publicField(this, "oldStyleTriplet");
2422
- __publicField(this, "rhythmProps");
2423
- __publicField(this, "startConnnectives", []);
2424
- __publicField(this, "runningConnectives", []);
2425
- __publicField(this, "leftBeamCount", 0);
2426
- __publicField(this, "rightBeamCount", 0);
2427
- __publicField(this, "beamGroup");
2428
- __publicField(this, "staffObjects", []);
2429
- __publicField(this, "tabObjects", []);
2430
- __publicField(this, "mi");
2431
- if (!Utils4.Is.isIntegerGte(notes.length, 1)) {
2432
- throw new MusicError7(MusicErrorType7.Score, "Cannot create note group object because notes array is empty.");
2433
- }
2434
- let noteStringData = sortNoteStringData(notes, options == null ? void 0 : options.string);
2435
- this.notes = noteStringData.notes;
2436
- this.minDiatonicId = this.notes[0].diatonicId;
2437
- this.maxDiatonicId = this.notes[this.notes.length - 1].diatonicId;
2438
- this.ownDiatonicId = this.measure.updateOwnDiatonicId(voiceId, Math.round((this.minDiatonicId + this.maxDiatonicId) / 2));
2439
- this.ownStemDir = this.measure.updateOwnStemDir(this, getStem(options == null ? void 0 : options.stem));
2440
- this.ownString = this.measure.updateOwnString(this, noteStringData.strings);
2441
- this.color = (_a = options == null ? void 0 : options.color) != null ? _a : "black";
2442
- this.staccato = (_b = options == null ? void 0 : options.staccato) != null ? _b : false;
2443
- this.diamond = (_c = options == null ? void 0 : options.diamond) != null ? _c : false;
2444
- this.arpeggio = getArpeggio(options == null ? void 0 : options.arpeggio);
2445
- this.oldStyleTriplet = tupletRatio === void 0 && ((options == null ? void 0 : options.triplet) === true || NoteLengthProps3.get(noteLength).isTriplet);
2446
- 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;
2447
- this.rhythmProps = RhythmProps3.get(noteLength, dotCount, (tupletRatio != null ? tupletRatio : this.oldStyleTriplet) ? Tuplet3.Triplet : void 0);
2448
- this.mi = new MNoteGroup(this);
2449
- }
2450
- getMusicInterface() {
2451
- return this.mi;
2452
- }
2453
- get doc() {
2454
- return this.col.doc;
2455
- }
2456
- get measure() {
2457
- return this.col.measure;
2458
- }
2459
- get row() {
2460
- return this.col.row;
2461
- }
2462
- get stemDir() {
2463
- return this.beamGroup ? this.beamGroup.stemDir : this.ownStemDir;
2464
- }
2465
- enableConnective(line) {
2466
- return line.containsVoiceId(this.voiceId) && (line instanceof ObjTab || line.containsDiatonicId(this.ownDiatonicId));
2467
- }
2468
- startConnective(connectiveProps) {
2469
- if (!this.row.hasStaff && connectiveProps.connective === "tie" /* Tie */) {
2470
- throw new MusicError7(MusicErrorType7.Score, "Ties not implemented for guitar tabs alone, staff is required!");
2471
- } else if (!this.row.hasStaff && connectiveProps.connective === "slur" /* Slur */) {
2472
- throw new MusicError7(MusicErrorType7.Score, "Slurs not implemented for guitar tabs alone, staff is required!");
2473
- }
2474
- this.startConnnectives.push(connectiveProps);
2475
- this.doc.addConnectiveProps(connectiveProps);
2476
- }
2477
- getStaticObjects(line) {
2478
- let staticObjects = [];
2479
- this.staffObjects.forEach((obj) => {
2480
- if (obj.staff === line) {
2481
- staticObjects.push(obj);
2482
- }
2483
- });
2484
- this.tabObjects.forEach((obj) => {
2485
- if (obj.tab === line) {
2486
- staticObjects.push(obj);
2487
- }
2488
- });
2489
- return staticObjects;
2490
- }
2491
- pick(x, y) {
2492
- if (!this.getRect().contains(x, y)) {
2493
- return [];
2494
- }
2495
- for (let i = 0; i < this.staffObjects.length; i++) {
2496
- let arr = this.staffObjects[i].pick(x, y);
2497
- if (arr.length > 0) {
2498
- return [this, ...arr];
2499
- }
2500
- }
2501
- for (let i = 0; i < this.tabObjects.length; i++) {
2502
- let arr = this.tabObjects[i].pick(x, y);
2503
- if (arr.length > 0) {
2504
- return [this, ...arr];
2505
- }
2506
- }
2507
- return [];
2508
- }
2509
- getTopNote() {
2510
- return this.notes[this.notes.length - 1];
2511
- }
2512
- getBottomNote() {
2513
- return this.notes[0];
2268
+ getBottomNote() {
2269
+ return this.notes[0];
2514
2270
  }
2515
2271
  getConnectiveAnchorPoint(connectiveProps, line, noteIndex, noteAnchor, side) {
2516
2272
  if (line instanceof ObjStaff) {
2517
2273
  let staff = line;
2518
2274
  if (noteIndex < 0 || noteIndex >= this.notes.length) {
2519
- throw new MusicError7(MusicErrorType7.Score, "Invalid noteIndex: " + noteIndex);
2275
+ throw new MusicError6(MusicErrorType6.Score, "Invalid noteIndex: " + noteIndex);
2520
2276
  }
2521
2277
  let obj = this.staffObjects.find((obj2) => obj2.staff === staff);
2522
2278
  if (!obj || noteIndex < 0 || noteIndex >= obj.noteHeadRects.length) {
@@ -2564,7 +2320,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2564
2320
  case "stemTip" /* StemTip */:
2565
2321
  return { x: centerX, y: stemTip.centerY + (stemDir === "up" /* Up */ ? -padding : padding) };
2566
2322
  default:
2567
- throw new MusicError7(MusicErrorType7.Score, "Invalid noteAnchor: " + noteAnchor);
2323
+ throw new MusicError6(MusicErrorType6.Score, "Invalid noteAnchor: " + noteAnchor);
2568
2324
  }
2569
2325
  } else {
2570
2326
  let tab = line;
@@ -2679,6 +2435,15 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2679
2435
  getRightBeamCount() {
2680
2436
  return this.rightBeamCount;
2681
2437
  }
2438
+ setLeftBeamCount(count) {
2439
+ this.leftBeamCount = count;
2440
+ }
2441
+ setRightBeamCount(count) {
2442
+ this.rightBeamCount = count;
2443
+ }
2444
+ hasTuplet() {
2445
+ return this.rhythmProps.tupletRatio !== void 0;
2446
+ }
2682
2447
  isEmpty() {
2683
2448
  return this.staffObjects.length === 0 && this.tabObjects.length === 0;
2684
2449
  }
@@ -2704,7 +2469,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2704
2469
  if (j >= 0) {
2705
2470
  tieNoteGroups = tieNoteGroups.slice(0, j);
2706
2471
  }
2707
- return Utils4.Math.sum(tieNoteGroups.map((ng) => ng.rhythmProps.ticks));
2472
+ return Utils3.Math.sum(tieNoteGroups.map((ng) => ng.rhythmProps.ticks));
2708
2473
  });
2709
2474
  return tiedTicks.length === 0 ? this.rhythmProps.ticks : Math.max(...tiedTicks);
2710
2475
  }
@@ -2903,95 +2668,10 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2903
2668
  ctx.lineTo(obj.stemTip.centerX, obj.stemTip.centerY);
2904
2669
  ctx.stroke();
2905
2670
  }
2906
- obj.flagRects.forEach((rect) => {
2907
- let left = rect.left;
2908
- let right = rect.right;
2909
- let width = right - left;
2910
- let top = stemDir === "up" /* Up */ ? rect.top : rect.bottom;
2911
- let bottom = stemDir === "up" /* Up */ ? rect.bottom : rect.top;
2912
- ctx.beginPath();
2913
- ctx.moveTo(left, top);
2914
- ctx.bezierCurveTo(
2915
- left,
2916
- top * 0.75 + bottom * 0.25,
2917
- left + width * 1.5,
2918
- top * 0.5 + bottom * 0.5,
2919
- left + width * 0.5,
2920
- bottom
2921
- );
2922
- ctx.stroke();
2923
- });
2671
+ obj.flagRects.forEach((rect) => renderer.drawFlag(rect, stemDir === "up" /* Up */ ? "up" : "down"));
2924
2672
  });
2925
2673
  this.tabObjects.forEach((obj) => obj.fretNumbers.forEach((fn) => fn.draw(renderer)));
2926
2674
  }
2927
- static setBeamCounts(groupNotes) {
2928
- const isADottedBHalf = (a, b) => {
2929
- let { flagCount: aFlagCount, noteSize: aNoteSize, dotCount: aDotCount } = a.rhythmProps;
2930
- let { flagCount: bFlagCount, noteSize: bNoteSize, dotCount: bDotCount } = b.rhythmProps;
2931
- return aFlagCount > 0 && bFlagCount > 0 && aDotCount > 0 && bDotCount === 0 && aNoteSize * Math.pow(2, aDotCount) === bNoteSize;
2932
- };
2933
- for (let i = 0; i < groupNotes.length; i++) {
2934
- let center = groupNotes[i];
2935
- let left = groupNotes[i - 1];
2936
- let right = groupNotes[i + 1];
2937
- if (center) {
2938
- center.leftBeamCount = 0;
2939
- center.rightBeamCount = 0;
2940
- if (left) {
2941
- if (left.rhythmProps.flagCount === center.rhythmProps.flagCount || isADottedBHalf(left, center) || isADottedBHalf(center, left)) {
2942
- center.leftBeamCount = center.rhythmProps.flagCount;
2943
- } else {
2944
- center.leftBeamCount = Math.min(left.rhythmProps.flagCount, center.rhythmProps.flagCount);
2945
- }
2946
- }
2947
- if (right) {
2948
- if (right.rhythmProps.flagCount === center.rhythmProps.flagCount || isADottedBHalf(right, center) || isADottedBHalf(center, right)) {
2949
- center.rightBeamCount = center.rhythmProps.flagCount;
2950
- } else {
2951
- center.rightBeamCount = Math.min(right.rhythmProps.flagCount, center.rhythmProps.flagCount);
2952
- }
2953
- }
2954
- }
2955
- }
2956
- let fixAgain;
2957
- do {
2958
- fixAgain = false;
2959
- for (let i = 0; i < groupNotes.length; i++) {
2960
- let center = groupNotes[i];
2961
- let left = groupNotes[i - 1];
2962
- let right = groupNotes[i + 1];
2963
- if (center && center.leftBeamCount !== center.rhythmProps.flagCount && center.rightBeamCount !== center.rhythmProps.flagCount) {
2964
- center.leftBeamCount = center.rightBeamCount = 0;
2965
- if (left && left.rightBeamCount > 0) {
2966
- left.rightBeamCount = 0;
2967
- fixAgain = true;
2968
- }
2969
- if (right && right.leftBeamCount > 0) {
2970
- right.leftBeamCount = 0;
2971
- fixAgain = true;
2972
- }
2973
- }
2974
- }
2975
- } while (fixAgain);
2976
- }
2977
- static setTupletBeamCounts(tuplet) {
2978
- let type = tuplet.getType();
2979
- let symbols = tuplet.getSymbols();
2980
- if (type === 1 /* TupletBeam */) {
2981
- symbols.forEach((s, i) => {
2982
- if (s instanceof _ObjNoteGroup) {
2983
- s.leftBeamCount = i === 0 ? 0 : s.rhythmProps.flagCount;
2984
- s.rightBeamCount = i === symbols.length - 1 ? 0 : s.rhythmProps.flagCount;
2985
- }
2986
- });
2987
- } else if (type === 2 /* TupletGroup */) {
2988
- symbols.forEach((s) => {
2989
- if (s instanceof _ObjNoteGroup) {
2990
- s.leftBeamCount = s.rightBeamCount = 0;
2991
- }
2992
- });
2993
- }
2994
- }
2995
2675
  getDotVerticalDisplacement(staff, diatonicId, stemDir) {
2996
2676
  if (staff.isLine(diatonicId)) {
2997
2677
  return stemDir === "up" /* Up */ ? -1 : 1;
@@ -3015,10 +2695,10 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
3015
2695
  };
3016
2696
 
3017
2697
  // src/score/engine/obj-rhythm-column.ts
3018
- import { MusicError as MusicError8, MusicErrorType as MusicErrorType8 } from "@tspro/web-music-score/core";
2698
+ import { MusicError as MusicError7, MusicErrorType as MusicErrorType7 } from "@tspro/web-music-score/core";
3019
2699
 
3020
2700
  // src/score/engine/obj-lyrics.ts
3021
- import { Utils as Utils5 } from "@tspro/ts-utils-lib";
2701
+ import { Utils as Utils4 } from "@tspro/ts-utils-lib";
3022
2702
  var LyricsContainer = class {
3023
2703
  constructor(col, lyricsLength) {
3024
2704
  this.col = col;
@@ -3045,7 +2725,7 @@ var ObjLyrics = class extends MusicObject {
3045
2725
  __publicField(this, "text");
3046
2726
  __publicField(this, "mi");
3047
2727
  let halign = (lyricsOptions == null ? void 0 : lyricsOptions.align) === "left" /* Left */ ? 0 : (lyricsOptions == null ? void 0 : lyricsOptions.align) === "right" /* Right */ ? 1 : 0.5;
3048
- this.hyphen = Utils5.Is.isEnumValue(lyricsOptions == null ? void 0 : lyricsOptions.hyphen, LyricsHyphen) ? lyricsOptions == null ? void 0 : lyricsOptions.hyphen : void 0;
2728
+ this.hyphen = Utils4.Is.isEnumValue(lyricsOptions == null ? void 0 : lyricsOptions.hyphen, LyricsHyphen) ? lyricsOptions == null ? void 0 : lyricsOptions.hyphen : void 0;
3049
2729
  this.text = new ObjText(this, { text: lyricsText, color: this.color, scale: 0.8 }, halign, 0);
3050
2730
  this.rect = new DivRect();
3051
2731
  this.mi = new MLyrics(this);
@@ -3098,11 +2778,11 @@ var ObjLyrics = class extends MusicObject {
3098
2778
 
3099
2779
  // src/score/engine/obj-rhythm-column.ts
3100
2780
  var noteHeadDataCompareFunc = (a, b) => {
3101
- let cmp2 = Note5.compareFunc(a.note, b.note);
3102
- if (cmp2 === 0) {
3103
- cmp2 = a.noteGroup.stemDir === b.noteGroup.stemDir ? 0 : a.noteGroup.stemDir === "up" /* Up */ ? 1 : -1;
2781
+ let cmp = Note5.compareFunc(a.note, b.note);
2782
+ if (cmp === 0) {
2783
+ cmp = a.noteGroup.stemDir === b.noteGroup.stemDir ? 0 : a.noteGroup.stemDir === "up" /* Up */ ? 1 : -1;
3104
2784
  }
3105
- return cmp2;
2785
+ return cmp;
3106
2786
  };
3107
2787
  var ObjRhythmColumn = class extends MusicObject {
3108
2788
  constructor(measure, positionTicks) {
@@ -3110,7 +2790,7 @@ var ObjRhythmColumn = class extends MusicObject {
3110
2790
  this.measure = measure;
3111
2791
  this.positionTicks = positionTicks;
3112
2792
  __publicField(this, "voiceSymbol", []);
3113
- __publicField(this, "lyricsContainers", []);
2793
+ __publicField(this, "lyricsContainerCache", /* @__PURE__ */ new Map());
3114
2794
  __publicField(this, "minDiatonicId");
3115
2795
  __publicField(this, "maxDiatonicId");
3116
2796
  __publicField(this, "staffMinDiatonicId", /* @__PURE__ */ new Map());
@@ -3140,7 +2820,7 @@ var ObjRhythmColumn = class extends MusicObject {
3140
2820
  if (colId >= 0 && colId < this.measure.getColumnCount()) {
3141
2821
  return this.measure.getColumn(colId + 1);
3142
2822
  } else {
3143
- throw new MusicError8(MusicErrorType8.Score, "Cannot get next column in measure because current column's id in mesure is invalid.");
2823
+ throw new MusicError7(MusicErrorType7.Score, "Cannot get next column in measure because current column's id in mesure is invalid.");
3144
2824
  }
3145
2825
  }
3146
2826
  /**
@@ -3236,18 +2916,20 @@ var ObjRhythmColumn = class extends MusicObject {
3236
2916
  getVoiceSymbol(voiceId) {
3237
2917
  return this.voiceSymbol[voiceId];
3238
2918
  }
3239
- getLyricsContainerDatas() {
3240
- return this.lyricsContainers;
3241
- }
3242
2919
  getLyricsContainer(verse, line, vpos, lyricsLength) {
3243
- let data = this.lyricsContainers.find((data2) => data2.verse === verse && data2.line === line && data2.vpos === vpos);
3244
- if (data === void 0 && lyricsLength !== void 0) {
3245
- data = { lyricsContainer: new LyricsContainer(this, validateNoteLength(lyricsLength)), verse, line, vpos };
3246
- this.lyricsContainers.push(data);
3247
- this.requestLayout();
3248
- this.requestRectUpdate();
2920
+ let vposMap = this.lyricsContainerCache.get(line);
2921
+ if (vposMap === void 0) {
2922
+ this.lyricsContainerCache.set(line, vposMap = /* @__PURE__ */ new Map());
3249
2923
  }
3250
- return data == null ? void 0 : data.lyricsContainer;
2924
+ let verseMap = vposMap.get(vpos);
2925
+ if (verseMap === void 0) {
2926
+ vposMap.set(vpos, verseMap = /* @__PURE__ */ new Map());
2927
+ }
2928
+ let lyricsContainer = verseMap.get(verse);
2929
+ if (lyricsContainer === void 0 && lyricsLength !== void 0) {
2930
+ verseMap.set(verse, lyricsContainer = new LyricsContainer(this, validateNoteLength2(lyricsLength)));
2931
+ }
2932
+ return lyricsContainer;
3251
2933
  }
3252
2934
  getMinWidth() {
3253
2935
  let maxNoteSize = Math.max(...this.voiceSymbol.map((s) => s.rhythmProps.noteSize));
@@ -3465,10 +3147,10 @@ var ObjRhythmColumn = class extends MusicObject {
3465
3147
  };
3466
3148
 
3467
3149
  // src/score/engine/extension.ts
3468
- import { MusicError as MusicError9, MusicErrorType as MusicErrorType9 } from "@tspro/web-music-score/core";
3150
+ import { MusicError as MusicError8, MusicErrorType as MusicErrorType8 } from "@tspro/web-music-score/core";
3469
3151
 
3470
3152
  // src/score/engine/element-data.ts
3471
- import { Utils as Utils6 } from "@tspro/ts-utils-lib";
3153
+ import { Utils as Utils5 } from "@tspro/ts-utils-lib";
3472
3154
 
3473
3155
  // src/score/engine/obj-special-text.ts
3474
3156
  var _ObjSpecialText = class _ObjSpecialText extends MusicObject {
@@ -3590,23 +3272,23 @@ function getNavigationString(navigation) {
3590
3272
  }
3591
3273
  }
3592
3274
  function isDynamicsText(text) {
3593
- return Utils6.Is.isEnumValue(text, DynamicsAnnotation);
3275
+ return Utils5.Is.isEnumValue(text, DynamicsAnnotation);
3594
3276
  }
3595
3277
  function getDynamicsVolume(text) {
3596
3278
  if (/^(p+|f+|m|mp|mf)$/.test(text)) {
3597
- let volume = 0.5 - Utils6.Str.charCount(text, "p") * 0.1 + Utils6.Str.charCount(text, "f") * 0.1;
3598
- return Utils6.Math.clamp(volume, 0, 1);
3279
+ let volume = 0.5 - Utils5.Str.charCount(text, "p") * 0.1 + Utils5.Str.charCount(text, "f") * 0.1;
3280
+ return Utils5.Math.clamp(volume, 0, 1);
3599
3281
  } else {
3600
3282
  return void 0;
3601
3283
  }
3602
3284
  }
3603
3285
  function isTempoText(text) {
3604
- return Utils6.Is.isEnumValue(text, TempoAnnotation);
3286
+ return Utils5.Is.isEnumValue(text, TempoAnnotation);
3605
3287
  }
3606
3288
  function getAnnotation(text) {
3607
- if (Utils6.Is.isEnumValue(text, DynamicsAnnotation)) {
3289
+ if (Utils5.Is.isEnumValue(text, DynamicsAnnotation)) {
3608
3290
  return "dynamics" /* Dynamics */;
3609
- } else if (Utils6.Is.isEnumValue(text, TempoAnnotation)) {
3291
+ } else if (Utils5.Is.isEnumValue(text, TempoAnnotation)) {
3610
3292
  return "tempo" /* Tempo */;
3611
3293
  } else {
3612
3294
  return void 0;
@@ -3649,7 +3331,7 @@ var Extension = class extends MusicObjectLink {
3649
3331
  if (head instanceof ObjText) {
3650
3332
  head.updateAnchorY(getTextAnchorY(linePos));
3651
3333
  } else {
3652
- throw new MusicError9(MusicErrorType9.Score, "Update anchor's y-coordinate is only implemented for text objects.");
3334
+ throw new MusicError8(MusicErrorType8.Score, "Update anchor's y-coordinate is only implemented for text objects.");
3653
3335
  }
3654
3336
  }
3655
3337
  isVisible() {
@@ -3762,7 +3444,7 @@ var PlayerColumnProps = class {
3762
3444
  return this.speed;
3763
3445
  }
3764
3446
  getTempo() {
3765
- let speed = Utils7.Math.clamp(this.getSpeed(), 0.1, 10);
3447
+ let speed = Utils6.Math.clamp(this.getSpeed(), 0.1, 10);
3766
3448
  return alterTempoSpeed(this.measure.getTempo(), speed);
3767
3449
  }
3768
3450
  setVolume(volume) {
@@ -3787,7 +3469,7 @@ var PlayerColumnProps = class {
3787
3469
  if (symbolsTicks.length === 0) {
3788
3470
  return 0;
3789
3471
  } else {
3790
- return Utils7.Math.sum(symbolsTicks) / symbolsTicks.length;
3472
+ return Utils6.Math.sum(symbolsTicks) / symbolsTicks.length;
3791
3473
  }
3792
3474
  }
3793
3475
  }
@@ -3936,7 +3618,7 @@ var Player = class _Player {
3936
3618
  } else if (layoutObj.musicObj.getLink() instanceof Extension) {
3937
3619
  let extension = layoutObj.musicObj.getLink();
3938
3620
  let { columnRange, extensionBreakText } = extension.getExtensionRangeInfo();
3939
- let totalTicks = Utils7.Math.sum(columnRange.map((c) => c.getTicksToNextColumn()));
3621
+ let totalTicks = Utils6.Math.sum(columnRange.map((c) => c.getTicksToNextColumn()));
3940
3622
  switch (text) {
3941
3623
  case "accel." /* accel */: {
3942
3624
  let startSpeed = curSpeed;
@@ -3990,11 +3672,11 @@ var Player = class _Player {
3990
3672
  });
3991
3673
  let speedArr = (_a = speedMap.get(col)) != null ? _a : [];
3992
3674
  if (speedArr.length > 0) {
3993
- curSpeed = Utils7.Math.sum(speedArr) / speedArr.length;
3675
+ curSpeed = Utils6.Math.sum(speedArr) / speedArr.length;
3994
3676
  }
3995
3677
  let volumeArr = (_b = volumeMap.get(col)) != null ? _b : [];
3996
3678
  if (volumeArr.length > 0) {
3997
- curVolume = Utils7.Math.sum(volumeArr) / volumeArr.length;
3679
+ curVolume = Utils6.Math.sum(volumeArr) / volumeArr.length;
3998
3680
  }
3999
3681
  col.getPlayerProps().setSpeed(curSpeed);
4000
3682
  col.getPlayerProps().setVolume(curVolume);
@@ -4020,6 +3702,10 @@ var Player = class _Player {
4020
3702
  return;
4021
3703
  }
4022
3704
  const col = this.playerColumnSequence[this.playPos];
3705
+ if (!col) {
3706
+ this.stop();
3707
+ return;
3708
+ }
4023
3709
  const getDuration = (ticks, tempo2) => {
4024
3710
  let seconds = calcTicksDuration(ticks, tempo2);
4025
3711
  return Math.max(0, seconds);
@@ -4104,6 +3790,9 @@ var Player = class _Player {
4104
3790
  return void 0;
4105
3791
  }
4106
3792
  let col = this.playerColumnSequence[this.playPos];
3793
+ if (!col) {
3794
+ return void 0;
3795
+ }
4107
3796
  let measure = col.measure;
4108
3797
  let x = col.getRect().centerX;
4109
3798
  let top = measure.row.getRect().top;
@@ -4268,146 +3957,676 @@ var ObjBarLineLeft = class extends ObjBarLine {
4268
3957
  __publicField(this, "mi");
4269
3958
  this.mi = new MBarLineLeft(this);
4270
3959
  }
4271
- getMusicInterface() {
4272
- return this.mi;
3960
+ getMusicInterface() {
3961
+ return this.mi;
3962
+ }
3963
+ solveBarLineType() {
3964
+ let m = this.measure;
3965
+ let prev = m.getPrevMeasure();
3966
+ if (m.hasNavigation("startRepeat" /* StartRepeat */)) {
3967
+ if (prev && prev.row === m.row && prev.hasNavigation("endRepeat" /* EndRepeat */)) {
3968
+ return 0 /* None */;
3969
+ } else {
3970
+ return 4 /* StartRepeat */;
3971
+ }
3972
+ } else {
3973
+ return 0 /* None */;
3974
+ }
3975
+ }
3976
+ };
3977
+ var ObjBarLineRight = class extends ObjBarLine {
3978
+ constructor(measure) {
3979
+ super(measure);
3980
+ __publicField(this, "playerProps");
3981
+ __publicField(this, "mi");
3982
+ this.playerProps = new PlayerColumnProps(this);
3983
+ this.mi = new MBarLineRight(this);
3984
+ }
3985
+ getMusicInterface() {
3986
+ return this.mi;
3987
+ }
3988
+ getPlayerProps() {
3989
+ return this.playerProps;
3990
+ }
3991
+ solveBarLineType() {
3992
+ let m = this.measure;
3993
+ let next = m.getNextMeasure();
3994
+ if (m.hasNavigation("endRepeat" /* EndRepeat */)) {
3995
+ if (next && next.row === m.row && next.hasNavigation("startRepeat" /* StartRepeat */)) {
3996
+ return 6 /* EndStartRepeat */;
3997
+ } else {
3998
+ return 5 /* EndRepeat */;
3999
+ }
4000
+ } else if (!m.doc.hasSingleMeasure() && (m.hasEndSong() || !m.getNextMeasure())) {
4001
+ return 3 /* EndSong */;
4002
+ } else if (m.hasEndSection()) {
4003
+ return 2 /* Double */;
4004
+ }
4005
+ if (m === m.row.getLastMeasure() && next && next.row === m.row.getNextRow() && next.hasNavigation("startRepeat" /* StartRepeat */)) {
4006
+ return 2 /* Double */;
4007
+ }
4008
+ if (next && next.hasNavigation("startRepeat" /* StartRepeat */)) {
4009
+ return 0 /* None */;
4010
+ }
4011
+ return 1 /* Single */;
4012
+ }
4013
+ };
4014
+
4015
+ // src/score/engine/obj-ending.ts
4016
+ import { Utils as Utils7 } from "@tspro/ts-utils-lib";
4017
+ import { MusicError as MusicError9, MusicErrorType as MusicErrorType9 } from "@tspro/web-music-score/core";
4018
+ var ObjEnding = class extends MusicObject {
4019
+ constructor(measure, passages) {
4020
+ super(measure);
4021
+ this.measure = measure;
4022
+ this.passages = passages;
4023
+ __publicField(this, "endingText");
4024
+ __publicField(this, "shapeRects", []);
4025
+ __publicField(this, "mi");
4026
+ this.mi = new MEnding(this);
4027
+ if (!Utils7.Is.isIntegerGte(passages.length, 1)) {
4028
+ throw new MusicError9(MusicErrorType9.Score, "Passages is empty.");
4029
+ } else if (!this.passages.every((p) => Utils7.Is.isIntegerGte(p, 1))) {
4030
+ throw new MusicError9(MusicErrorType9.Score, "Invalid passages: " + this.passages);
4031
+ }
4032
+ this.passages.sort((a, b) => a - b);
4033
+ let text = this.passages.map((p) => p + ".").join("");
4034
+ this.endingText = new ObjText(this, text, 0, 1);
4035
+ }
4036
+ getMusicInterface() {
4037
+ return this.mi;
4038
+ }
4039
+ getShapeRects() {
4040
+ return this.shapeRects;
4041
+ }
4042
+ isSingleMeasureEnding() {
4043
+ let { measure } = this;
4044
+ let next = measure.getNextMeasure();
4045
+ return (next == null ? void 0 : next.hasNavigation("ending" /* Ending */)) === true || measure.hasNavigation("endRepeat" /* EndRepeat */) || measure.isLastMeasure();
4046
+ }
4047
+ hasPassage(pass) {
4048
+ return this.passages.some((p) => p === pass);
4049
+ }
4050
+ getHighestPassage() {
4051
+ return Math.max(0, ...this.passages);
4052
+ }
4053
+ pick(x, y) {
4054
+ return this.rect.contains(x, y) ? [this] : [];
4055
+ }
4056
+ layout(renderer) {
4057
+ this.rect = new DivRect();
4058
+ this.shapeRects = [this.rect.copy()];
4059
+ }
4060
+ layoutFitToMeasure(renderer) {
4061
+ let { unitSize } = renderer;
4062
+ let { measure } = this;
4063
+ this.endingText.layout(renderer);
4064
+ let textRect = this.endingText.getRect();
4065
+ let measureContent = measure.getColumnsContentRect();
4066
+ let endingHeight = textRect.height;
4067
+ this.rect = new DivRect(measureContent.left + unitSize, measureContent.right - unitSize, -endingHeight, 0);
4068
+ this.endingText.offset(this.rect.left + unitSize / 2, this.rect.bottom);
4069
+ this.shapeRects = [
4070
+ new DivRect(this.rect.left, this.rect.left + 1, this.rect.top, this.rect.bottom),
4071
+ new DivRect(this.rect.left, this.rect.right, this.rect.top, this.rect.top + 1),
4072
+ new DivRect(this.rect.right - 1, this.rect.right, this.rect.top, this.rect.bottom),
4073
+ this.endingText.getRect().copy()
4074
+ ];
4075
+ }
4076
+ offset(dx, dy) {
4077
+ this.endingText.offset(dx, dy);
4078
+ this.shapeRects.forEach((r) => r.offsetInPlace(dx, dy));
4079
+ this.rect.offsetInPlace(dx, dy);
4080
+ }
4081
+ draw(renderer) {
4082
+ let ctx = renderer.getCanvasContext();
4083
+ if (!ctx) {
4084
+ return;
4085
+ }
4086
+ let { lineWidth } = renderer;
4087
+ let { rect } = this;
4088
+ renderer.drawDebugRect(this.rect);
4089
+ ctx.strokeStyle = ctx.fillStyle = "black";
4090
+ ctx.lineWidth = lineWidth;
4091
+ ctx.beginPath();
4092
+ ctx.moveTo(rect.left, rect.bottom);
4093
+ ctx.lineTo(rect.left, rect.top);
4094
+ ctx.lineTo(rect.right, rect.top);
4095
+ if (this.isSingleMeasureEnding()) {
4096
+ ctx.lineTo(rect.right, rect.bottom);
4097
+ }
4098
+ ctx.stroke();
4099
+ this.endingText.draw(renderer);
4100
+ }
4101
+ };
4102
+
4103
+ // src/score/engine/obj-beam-group.ts
4104
+ import { Utils as Utils8 } from "@tspro/ts-utils-lib";
4105
+ import { NoteLength as NoteLength7, Tuplet as Tuplet3, NoteLengthProps as NoteLengthProps4 } from "@tspro/web-music-score/theory";
4106
+ import { MusicError as MusicError10, MusicErrorType as MusicErrorType10 } from "@tspro/web-music-score/core";
4107
+ var adjustBeamAngle = (dx, dy) => {
4108
+ let T = DocumentSettings.BeamAngleFactor;
4109
+ if (!Number.isFinite(T) || T === 0) {
4110
+ return dy;
4111
+ } else {
4112
+ let k = dx / dy / T;
4113
+ k = Math.sign(k) * Math.sqrt(Math.abs(k));
4114
+ return dx / k * T;
4115
+ }
4116
+ };
4117
+ var BeamPoint = class {
4118
+ constructor(staff, beamGroup, symbol, x, y) {
4119
+ this.staff = staff;
4120
+ this.beamGroup = beamGroup;
4121
+ this.symbol = symbol;
4122
+ this.x = x;
4123
+ this.y = y;
4124
+ __publicField(this, "topBeamsHeight", 0);
4125
+ __publicField(this, "bottomBeamsHeight", 0);
4126
+ staff.addObject(this);
4127
+ }
4128
+ offset(dx, dy) {
4129
+ this.x += dx;
4130
+ this.y += dy;
4131
+ this.beamGroup.requestRectUpdate();
4132
+ }
4133
+ getRect() {
4134
+ return new DivRect(this.x, this.x, this.x, this.y - this.topBeamsHeight, this.y, this.y + this.bottomBeamsHeight);
4135
+ }
4136
+ };
4137
+ var ObjStaffBeamGroup = class extends MusicObject {
4138
+ constructor(staff, beamGroup) {
4139
+ super(staff);
4140
+ this.staff = staff;
4141
+ this.beamGroup = beamGroup;
4142
+ __publicField(this, "tupletNumber");
4143
+ __publicField(this, "tupletNumberOffsetY", 0);
4144
+ __publicField(this, "points", []);
4145
+ __publicField(this, "mi");
4146
+ staff.addObject(this);
4147
+ this.mi = new MStaffBeamGroup(this);
4148
+ }
4149
+ getMusicInterface() {
4150
+ return this.mi;
4151
+ }
4152
+ pick(x, y) {
4153
+ return this.getRect().contains(x, y) ? [this] : [];
4154
+ }
4155
+ offset(dx, dy) {
4156
+ var _a;
4157
+ this.points.forEach((p) => p.offset(dx, 0));
4158
+ (_a = this.tupletNumber) == null ? void 0 : _a.offset(dx, dy);
4159
+ this.requestRectUpdate();
4160
+ this.beamGroup.requestRectUpdate();
4161
+ }
4162
+ updateRect() {
4163
+ if (this.points.length > 0) {
4164
+ this.rect = this.points[0].getRect().copy();
4165
+ } else if (this.tupletNumber) {
4166
+ this.rect = this.tupletNumber.getRect().copy();
4167
+ }
4168
+ this.points.forEach((pt) => this.rect.expandInPlace(pt.getRect()));
4169
+ if (this.tupletNumber) {
4170
+ this.rect.expandInPlace(this.tupletNumber.getRect());
4171
+ }
4172
+ }
4173
+ };
4174
+ var InvalidBeamGroup = class {
4175
+ constructor(beamGroup, message) {
4176
+ this.beamGroup = beamGroup;
4177
+ this.message = message;
4178
+ }
4179
+ };
4180
+ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
4181
+ constructor(symbols, tupletRatio) {
4182
+ super(symbols[0].measure);
4183
+ this.symbols = symbols;
4184
+ this.tupletRatio = tupletRatio;
4185
+ __publicField(this, "mi");
4186
+ __publicField(this, "type");
4187
+ __publicField(this, "staffObjects", []);
4188
+ this.mi = new MBeamGroup(this);
4189
+ let beamGroupName = tupletRatio ? "Tuplet" : "BeamGroup";
4190
+ if (!symbols.every((s) => s.measure === symbols[0].measure)) {
4191
+ throw new MusicError10(MusicErrorType10.Score, `All ${beamGroupName} symbols are not in same measure.`);
4192
+ } else if (symbols.length < 2) {
4193
+ throw new MusicError10(MusicErrorType10.Score, `${beamGroupName} needs minimum 2 symbols, but ${symbols.length} given.`);
4194
+ }
4195
+ if (tupletRatio !== void 0) {
4196
+ let isGroup = symbols.length < 3 || symbols.some((s) => !(s instanceof ObjNoteGroup)) || symbols.some((s) => s.rhythmProps.flagCount !== symbols[0].rhythmProps.flagCount);
4197
+ if (symbols.length >= 3 && symbols[0] instanceof ObjNoteGroup && symbols[symbols.length - 1] instanceof ObjNoteGroup && symbols[0].rhythmProps.flagCount === symbols[symbols.length - 1].rhythmProps.flagCount) {
4198
+ isGroup = false;
4199
+ }
4200
+ if (symbols.some((s) => NoteLengthProps4.cmp(s.rhythmProps.noteLength, NoteLength7.Quarter) >= 0)) {
4201
+ isGroup = true;
4202
+ }
4203
+ this.type = isGroup ? 2 /* TupletGroup */ : 1 /* TupletBeam */;
4204
+ this.setTupletBeamCounts();
4205
+ } else {
4206
+ this.type = 0 /* RegularBeam */;
4207
+ this.setBeamCounts();
4208
+ }
4209
+ if (symbols.every((s) => s.getBeamGroup() === void 0)) {
4210
+ symbols.forEach((s) => s.setBeamGroup(this));
4211
+ symbols[0].measure.addBeamGroup(this);
4212
+ } else {
4213
+ throw new MusicError10(MusicErrorType10.Score, `Cannot add ${beamGroupName} because some symbol already has one.`);
4214
+ }
4215
+ if (this.type === 0 /* RegularBeam */) {
4216
+ this.symbols.filter((sym) => sym instanceof ObjNoteGroup).some((sym, i) => {
4217
+ let first = i === 0;
4218
+ let last = i === this.symbols.length - 1;
4219
+ if (first && sym.getRightBeamCount() === 0 || last && sym.getLeftBeamCount() === 0 || !first && !last && (sym.getLeftBeamCount() === 0 || sym.getRightBeamCount() === 0)) {
4220
+ throw new InvalidBeamGroup(this, "Beam has zero left or right beam count!");
4221
+ }
4222
+ });
4223
+ }
4224
+ if (symbols.some((symbol) => symbol.voiceId !== symbols[0].voiceId)) {
4225
+ if (this.type === 0 /* RegularBeam */) {
4226
+ throw new InvalidBeamGroup(this, "Beam symbols have different voiceId.");
4227
+ } else {
4228
+ throw new MusicError10(MusicErrorType10.Score, `Tuplet symbols have different voiceId.`);
4229
+ }
4230
+ }
4231
+ symbols[0].row.getStaves().forEach((staff) => {
4232
+ if (staff.getActualStaff(symbols[0].ownDiatonicId) && staff.containsVoiceId(symbols[0].voiceId)) {
4233
+ symbols.forEach((sym) => {
4234
+ let actualStaff = staff.getActualStaff(sym.ownDiatonicId);
4235
+ if (!actualStaff || !actualStaff.containsVoiceId(sym.voiceId)) {
4236
+ throw new InvalidBeamGroup(this, "Some of beam or tuplet symbols are not visible!");
4237
+ }
4238
+ });
4239
+ }
4240
+ });
4241
+ }
4242
+ get showTupletRatio() {
4243
+ var _a;
4244
+ return ((_a = this.tupletRatio) == null ? void 0 : _a.showRatio) === true;
4273
4245
  }
4274
- solveBarLineType() {
4275
- let m = this.measure;
4276
- let prev = m.getPrevMeasure();
4277
- if (m.hasNavigation("startRepeat" /* StartRepeat */)) {
4278
- if (prev && prev.row === m.row && prev.hasNavigation("endRepeat" /* EndRepeat */)) {
4279
- return 0 /* None */;
4246
+ static createBeam(noteGroups) {
4247
+ if (noteGroups.length > 1 && noteGroups.every((ng) => !ng.hasTuplet())) {
4248
+ try {
4249
+ new _ObjBeamGroup(noteGroups, void 0);
4250
+ return true;
4251
+ } catch (err) {
4252
+ if (err instanceof InvalidBeamGroup) {
4253
+ err.beamGroup.detach();
4254
+ } else {
4255
+ throw err;
4256
+ }
4257
+ }
4258
+ }
4259
+ return false;
4260
+ }
4261
+ static createOldStyleTriplet(symbols) {
4262
+ try {
4263
+ let s2 = symbols.slice(0, 2);
4264
+ let n2 = s2.map((s) => s.rhythmProps.noteSize);
4265
+ if (s2.length === 2 && s2.every((s) => s.oldStyleTriplet && s.getBeamGroup() === void 0) && (n2[0] * 2 === n2[1] || n2[1] * 2 === n2[0])) {
4266
+ new _ObjBeamGroup(s2, Tuplet3.Triplet);
4267
+ return 2;
4268
+ }
4269
+ let s3 = symbols.slice(0, 3);
4270
+ let n3 = s3.map((s) => s.rhythmProps.noteSize);
4271
+ if (s3.length === 3 && s3.every((s) => s.oldStyleTriplet && s.getBeamGroup() === void 0) && n3.every((n) => n === n3[0])) {
4272
+ new _ObjBeamGroup(s3, Tuplet3.Triplet);
4273
+ return 3;
4274
+ }
4275
+ } catch (err) {
4276
+ if (err instanceof InvalidBeamGroup) {
4277
+ console.error(err.message);
4278
+ err.beamGroup.detach();
4280
4279
  } else {
4281
- return 4 /* StartRepeat */;
4280
+ throw err;
4282
4281
  }
4283
- } else {
4284
- return 0 /* None */;
4285
4282
  }
4283
+ return 0;
4286
4284
  }
4287
- };
4288
- var ObjBarLineRight = class extends ObjBarLine {
4289
- constructor(measure) {
4290
- super(measure);
4291
- __publicField(this, "playerProps");
4292
- __publicField(this, "mi");
4293
- this.playerProps = new PlayerColumnProps(this);
4294
- this.mi = new MBarLineRight(this);
4285
+ static createTuplet(symbols, tupletRatio) {
4286
+ try {
4287
+ new _ObjBeamGroup(symbols, tupletRatio);
4288
+ } catch (err) {
4289
+ if (err instanceof InvalidBeamGroup) {
4290
+ console.error(err.message);
4291
+ err.beamGroup.detach();
4292
+ } else {
4293
+ throw err;
4294
+ }
4295
+ }
4295
4296
  }
4296
4297
  getMusicInterface() {
4297
4298
  return this.mi;
4298
4299
  }
4299
- getPlayerProps() {
4300
- return this.playerProps;
4300
+ detach() {
4301
+ this.getSymbols().forEach((s) => s.resetBeamGroup());
4301
4302
  }
4302
- solveBarLineType() {
4303
- let m = this.measure;
4304
- let next = m.getNextMeasure();
4305
- if (m.hasNavigation("endRepeat" /* EndRepeat */)) {
4306
- if (next && next.row === m.row && next.hasNavigation("startRepeat" /* StartRepeat */)) {
4307
- return 6 /* EndStartRepeat */;
4308
- } else {
4309
- return 5 /* EndRepeat */;
4310
- }
4311
- } else if (!m.doc.hasSingleMeasure() && (m.hasEndSong() || !m.getNextMeasure())) {
4312
- return 3 /* EndSong */;
4313
- } else if (m.hasEndSection()) {
4314
- return 2 /* Double */;
4315
- }
4316
- if (m === m.row.getLastMeasure() && next && next.row === m.row.getNextRow() && next.hasNavigation("startRepeat" /* StartRepeat */)) {
4317
- return 2 /* Double */;
4303
+ isEmpty() {
4304
+ return this.staffObjects.length === 0;
4305
+ }
4306
+ pick(x, y) {
4307
+ if (!this.getRect().contains(x, y)) {
4308
+ return [];
4318
4309
  }
4319
- if (next && next.hasNavigation("startRepeat" /* StartRepeat */)) {
4320
- return 0 /* None */;
4310
+ for (let i = 0; i < this.staffObjects.length; i++) {
4311
+ let arr = this.staffObjects[i].pick(x, y);
4312
+ if (arr.length > 0) {
4313
+ return [this, ...arr];
4314
+ }
4321
4315
  }
4322
- return 1 /* Single */;
4316
+ return [this];
4323
4317
  }
4324
- };
4325
-
4326
- // src/score/engine/obj-ending.ts
4327
- import { Utils as Utils8 } from "@tspro/ts-utils-lib";
4328
- import { MusicError as MusicError10, MusicErrorType as MusicErrorType10 } from "@tspro/web-music-score/core";
4329
- var ObjEnding = class extends MusicObject {
4330
- constructor(measure, passages) {
4331
- super(measure);
4332
- this.measure = measure;
4333
- this.passages = passages;
4334
- __publicField(this, "endingText");
4335
- __publicField(this, "shapeRects", []);
4336
- __publicField(this, "mi");
4337
- this.mi = new MEnding(this);
4338
- if (!Utils8.Is.isIntegerGte(passages.length, 1)) {
4339
- throw new MusicError10(MusicErrorType10.Score, "Passages is empty.");
4340
- } else if (!this.passages.every((p) => Utils8.Is.isIntegerGte(p, 1))) {
4341
- throw new MusicError10(MusicErrorType10.Score, "Invalid passages: " + this.passages);
4342
- }
4343
- this.passages.sort((a, b) => a - b);
4344
- let text = this.passages.map((p) => p + ".").join("");
4345
- this.endingText = new ObjText(this, text, 0, 1);
4318
+ getType() {
4319
+ return this.type;
4346
4320
  }
4347
- getMusicInterface() {
4348
- return this.mi;
4321
+ isTuplet() {
4322
+ return this.type === 1 /* TupletBeam */ || this.type === 2 /* TupletGroup */;
4349
4323
  }
4350
- getShapeRects() {
4351
- return this.shapeRects;
4324
+ getTupletRatioText() {
4325
+ var _a, _b, _c;
4326
+ return this.showTupletRatio ? String((_a = this.tupletRatio) == null ? void 0 : _a.parts) + ":" + String((_b = this.tupletRatio) == null ? void 0 : _b.inTimeOf) : String((_c = this.tupletRatio) == null ? void 0 : _c.parts);
4352
4327
  }
4353
- isSingleMeasureEnding() {
4354
- let { measure } = this;
4355
- let next = measure.getNextMeasure();
4356
- return (next == null ? void 0 : next.hasNavigation("ending" /* Ending */)) === true || measure.hasNavigation("endRepeat" /* EndRepeat */) || measure.isLastMeasure();
4328
+ getSymbols() {
4329
+ return this.symbols;
4357
4330
  }
4358
- hasPassage(pass) {
4359
- return this.passages.some((p) => p === pass);
4331
+ getFirstSymbol() {
4332
+ return this.symbols[0];
4360
4333
  }
4361
- getHighestPassage() {
4362
- return Math.max(0, ...this.passages);
4334
+ getLastSymbol() {
4335
+ return this.symbols[this.symbols.length - 1];
4363
4336
  }
4364
- pick(x, y) {
4365
- return this.rect.contains(x, y) ? [this] : [];
4337
+ get stemDir() {
4338
+ return this.symbols[0].ownStemDir;
4366
4339
  }
4367
- layout(renderer) {
4368
- this.rect = new DivRect();
4369
- this.shapeRects = [this.rect.copy()];
4340
+ get color() {
4341
+ return this.symbols[0].color;
4370
4342
  }
4371
- layoutFitToMeasure(renderer) {
4343
+ layout(renderer) {
4344
+ this.requestRectUpdate();
4345
+ this.staffObjects.length = 0;
4346
+ let symbols = this.getSymbols();
4347
+ if (symbols.length === 0) {
4348
+ return;
4349
+ }
4372
4350
  let { unitSize } = renderer;
4373
- let { measure } = this;
4374
- this.endingText.layout(renderer);
4375
- let textRect = this.endingText.getRect();
4376
- let measureContent = measure.getColumnsContentRect();
4377
- let endingHeight = textRect.height;
4378
- this.rect = new DivRect(measureContent.left + unitSize, measureContent.right - unitSize, -endingHeight, 0);
4379
- this.endingText.offset(this.rect.left + unitSize / 2, this.rect.bottom);
4380
- this.shapeRects = [
4381
- new DivRect(this.rect.left, this.rect.left + 1, this.rect.top, this.rect.bottom),
4382
- new DivRect(this.rect.left, this.rect.right, this.rect.top, this.rect.top + 1),
4383
- new DivRect(this.rect.right - 1, this.rect.right, this.rect.top, this.rect.bottom),
4384
- this.endingText.getRect().copy()
4385
- ];
4351
+ let { stemDir, type } = this;
4352
+ let symbolsBeamCoords = symbols.map((s) => s.getBeamCoords());
4353
+ symbolsBeamCoords[0].map((s) => s == null ? void 0 : s.staff).forEach((mainStaff, index) => {
4354
+ var _a, _b;
4355
+ if (!mainStaff) {
4356
+ return;
4357
+ }
4358
+ let symbolX = symbolsBeamCoords.map((s) => {
4359
+ var _a2;
4360
+ return (_a2 = s[index]) == null ? void 0 : _a2.x;
4361
+ });
4362
+ let symbolY = symbolsBeamCoords.map((s) => {
4363
+ var _a2;
4364
+ return (_a2 = s[index]) == null ? void 0 : _a2.y;
4365
+ });
4366
+ let symbolStaff = symbolsBeamCoords.map((s) => {
4367
+ var _a2;
4368
+ return (_a2 = s[index]) == null ? void 0 : _a2.staff;
4369
+ });
4370
+ let symbolStemHeight = symbolsBeamCoords.map((s) => {
4371
+ var _a2;
4372
+ return (_a2 = s[index]) == null ? void 0 : _a2.stemHeight;
4373
+ });
4374
+ let leftSymbol = symbols[0];
4375
+ let leftX = symbolX[0];
4376
+ let leftY = symbolY[0];
4377
+ let leftStaff = symbolStaff[0];
4378
+ let rightSymbol = symbols[symbols.length - 1];
4379
+ let rightX = symbolX[symbolX.length - 1];
4380
+ let rightY = symbolY[symbolY.length - 1];
4381
+ let rightStaff = symbolStaff[symbolY.length - 1];
4382
+ if (leftX === void 0 || leftY === void 0 || leftStaff === void 0 || rightX === void 0 || rightY === void 0 || rightStaff === void 0) {
4383
+ return;
4384
+ }
4385
+ let leftStemHeight = (_a = symbolStemHeight[0]) != null ? _a : 0;
4386
+ let rightStemHeight = (_b = symbolStemHeight[symbolStemHeight.length - 1]) != null ? _b : 0;
4387
+ if (type !== 2 /* TupletGroup */) {
4388
+ let leftDy = leftStemHeight < rightStemHeight ? Math.sqrt(rightStemHeight - leftStemHeight) : 0;
4389
+ let rightDy = rightStemHeight < leftStemHeight ? Math.sqrt(leftStemHeight - rightStemHeight) : 0;
4390
+ if (stemDir === "up" /* Up */) {
4391
+ leftDy *= -1;
4392
+ rightDy *= -1;
4393
+ }
4394
+ if (leftDy !== 0) {
4395
+ leftY += leftDy;
4396
+ symbolY[0] += leftDy;
4397
+ }
4398
+ if (rightDy !== 0) {
4399
+ rightY += rightDy;
4400
+ symbolY[symbolY.length - 1] += rightDy;
4401
+ }
4402
+ }
4403
+ let groupLineDy = unitSize * 2 * (stemDir === "up" /* Up */ ? -1 : 1);
4404
+ let centerY = (rightY + leftY) / 2;
4405
+ let halfDy = adjustBeamAngle(rightX - leftX, rightY - leftY) / 2;
4406
+ leftY = centerY - halfDy;
4407
+ rightY = centerY + halfDy;
4408
+ let raiseBeamY = 0;
4409
+ symbolY.forEach((symY, i) => {
4410
+ let symX = symbolX[i];
4411
+ if (symX !== void 0 && symY !== void 0) {
4412
+ let beamY = Utils8.Math.interpolateY(leftX, leftY, rightX, rightY, symX);
4413
+ let raiseY = symY - beamY;
4414
+ if (stemDir === "up" /* Up */ && raiseY < 0) {
4415
+ raiseBeamY = Math.min(raiseBeamY, raiseY);
4416
+ } else if (stemDir === "down" /* Down */ && raiseY > 0) {
4417
+ raiseBeamY = Math.max(raiseBeamY, raiseY);
4418
+ }
4419
+ }
4420
+ });
4421
+ leftY += raiseBeamY;
4422
+ rightY += raiseBeamY;
4423
+ symbolY = symbolY.map((y) => y === void 0 ? void 0 : y + raiseBeamY);
4424
+ let obj = new ObjStaffBeamGroup(mainStaff, this);
4425
+ if (type === 2 /* TupletGroup */) {
4426
+ let ef = unitSize / (rightX - leftX);
4427
+ let l = Utils8.Math.interpolateCoord(leftX, leftY + groupLineDy, rightX, rightY + groupLineDy, -ef);
4428
+ let r = Utils8.Math.interpolateCoord(leftX, leftY + groupLineDy, rightX, rightY + groupLineDy, 1 + ef);
4429
+ obj.points.push(new BeamPoint(leftStaff, this, leftSymbol, l.x, l.y));
4430
+ obj.points.push(new BeamPoint(rightStaff, this, rightSymbol, r.x, r.y));
4431
+ obj.tupletNumberOffsetY = 0;
4432
+ } else if (type === 0 /* RegularBeam */ || type === 1 /* TupletBeam */) {
4433
+ raiseBeamY *= 0.5;
4434
+ let { beamThickness } = renderer;
4435
+ const beamHeight = (i) => {
4436
+ let sym = symbols[i];
4437
+ if (sym instanceof ObjNoteGroup) {
4438
+ let beamCount = sym instanceof ObjNoteGroup ? Math.max(sym.getLeftBeamCount(), sym.getRightBeamCount()) : 0;
4439
+ return DocumentSettings.BeamSeparation * unitSize * (stemDir === "up" /* Up */ ? beamCount - 1 : 0);
4440
+ } else {
4441
+ return 0;
4442
+ }
4443
+ };
4444
+ symbols.forEach((sym, i) => {
4445
+ let symStaff = symbolStaff[i];
4446
+ let symX = symbolX[i];
4447
+ let symY = symbolY[i];
4448
+ if (symStaff && symX !== void 0 && symY !== void 0) {
4449
+ let pt = new BeamPoint(symStaff, this, sym, symX, symY);
4450
+ switch (stemDir) {
4451
+ case "up" /* Up */:
4452
+ pt.topBeamsHeight = beamThickness / 2;
4453
+ pt.bottomBeamsHeight = beamThickness / 2 + beamHeight(i);
4454
+ break;
4455
+ case "down" /* Down */:
4456
+ pt.topBeamsHeight = beamThickness / 2 + beamHeight(i);
4457
+ pt.bottomBeamsHeight = beamThickness / 2;
4458
+ break;
4459
+ }
4460
+ obj.points.push(pt);
4461
+ }
4462
+ });
4463
+ obj.tupletNumberOffsetY = groupLineDy;
4464
+ }
4465
+ if (this.isTuplet()) {
4466
+ obj.tupletNumber = new ObjText(this, this.getTupletRatioText(), 0.5, 0.5);
4467
+ obj.tupletNumber.layout(renderer);
4468
+ obj.tupletNumber.offset((leftX + rightX) / 2, (leftY + rightY) / 2 + obj.tupletNumberOffsetY);
4469
+ }
4470
+ if (obj.points.length >= 2) {
4471
+ this.staffObjects.push(obj);
4472
+ }
4473
+ });
4474
+ }
4475
+ updateRect() {
4476
+ if (this.staffObjects.length === 0) {
4477
+ this.rect = new DivRect();
4478
+ } else {
4479
+ this.staffObjects.forEach((obj) => obj.updateRect());
4480
+ this.rect = this.staffObjects[0].getRect().copy();
4481
+ for (let i = 1; i < this.staffObjects.length; i++) {
4482
+ this.rect.expandInPlace(this.staffObjects[i].getRect());
4483
+ }
4484
+ }
4485
+ }
4486
+ updateStemTips() {
4487
+ this.staffObjects.forEach((obj) => {
4488
+ let left = obj.points[0];
4489
+ let right = obj.points[obj.points.length - 1];
4490
+ if (this.type !== 2 /* TupletGroup */) {
4491
+ obj.points.forEach((pt) => {
4492
+ if (pt.symbol instanceof ObjNoteGroup) {
4493
+ if (pt !== left && pt !== right) {
4494
+ pt.y = Utils8.Math.interpolateY(left.x, left.y, right.x, right.y, pt.x);
4495
+ }
4496
+ pt.symbol.setStemTipY(pt.staff, pt.y);
4497
+ }
4498
+ });
4499
+ }
4500
+ if (obj.tupletNumber) {
4501
+ let y = (left.y + right.y) / 2 + obj.tupletNumberOffsetY;
4502
+ obj.tupletNumber.offset(0, -obj.tupletNumber.getRect().centerY + y);
4503
+ }
4504
+ });
4386
4505
  }
4387
4506
  offset(dx, dy) {
4388
- this.endingText.offset(dx, dy);
4389
- this.shapeRects.forEach((r) => r.offsetInPlace(dx, dy));
4390
- this.rect.offsetInPlace(dx, dy);
4507
+ this.staffObjects.forEach((obj) => obj.offset(dx, 0));
4508
+ this.requestRectUpdate();
4391
4509
  }
4392
4510
  draw(renderer) {
4393
- let ctx = renderer.getCanvasContext();
4394
- if (!ctx) {
4395
- return;
4511
+ let { unitSize, beamThickness, lineWidth } = renderer;
4512
+ let { stemDir, color, type } = this;
4513
+ if (type === 2 /* TupletGroup */) {
4514
+ let tipHeight = (stemDir === "up" /* Up */ ? 1 : -1) * unitSize;
4515
+ this.staffObjects.forEach((obj) => {
4516
+ let { x: lx, y: ly } = obj.points[0];
4517
+ let { x: rx, y: ry } = obj.points[obj.points.length - 1];
4518
+ if (obj.tupletNumber) {
4519
+ let tf = obj.tupletNumber.getRect().width / (rx - lx) * 1.2;
4520
+ let lc = Utils8.Math.interpolateCoord(lx, ly, rx, ry, 0.5 - tf / 2);
4521
+ let rc = Utils8.Math.interpolateCoord(lx, ly, rx, ry, 0.5 + tf / 2);
4522
+ renderer.drawLine(lx, ly, lc.x, lc.y, color, lineWidth);
4523
+ renderer.drawLine(rc.x, rc.y, rx, ry, color, lineWidth);
4524
+ } else {
4525
+ renderer.drawLine(lx, ly, rx, ry, color, lineWidth);
4526
+ }
4527
+ renderer.drawLine(lx, ly, lx, ly + tipHeight, color, lineWidth);
4528
+ renderer.drawLine(rx, ry, rx, ry + tipHeight, color, lineWidth);
4529
+ });
4530
+ } else if (type === 0 /* RegularBeam */ || type === 1 /* TupletBeam */) {
4531
+ this.staffObjects.forEach((obj) => {
4532
+ let noteGroupPoints = obj.points.filter((p) => p.symbol instanceof ObjNoteGroup);
4533
+ let { x: lx, y: ly } = noteGroupPoints[0];
4534
+ let { x: rx, y: ry } = noteGroupPoints[noteGroupPoints.length - 1];
4535
+ let beamSeparation = DocumentSettings.BeamSeparation * unitSize * (stemDir === "up" /* Up */ ? 1 : -1) * (1 + 0.5 * Math.abs(Math.atan2(ry - ly, rx - lx)));
4536
+ for (let i = 0; i < noteGroupPoints.length - 1; i++) {
4537
+ let { x: lx2, y: ly2, symbol: lsymbol } = noteGroupPoints[i];
4538
+ let { x: rx2, y: ry2, symbol: rsymbol } = noteGroupPoints[i + 1];
4539
+ let leftBeamCount = lsymbol.getRightBeamCount();
4540
+ let rightBeamCount = rsymbol.getLeftBeamCount();
4541
+ for (let beamId = 0; beamId < Math.max(leftBeamCount, rightBeamCount); beamId++) {
4542
+ if (beamId < leftBeamCount && beamId < rightBeamCount) {
4543
+ renderer.drawLine(lx2, ly2, rx2, ry2, color, beamThickness);
4544
+ } else if (leftBeamCount > rightBeamCount) {
4545
+ renderer.drawPartialLine(lx2, ly2, rx2, ry2, 0, 0.25, color, beamThickness);
4546
+ } else if (rightBeamCount > leftBeamCount) {
4547
+ renderer.drawPartialLine(lx2, ly2, rx2, ry2, 0.75, 1, color, beamThickness);
4548
+ }
4549
+ ly2 += beamSeparation;
4550
+ ry2 += beamSeparation;
4551
+ }
4552
+ }
4553
+ });
4396
4554
  }
4397
- let { lineWidth } = renderer;
4398
- let { rect } = this;
4399
- renderer.drawDebugRect(this.rect);
4400
- ctx.strokeStyle = ctx.fillStyle = "black";
4401
- ctx.lineWidth = lineWidth;
4402
- ctx.beginPath();
4403
- ctx.moveTo(rect.left, rect.bottom);
4404
- ctx.lineTo(rect.left, rect.top);
4405
- ctx.lineTo(rect.right, rect.top);
4406
- if (this.isSingleMeasureEnding()) {
4407
- ctx.lineTo(rect.right, rect.bottom);
4555
+ this.staffObjects.forEach((obj) => {
4556
+ var _a;
4557
+ return (_a = obj.tupletNumber) == null ? void 0 : _a.draw(renderer);
4558
+ });
4559
+ }
4560
+ setBeamCounts() {
4561
+ const isADottedBHalf = (a, b) => {
4562
+ let { flagCount: aFlagCount, noteSize: aNoteSize, dotCount: aDotCount } = a.rhythmProps;
4563
+ let { flagCount: bFlagCount, noteSize: bNoteSize, dotCount: bDotCount } = b.rhythmProps;
4564
+ return aFlagCount > 0 && bFlagCount > 0 && aDotCount > 0 && bDotCount === 0 && aNoteSize * Math.pow(2, aDotCount) === bNoteSize;
4565
+ };
4566
+ let groupNotes = this.symbols.filter((s) => s instanceof ObjNoteGroup);
4567
+ for (let i = 0; i < groupNotes.length; i++) {
4568
+ let center = groupNotes[i];
4569
+ let left = groupNotes[i - 1];
4570
+ let right = groupNotes[i + 1];
4571
+ if (center) {
4572
+ center.setLeftBeamCount(0);
4573
+ center.setRightBeamCount(0);
4574
+ if (left) {
4575
+ if (left.rhythmProps.flagCount === center.rhythmProps.flagCount || isADottedBHalf(left, center) || isADottedBHalf(center, left)) {
4576
+ center.setLeftBeamCount(center.rhythmProps.flagCount);
4577
+ } else {
4578
+ center.setLeftBeamCount(Math.min(left.rhythmProps.flagCount, center.rhythmProps.flagCount));
4579
+ }
4580
+ }
4581
+ if (right) {
4582
+ if (right.rhythmProps.flagCount === center.rhythmProps.flagCount || isADottedBHalf(right, center) || isADottedBHalf(center, right)) {
4583
+ center.setRightBeamCount(center.rhythmProps.flagCount);
4584
+ } else {
4585
+ center.setRightBeamCount(Math.min(right.rhythmProps.flagCount, center.rhythmProps.flagCount));
4586
+ }
4587
+ }
4588
+ }
4589
+ }
4590
+ let fixAgain;
4591
+ do {
4592
+ fixAgain = false;
4593
+ for (let i = 0; i < groupNotes.length; i++) {
4594
+ let center = groupNotes[i];
4595
+ let left = groupNotes[i - 1];
4596
+ let right = groupNotes[i + 1];
4597
+ if (center && center.getLeftBeamCount() !== center.rhythmProps.flagCount && center.getRightBeamCount() !== center.rhythmProps.flagCount) {
4598
+ center.setLeftBeamCount(0);
4599
+ center.setRightBeamCount(0);
4600
+ if (left && left.getRightBeamCount() > 0) {
4601
+ left.setRightBeamCount(0);
4602
+ fixAgain = true;
4603
+ }
4604
+ if (right && right.getLeftBeamCount() > 0) {
4605
+ right.setLeftBeamCount(0);
4606
+ fixAgain = true;
4607
+ }
4608
+ }
4609
+ }
4610
+ } while (fixAgain);
4611
+ }
4612
+ setTupletBeamCounts() {
4613
+ let type = this.getType();
4614
+ let symbols = this.getSymbols();
4615
+ if (type === 1 /* TupletBeam */) {
4616
+ symbols.forEach((s, i) => {
4617
+ if (s instanceof ObjNoteGroup) {
4618
+ s.setLeftBeamCount(i === 0 ? 0 : s.rhythmProps.flagCount);
4619
+ s.setRightBeamCount(i === symbols.length - 1 ? 0 : s.rhythmProps.flagCount);
4620
+ }
4621
+ });
4622
+ } else if (type === 2 /* TupletGroup */) {
4623
+ symbols.forEach((s) => {
4624
+ if (s instanceof ObjNoteGroup) {
4625
+ s.setLeftBeamCount(0);
4626
+ s.setRightBeamCount(0);
4627
+ }
4628
+ });
4408
4629
  }
4409
- ctx.stroke();
4410
- this.endingText.draw(renderer);
4411
4630
  }
4412
4631
  };
4413
4632
 
@@ -4852,8 +5071,147 @@ var ConnectiveProps = class {
4852
5071
  }
4853
5072
  };
4854
5073
 
5074
+ // src/score/engine/obj-tab-rhythm.ts
5075
+ import { Utils as Utils11 } from "@tspro/ts-utils-lib";
5076
+ var ObjTabRhythm = class extends MusicObject {
5077
+ constructor(measure, tab) {
5078
+ super(measure);
5079
+ this.measure = measure;
5080
+ this.tab = tab;
5081
+ __publicField(this, "voiceIds");
5082
+ __publicField(this, "mi");
5083
+ // Keep non-static
5084
+ __publicField(this, "tupletPartsTextObjMap", /* @__PURE__ */ new Map());
5085
+ this.voiceIds = getVoiceIds().filter((voiceId) => tab.containsVoiceId(voiceId));
5086
+ this.rect = new DivRect();
5087
+ this.mi = new MTabRhythm(this);
5088
+ }
5089
+ getMusicInterface() {
5090
+ return this.mi;
5091
+ }
5092
+ pick(x, y) {
5093
+ return this.rect.contains(x, y) ? [this] : [];
5094
+ }
5095
+ layout(renderer) {
5096
+ let columns = this.measure.getColumns();
5097
+ let numColsInVoiceId = getVoiceIds().map((voiceId) => Utils11.Math.sum(columns.map((col) => col.getVoiceSymbol(voiceId) ? 1 : 0)));
5098
+ this.voiceIds.sort((a, b) => Utils11.Math.cmp(numColsInVoiceId[a], numColsInVoiceId[b]));
5099
+ this.rect = new DivRect();
5100
+ }
5101
+ hasTuplets() {
5102
+ return this.measure.getBeamGroups().some((beamGroup) => beamGroup.isTuplet());
5103
+ }
5104
+ layoutFitToMeasure(renderer) {
5105
+ let { unitSize, fontSize } = renderer;
5106
+ let { measure } = this;
5107
+ let { left, right } = measure.getColumnsContentRect();
5108
+ let stemHeight = unitSize * 5;
5109
+ this.rect.left = left;
5110
+ this.rect.centerX = (left + right) / 2;
5111
+ this.rect.right = right;
5112
+ this.rect.top = this.hasTuplets() ? -fontSize : 0;
5113
+ this.rect.centerY = 0;
5114
+ this.rect.bottom = stemHeight;
5115
+ }
5116
+ offset(dx, dy) {
5117
+ this.rect.offsetInPlace(dx, dy);
5118
+ }
5119
+ draw(renderer) {
5120
+ const ctx = renderer.getCanvasContext();
5121
+ if (!ctx) {
5122
+ return;
5123
+ }
5124
+ renderer.drawDebugRect(this.rect);
5125
+ let { unitSize, lineWidth, fontSize } = renderer;
5126
+ let flagSize = unitSize;
5127
+ let dotSpace = unitSize;
5128
+ let dotWidth = unitSize * 0.25;
5129
+ let { bottom, centerY } = this.getRect();
5130
+ let stemTop = centerY;
5131
+ let stemBottom = bottom;
5132
+ let columns = this.measure.getColumns();
5133
+ for (let colId = 0; colId < columns.length; colId++) {
5134
+ let cur = columns[colId];
5135
+ let curVoiceSymbol = this.voiceIds.map((voiceId) => cur.getVoiceSymbol(voiceId)).find((sym) => sym !== void 0);
5136
+ if (!curVoiceSymbol) {
5137
+ continue;
5138
+ }
5139
+ let beamGroup = curVoiceSymbol.getBeamGroup();
5140
+ let symbols = beamGroup ? beamGroup.getSymbols() : [curVoiceSymbol];
5141
+ for (let j = 0; j < symbols.length; j++) {
5142
+ let sym = symbols[j];
5143
+ let nextSym = symbols[j + 1];
5144
+ let colX = sym.col.getRect().centerX;
5145
+ if (sym instanceof ObjNoteGroup) {
5146
+ if (sym.rhythmProps.noteSize >= 2) {
5147
+ let stemThickness = sym.rhythmProps.noteSize === 4 ? lineWidth * 2 : lineWidth;
5148
+ renderer.drawLine(colX, stemBottom, colX, stemTop, "black", stemThickness);
5149
+ }
5150
+ if (symbols.length === 1) {
5151
+ for (let i = 0; i < sym.rhythmProps.flagCount; i++) {
5152
+ renderer.drawFlag(new DivRect(colX, colX + flagSize, stemTop + i * flagSize, stemTop + (i + 2) * flagSize), "up");
5153
+ }
5154
+ }
5155
+ for (let i = 0; i < sym.rhythmProps.dotCount; i++) {
5156
+ renderer.fillCircle(colX + dotSpace * (i + 1), stemBottom - dotWidth, dotWidth);
5157
+ }
5158
+ } else if (sym instanceof ObjRest) {
5159
+ let cx = colX;
5160
+ let cy = (stemTop + stemBottom) / 2;
5161
+ let scale = 0.65;
5162
+ ctx.save();
5163
+ ctx.scale(scale, scale);
5164
+ renderer.drawRest(sym.rhythmProps.noteSize, cx / scale, cy / scale, "black");
5165
+ ctx.restore();
5166
+ for (let i = 0; i < sym.rhythmProps.dotCount; i++) {
5167
+ cx += dotSpace * 1.5;
5168
+ renderer.fillCircle(cx, cy + dotSpace, dotWidth);
5169
+ }
5170
+ }
5171
+ if (nextSym) {
5172
+ let left = sym;
5173
+ let right = nextSym;
5174
+ let leftX = left.col.getRect().centerX;
5175
+ let rightX = right.col.getRect().centerX;
5176
+ let leftBeamCount = left.hasTuplet() ? 1 : left instanceof ObjNoteGroup ? left.getRightBeamCount() : 1;
5177
+ let rightBeamCount = right.hasTuplet() ? 1 : right instanceof ObjNoteGroup ? right.getLeftBeamCount() : 1;
5178
+ let maxBeamCount = Math.max(leftBeamCount, rightBeamCount);
5179
+ for (let i = 0; i < maxBeamCount; i++) {
5180
+ let leftT = rightBeamCount > leftBeamCount && i >= leftBeamCount ? 0.75 : 0;
5181
+ let rightT = leftBeamCount > rightBeamCount && i >= rightBeamCount ? 0.25 : 1;
5182
+ renderer.drawPartialLine(leftX, stemTop + i * flagSize, rightX, stemTop + i * flagSize, leftT, rightT, "black", lineWidth * 2);
5183
+ }
5184
+ for (let i = 0; i < left.rhythmProps.dotCount; i++) {
5185
+ renderer.fillCircle(leftX + dotSpace * (i + 1), stemBottom - dotWidth, dotWidth);
5186
+ }
5187
+ for (let i = 0; i < right.rhythmProps.dotCount; i++) {
5188
+ renderer.fillCircle(rightX + dotSpace * (i + 1), stemBottom - dotWidth, dotWidth);
5189
+ }
5190
+ }
5191
+ if (beamGroup && beamGroup.isTuplet()) {
5192
+ let cx = (symbols[0].col.getRect().centerX + symbols[symbols.length - 1].col.getRect().centerX) / 2;
5193
+ let text = beamGroup.getTupletRatioText();
5194
+ let textObj = this.tupletPartsTextObjMap.get(text);
5195
+ if (!textObj) {
5196
+ this.tupletPartsTextObjMap.set(text, textObj = new ObjText(this, { text, scale: 0.75 }, 0.5, 0.5));
5197
+ textObj.layout(renderer);
5198
+ }
5199
+ textObj.offset(-textObj.getRect().centerX, -textObj.getRect().centerY);
5200
+ textObj.offset(cx, stemTop - fontSize / 2);
5201
+ textObj.draw(renderer);
5202
+ }
5203
+ if (symbols.length > 1) {
5204
+ colId = columns.indexOf(symbols[symbols.length - 1].col);
5205
+ if (colId < 0) {
5206
+ colId = columns.length;
5207
+ }
5208
+ }
5209
+ }
5210
+ }
5211
+ }
5212
+ };
5213
+
4855
5214
  // src/score/engine/obj-measure.ts
4856
- var cmp = (a, b) => a === b ? 0 : a < b ? -1 : 1;
4857
5215
  function validateVoiceId(voiceId) {
4858
5216
  if (typeof voiceId === "number" && getVoiceIds().indexOf(voiceId) < 0) {
4859
5217
  throw new MusicError13(MusicErrorType13.Score, "Invalid voiceId: " + voiceId);
@@ -4865,7 +5223,7 @@ function getExtensionTicks(extensionLength) {
4865
5223
  if (typeof extensionLength === "string") {
4866
5224
  extensionLength = [extensionLength];
4867
5225
  }
4868
- if (Utils11.Is.isArray(extensionLength)) {
5226
+ if (Utils12.Is.isArray(extensionLength)) {
4869
5227
  let totalTicks = 0;
4870
5228
  for (let i = 0; i < extensionLength.length; ) {
4871
5229
  let str = extensionLength[i];
@@ -4890,11 +5248,11 @@ function getExtensionTicks(extensionLength) {
4890
5248
  function getVerseLayoutGroupId(verse) {
4891
5249
  switch (verse) {
4892
5250
  case 1:
4893
- return 7 /* LyricsVerse1 */;
5251
+ return 8 /* LyricsVerse1 */;
4894
5252
  case 2:
4895
- return 8 /* LyricsVerse2 */;
5253
+ return 9 /* LyricsVerse2 */;
4896
5254
  case 3:
4897
- return 9 /* LyricsVerse3 */;
5255
+ return 10 /* LyricsVerse3 */;
4898
5256
  default:
4899
5257
  throw new MusicError13(MusicErrorType13.Unknown, "VerseNumber is not 1, 2 or 3.");
4900
5258
  }
@@ -4956,6 +5314,9 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
4956
5314
  this.updateKeySignature();
4957
5315
  this.updateTimeSignature();
4958
5316
  this.updateTempo();
5317
+ this.row.getTabs().forEach((tab) => {
5318
+ this.addLayoutObject(new ObjTabRhythm(this, tab), tab, 0 /* TabRhythm */, 0 /* Above */);
5319
+ });
4959
5320
  }
4960
5321
  getMusicInterface() {
4961
5322
  return this.mi;
@@ -5127,7 +5488,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5127
5488
  this.alterKeySignature = args[0];
5128
5489
  } else if (args[0] instanceof Scale) {
5129
5490
  this.alterKeySignature = args[0];
5130
- } else if (Utils11.Is.isNonEmptyString(args[0])) {
5491
+ } else if (Utils12.Is.isNonEmptyString(args[0])) {
5131
5492
  if (args.length === 1) {
5132
5493
  this.alterKeySignature = getScale(args[0]);
5133
5494
  } else if (args.length === 2) {
@@ -5180,9 +5541,9 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5180
5541
  if (beatLength === void 0) {
5181
5542
  this.alterTempo = { beatsPerMinute };
5182
5543
  } else {
5183
- let dotCount = typeof dotted === "number" && dotted > 0 ? dotted : dotted === true ? 1 : NoteLengthProps4.get(beatLength).dotCount;
5544
+ let dotCount = typeof dotted === "number" && dotted > 0 ? dotted : dotted === true ? 1 : NoteLengthProps5.get(beatLength).dotCount;
5184
5545
  let options = {
5185
- beatLength: validateNoteLength2(beatLength),
5546
+ beatLength: validateNoteLength3(beatLength),
5186
5547
  dotCount: dotCount > 0 ? dotCount : void 0
5187
5548
  };
5188
5549
  this.alterTempo = { beatsPerMinute, options };
@@ -5238,7 +5599,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5238
5599
  let grp = this.doc.getStaffGroup(staffTabOrGroup);
5239
5600
  if (grp && !prevGroups.includes(staffTabOrGroup)) {
5240
5601
  let curGroups = [...prevGroups, staffTabOrGroup];
5241
- (Utils11.Is.isArray(grp.staffsTabsAndGroups) ? grp.staffsTabsAndGroups : [grp.staffsTabsAndGroups]).forEach((staffTabOrGroup2) => {
5602
+ (Utils12.Is.isArray(grp.staffsTabsAndGroups) ? grp.staffsTabsAndGroups : [grp.staffsTabsAndGroups]).forEach((staffTabOrGroup2) => {
5242
5603
  switch (grp.verticalPosition) {
5243
5604
  case "above" /* Above */:
5244
5605
  addToStaffTabOrGroup(staffTabOrGroup2, 0 /* Above */, curGroups);
@@ -5260,12 +5621,12 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5260
5621
  }
5261
5622
  };
5262
5623
  if (staffTabOrGroups === void 0) {
5263
- if (lines.length >= 2 && lines[0] instanceof ObjStaff && lines[0].staffConfig.clef === "G" /* G */ && lines[0].isGrand() && lines[1] instanceof ObjStaff && lines[1].staffConfig.clef === "F" /* F */ && lines[1].isGrand()) {
5624
+ if (lines.length >= 2 && lines[0] instanceof ObjStaff && lines[1] instanceof ObjStaff && lines[0].staffConfig.grandId !== void 0 && lines[0].staffConfig.grandId === lines[1].staffConfig.grandId) {
5264
5625
  addToStaffTabOrGroup(defaultVerticalPos === 1 /* Below */ ? 1 : 0, defaultVerticalPos);
5265
5626
  } else {
5266
5627
  addToStaffTabOrGroup(0, defaultVerticalPos);
5267
5628
  }
5268
- } else if (Utils11.Is.isArray(staffTabOrGroups)) {
5629
+ } else if (Utils12.Is.isArray(staffTabOrGroups)) {
5269
5630
  staffTabOrGroups.forEach((staffTabOrGroup) => addToStaffTabOrGroup(staffTabOrGroup, defaultVerticalPos));
5270
5631
  } else {
5271
5632
  addToStaffTabOrGroup(staffTabOrGroups, defaultVerticalPos);
@@ -5277,7 +5638,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5277
5638
  throw new MusicError13(MusicErrorType13.Score, "Cannot add Fermata because anchor is undefined.");
5278
5639
  }
5279
5640
  this.forEachStaffGroup(staffTabOrGroups, 0 /* Above */, (line, vpos) => {
5280
- this.addLayoutObject(new ObjFermata(anchor, vpos), line, 0 /* Fermata */, vpos);
5641
+ this.addLayoutObject(new ObjFermata(anchor, vpos), line, 1 /* Fermata */, vpos);
5281
5642
  });
5282
5643
  this.disableExtension();
5283
5644
  this.requestLayout();
@@ -5296,7 +5657,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5296
5657
  let passages = args;
5297
5658
  addLayoutObjectProps = {
5298
5659
  createObj: () => new ObjEnding(anchor, passages),
5299
- layoutGroupId: 3 /* Ending */,
5660
+ layoutGroupId: 4 /* Ending */,
5300
5661
  defaultVerticalPos: 0 /* Above */
5301
5662
  };
5302
5663
  break;
@@ -5308,7 +5669,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5308
5669
  let text = getNavigationString(navigation);
5309
5670
  addLayoutObjectProps = {
5310
5671
  createObj: () => new ObjText(anchor2, text, 1, 1),
5311
- layoutGroupId: 2 /* Navigation */,
5672
+ layoutGroupId: 3 /* Navigation */,
5312
5673
  defaultVerticalPos: 0 /* Above */
5313
5674
  };
5314
5675
  this.addNavigation(staffTabOrGroups, "endRepeat" /* EndRepeat */);
@@ -5320,7 +5681,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5320
5681
  let text = getNavigationString(navigation);
5321
5682
  addLayoutObjectProps = {
5322
5683
  createObj: () => new ObjText(anchor2, text, 1, 1),
5323
- layoutGroupId: 2 /* Navigation */,
5684
+ layoutGroupId: 3 /* Navigation */,
5324
5685
  defaultVerticalPos: 0 /* Above */
5325
5686
  };
5326
5687
  break;
@@ -5331,7 +5692,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5331
5692
  let text = getNavigationString(navigation);
5332
5693
  addLayoutObjectProps = {
5333
5694
  createObj: () => new ObjSpecialText(anchor2, text),
5334
- layoutGroupId: 2 /* Navigation */,
5695
+ layoutGroupId: 3 /* Navigation */,
5335
5696
  defaultVerticalPos: 0 /* Above */
5336
5697
  };
5337
5698
  break;
@@ -5341,7 +5702,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5341
5702
  let text = getNavigationString(navigation);
5342
5703
  addLayoutObjectProps = {
5343
5704
  createObj: () => new ObjSpecialText(anchor2, text),
5344
- layoutGroupId: 2 /* Navigation */,
5705
+ layoutGroupId: 3 /* Navigation */,
5345
5706
  defaultVerticalPos: 0 /* Above */
5346
5707
  };
5347
5708
  break;
@@ -5349,7 +5710,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5349
5710
  case "endRepeat" /* EndRepeat */:
5350
5711
  if (args.length === 0) {
5351
5712
  this.endRepeatPlayCount = 2;
5352
- } else if (Utils11.Is.isIntegerGte(args[0], 2)) {
5713
+ } else if (Utils12.Is.isIntegerGte(args[0], 2)) {
5353
5714
  this.endRepeatPlayCount = args[0];
5354
5715
  } else {
5355
5716
  throw new MusicError13(MusicErrorType13.Score, "Invalid end repeat play count (should be 2 or greater integer): " + args[0]);
@@ -5386,12 +5747,12 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5386
5747
  let defaultVerticalPos;
5387
5748
  switch (annotation) {
5388
5749
  case "dynamics" /* Dynamics */:
5389
- layoutGroupId = 5 /* DynamicsAnnotation */;
5750
+ layoutGroupId = 6 /* DynamicsAnnotation */;
5390
5751
  defaultVerticalPos = 0 /* Above */;
5391
5752
  textProps.italic = true;
5392
5753
  break;
5393
5754
  case "tempo" /* Tempo */:
5394
- layoutGroupId = 4 /* TempoAnnotation */;
5755
+ layoutGroupId = 5 /* TempoAnnotation */;
5395
5756
  defaultVerticalPos = 0 /* Above */;
5396
5757
  textProps.italic = true;
5397
5758
  break;
@@ -5415,11 +5776,11 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5415
5776
  let defaultVerticalPos;
5416
5777
  switch (label) {
5417
5778
  case "note" /* Note */:
5418
- layoutGroupId = 1 /* NoteLabel */;
5779
+ layoutGroupId = 2 /* NoteLabel */;
5419
5780
  defaultVerticalPos = 1 /* Below */;
5420
5781
  break;
5421
5782
  case "chord" /* Chord */:
5422
- layoutGroupId = 6 /* ChordLabel */;
5783
+ layoutGroupId = 7 /* ChordLabel */;
5423
5784
  defaultVerticalPos = 0 /* Above */;
5424
5785
  break;
5425
5786
  }
@@ -5436,15 +5797,15 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5436
5797
  throw new MusicError13(MusicErrorType13.Score, "Connective can be added to note group only.");
5437
5798
  }
5438
5799
  if (connective === "tie" /* Tie */) {
5439
- let tieSpan = Utils11.Is.isInteger(args[0]) || Utils11.Is.isEnumValue(args[0], TieType) ? args[0] : 2;
5440
- let noteAnchor = Utils11.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : "auto" /* Auto */;
5800
+ let tieSpan = Utils12.Is.isInteger(args[0]) || Utils12.Is.isEnumValue(args[0], TieType) ? args[0] : 2;
5801
+ let noteAnchor = Utils12.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : "auto" /* Auto */;
5441
5802
  anchor.startConnective(new ConnectiveProps("tie" /* Tie */, tieSpan, noteAnchor, anchor));
5442
5803
  } else if (connective === "slur" /* Slur */) {
5443
- let slurSpan = Utils11.Is.isInteger(args[0]) ? args[0] : 2;
5444
- let noteAnchor = Utils11.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : "auto" /* Auto */;
5804
+ let slurSpan = Utils12.Is.isInteger(args[0]) ? args[0] : 2;
5805
+ let noteAnchor = Utils12.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : "auto" /* Auto */;
5445
5806
  anchor.startConnective(new ConnectiveProps("slur" /* Slur */, slurSpan, noteAnchor, anchor));
5446
5807
  } else if (connective === "slide" /* Slide */) {
5447
- let noteAnchor = Utils11.Is.isEnumValue(args[0], NoteAnchor) ? args[0] : "auto" /* Auto */;
5808
+ let noteAnchor = Utils12.Is.isEnumValue(args[0], NoteAnchor) ? args[0] : "auto" /* Auto */;
5448
5809
  anchor.startConnective(new ConnectiveProps("slide" /* Slide */, 2, noteAnchor, anchor));
5449
5810
  }
5450
5811
  }
@@ -5527,12 +5888,12 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5527
5888
  addLyrics(staffTabOrGroups, verse, lyricsLength, lyricsText, lyricsOptions) {
5528
5889
  this.forEachStaffGroup(staffTabOrGroups, 1 /* Below */, (line, vpos) => {
5529
5890
  let col = this.getRhythmColumn({ verse, line, vpos });
5530
- let lyricsContainer = col.getLyricsContainer(verse, line, vpos, validateNoteLength2(lyricsLength));
5891
+ let lyricsContainer = col.getLyricsContainer(verse, line, vpos, validateNoteLength3(lyricsLength));
5531
5892
  if (lyricsContainer) {
5532
5893
  let lyricsObj = new ObjLyrics(col, verse, line, vpos, lyricsText, lyricsOptions);
5533
5894
  let lyricsArr = this.getLyricsObjects(lyricsObj.line, lyricsObj.vpos, lyricsObj.verse);
5534
5895
  lyricsArr.push(lyricsObj);
5535
- lyricsArr.sort((a, b) => cmp(a.col.positionTicks, b.col.positionTicks));
5896
+ lyricsArr.sort((a, b) => Utils12.Math.cmp(a.col.positionTicks, b.col.positionTicks));
5536
5897
  lyricsContainer.addLyricsObject(lyricsObj);
5537
5898
  this.addLayoutObject(lyricsObj, line, getVerseLayoutGroupId(verse), vpos);
5538
5899
  }
@@ -5618,18 +5979,15 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5618
5979
  getLyricsObjects(line, vpos, verse) {
5619
5980
  let vposMap = this.lyricsObjectsCache.get(line);
5620
5981
  if (vposMap === void 0) {
5621
- vposMap = /* @__PURE__ */ new Map();
5622
- this.lyricsObjectsCache.set(line, vposMap);
5982
+ this.lyricsObjectsCache.set(line, vposMap = /* @__PURE__ */ new Map());
5623
5983
  }
5624
5984
  let verseMap = vposMap.get(vpos);
5625
5985
  if (verseMap === void 0) {
5626
- verseMap = /* @__PURE__ */ new Map();
5627
- vposMap.set(vpos, verseMap);
5986
+ vposMap.set(vpos, verseMap = /* @__PURE__ */ new Map());
5628
5987
  }
5629
5988
  let lyricsArr = verseMap.get(verse);
5630
5989
  if (lyricsArr === void 0) {
5631
- lyricsArr = [];
5632
- verseMap.set(verse, lyricsArr);
5990
+ verseMap.set(verse, lyricsArr = []);
5633
5991
  }
5634
5992
  return lyricsArr;
5635
5993
  }
@@ -5724,6 +6082,9 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5724
6082
  }
5725
6083
  this.requestLayout();
5726
6084
  }
6085
+ getBeamGroups() {
6086
+ return this.beamGroups;
6087
+ }
5727
6088
  createBeams() {
5728
6089
  if (!this.needBeamsUpdate) {
5729
6090
  return;
@@ -5742,72 +6103,44 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5742
6103
  }
5743
6104
  getVoiceIds().forEach((voiceId) => {
5744
6105
  let symbols = this.getVoiceSymbols(voiceId).slice();
5745
- if (symbols.length >= 2) {
5746
- let symbolsStartTicks = this.isUpBeat() ? Math.max(0, this.getMeasureTicks() - this.getConsumedTicks()) : 0;
5747
- let groupStartTicks = 0;
5748
- for (let groupId = 0; groupId < ts.beamGroupSizes.length; groupId++) {
5749
- let beamGroupSize = ts.beamGroupSizes[groupId];
5750
- let groupSizeSum = 0;
5751
- beamGroupSize.forEach((s) => groupSizeSum += s);
5752
- let groupLength = groupSizeSum * NoteLengthProps4.get("8n").ticks;
5753
- let groupSymbols = [];
5754
- let groupSymbolsLength = 0;
5755
- while (symbols.length > 0 && groupSymbolsLength < groupLength) {
5756
- let symbol = symbols[0];
5757
- if (symbol.col.positionTicks >= groupStartTicks) {
5758
- groupSymbols.push(symbol);
5759
- groupSymbolsLength += symbol.rhythmProps.ticks;
5760
- symbols.shift();
5761
- } else {
5762
- break;
6106
+ if (symbols.length < 2) {
6107
+ return;
6108
+ }
6109
+ let upBeatStartTicks = this.isUpBeat() ? Math.max(0, this.getMeasureTicks() - this.getConsumedTicks()) : 0;
6110
+ let groupStartTicks = 0;
6111
+ for (let groupId = 0; groupId < ts.beamGroupSizes.length; groupId++) {
6112
+ let beamGroupSize = ts.beamGroupSizes[groupId];
6113
+ let beamGroupSizeList = [beamGroupSize];
6114
+ if (beamGroupSize.length > 1) {
6115
+ beamGroupSizeList.unshift([Utils12.Math.sum(beamGroupSize)]);
6116
+ }
6117
+ let beamCreated = false;
6118
+ let groupStartTicksSave = groupStartTicks;
6119
+ while (beamGroupSizeList.length > 0 && !beamCreated) {
6120
+ let beamGroupSize2 = beamGroupSizeList.shift();
6121
+ groupStartTicks = groupStartTicksSave;
6122
+ beamGroupSize2.forEach((beamGroupSize3) => {
6123
+ let beamGroupTicks = beamGroupSize3 * NoteLengthProps5.get("8n").ticks;
6124
+ let groupEndTicks = groupStartTicks + beamGroupTicks;
6125
+ let groupSymbols = symbols.filter((symbol) => {
6126
+ let symbolStartTicks = upBeatStartTicks + symbol.col.positionTicks;
6127
+ let symbolEndTicks = symbolStartTicks + symbol.rhythmProps.ticks;
6128
+ return symbolStartTicks >= groupStartTicks && symbolEndTicks <= groupEndTicks;
6129
+ });
6130
+ let groupSymbolsTicks = Utils12.Math.sum(groupSymbols.map((sym) => sym.rhythmProps.ticks));
6131
+ if (groupSymbolsTicks === beamGroupTicks && groupSymbols.every((n) => n instanceof ObjNoteGroup) && (groupSymbols.every((n) => n.rhythmProps.flagCount === 1) || beamGroupSizeList.length === 0)) {
6132
+ if (ObjBeamGroup.createBeam(groupSymbols)) {
6133
+ beamCreated = true;
6134
+ }
5763
6135
  }
5764
- }
5765
- _ObjMeasure.setupBeamGroup(groupSymbols, beamGroupSize);
5766
- symbolsStartTicks += groupSymbolsLength;
5767
- groupStartTicks += groupLength;
6136
+ groupStartTicks += beamGroupTicks;
6137
+ });
5768
6138
  }
5769
6139
  }
5770
6140
  });
5771
6141
  this.needBeamsUpdate = false;
5772
6142
  this.requestLayout();
5773
6143
  }
5774
- static setupBeamGroup(groupSymbols, mainBeamGroupSizeArr) {
5775
- if (mainBeamGroupSizeArr.length === 0) {
5776
- return false;
5777
- }
5778
- let groupNotes = groupSymbols.map((s) => {
5779
- var _a;
5780
- return s instanceof ObjNoteGroup && ((_a = s.getBeamGroup()) == null ? void 0 : _a.isTuplet()) !== true ? s : void 0;
5781
- });
5782
- ObjNoteGroup.setBeamCounts(groupNotes);
5783
- let beamGroupSizeArrList = [mainBeamGroupSizeArr];
5784
- if (mainBeamGroupSizeArr.length > 1) {
5785
- let sum = 0;
5786
- mainBeamGroupSizeArr.forEach((s) => sum += s);
5787
- beamGroupSizeArrList.unshift([sum]);
5788
- }
5789
- let beamsCreated = false;
5790
- while (beamGroupSizeArrList.length > 0 && !beamsCreated) {
5791
- let beamGroupSizeArr = beamGroupSizeArrList.shift();
5792
- let groupSymbolsCopy = groupSymbols.slice();
5793
- beamGroupSizeArr.forEach((beamGroupSize) => {
5794
- var _a;
5795
- let beamGroupLength = beamGroupSize * NoteLengthProps4.get("8n").ticks;
5796
- let beamNotesLength = 0;
5797
- let beamNotes = [];
5798
- while (beamNotesLength < beamGroupLength && groupSymbolsCopy.length > 0) {
5799
- let symbol = groupSymbolsCopy.shift();
5800
- beamNotesLength += symbol.rhythmProps.ticks;
5801
- beamNotes.push(symbol instanceof ObjNoteGroup && ((_a = symbol.getBeamGroup()) == null ? void 0 : _a.isTuplet()) !== true ? symbol : void 0);
5802
- }
5803
- if (beamNotesLength === beamGroupLength && beamNotes.every((n) => n !== void 0) && (beamNotes.every((n) => n.rhythmProps.flagCount === 1) || beamGroupSizeArrList.length === 0)) {
5804
- ObjBeamGroup.createBeam(beamNotes);
5805
- beamsCreated = true;
5806
- }
5807
- });
5808
- }
5809
- return beamsCreated;
5810
- }
5811
6144
  getBarLineLeft() {
5812
6145
  return this.barLineLeft;
5813
6146
  }
@@ -5828,7 +6161,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5828
6161
  this.completeRests(getVoiceIds().filter((id) => this.getConsumedTicks(id) > 0));
5829
6162
  }
5830
6163
  return;
5831
- } else if (Utils11.Is.isArray(voiceId)) {
6164
+ } else if (Utils12.Is.isArray(voiceId)) {
5832
6165
  voiceId.forEach((id) => this.completeRests(id));
5833
6166
  return;
5834
6167
  } else {
@@ -5838,9 +6171,9 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5838
6171
  let remainingTicks = measureTicks - consumedTicks;
5839
6172
  let rests = [];
5840
6173
  while (remainingTicks > 0) {
5841
- for (let noteSize = NoteLengthProps4.LongestNoteSize; noteSize <= NoteLengthProps4.ShortestNoteSize; noteSize *= 2) {
5842
- let restLength = NoteLengthProps4.create(noteSize).noteLength;
5843
- for (let dotCount = NoteLengthProps4.get(restLength).maxDotCount; dotCount >= 0; dotCount--) {
6174
+ for (let noteSize = NoteLengthProps5.LongestNoteSize; noteSize <= NoteLengthProps5.ShortestNoteSize; noteSize *= 2) {
6175
+ let restLength = NoteLengthProps5.create(noteSize).noteLength;
6176
+ for (let dotCount = NoteLengthProps5.get(restLength).maxDotCount; dotCount >= 0; dotCount--) {
5844
6177
  let restProps = RhythmProps5.get(restLength, dotCount);
5845
6178
  while (restProps.ticks <= remainingTicks) {
5846
6179
  rests.push(restProps);
@@ -5875,22 +6208,30 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5875
6208
  let showKeySignature = isFirstMeasureInRow || isAfterMeasureBreak || !!this.alterKeySignature;
5876
6209
  let showTimeSignature = !!this.alterTimeSignature;
5877
6210
  let showTempo = !!this.alterTempo;
5878
- if (showClef || showMeasureNumber || showKeySignature || showTimeSignature || showTempo) {
5879
- this.signatures = this.row.getStaves().map((staff, staffId) => {
5880
- let oldSignature = this.signatures.find((s) => s.staff === staff);
5881
- let signature = oldSignature != null ? oldSignature : new ObjSignature(this, staff);
6211
+ this.signatures = [];
6212
+ this.row.getNotationLines().forEach((line, lineId) => {
6213
+ if (line instanceof ObjStaff && (showClef || showMeasureNumber || showKeySignature || showTimeSignature || showTempo)) {
6214
+ let oldSignature = this.signatures.filter((s) => s instanceof ObjStaffSignature).find((s) => s.staff === line);
6215
+ let signature = oldSignature != null ? oldSignature : new ObjStaffSignature(this, line);
5882
6216
  signature.staff.addObject(signature);
5883
6217
  signature.updateClefImage(renderer, showClef);
5884
- signature.updateMeasureNumber(showMeasureNumber && staffId === 0);
6218
+ signature.updateMeasureNumber(showMeasureNumber && lineId === 0);
5885
6219
  signature.updateKeySignature(showKeySignature);
5886
6220
  signature.updateTimeSignature(showTimeSignature);
5887
- signature.updateTempo(showTempo && staffId === 0);
5888
- return signature;
5889
- });
5890
- } else {
5891
- this.signatures = [];
5892
- }
5893
- this.signatures.forEach((signature) => signature.layout(renderer));
6221
+ signature.updateTempo(showTempo && lineId === 0);
6222
+ signature.layout(renderer);
6223
+ this.signatures.push(signature);
6224
+ } else if (line instanceof ObjTab && (showMeasureNumber || showTimeSignature || showTempo)) {
6225
+ let oldSignature = this.signatures.filter((s) => s instanceof ObjTabSignature).find((s) => s.tab === line);
6226
+ let signature = oldSignature != null ? oldSignature : new ObjTabSignature(this, line);
6227
+ signature.tab.addObject(signature);
6228
+ signature.updateMeasureNumber(showMeasureNumber && lineId === 0);
6229
+ signature.updateTimeSignature(showTimeSignature);
6230
+ signature.updateTempo(showTempo && lineId === 0);
6231
+ signature.layout(renderer);
6232
+ this.signatures.push(signature);
6233
+ }
6234
+ });
5894
6235
  this.tabStringNotes.length = 0;
5895
6236
  if (this === this.row.getFirstMeasure()) {
5896
6237
  this.row.getTabs().forEach((tab) => {
@@ -5943,7 +6284,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5943
6284
  let columnsAreaLeft = this.rect.left + this.leftSolidAreaWidth;
5944
6285
  let columnsAreaRight = this.rect.right - this.rightSolidAreaWidth;
5945
6286
  let columnsAreaWidth = columnsAreaRight - columnsAreaLeft;
5946
- let columnsWidth = Utils11.Math.sum(this.columns.map((col) => col.getRect().width));
6287
+ let columnsWidth = Utils12.Math.sum(this.columns.map((col) => col.getRect().width));
5947
6288
  let columnScale = columnsAreaWidth / columnsWidth;
5948
6289
  let columnLeft = columnsAreaLeft;
5949
6290
  this.columns.forEach((col) => {
@@ -6064,18 +6405,19 @@ var ObjMeasure2 = _ObjMeasure;
6064
6405
  // src/score/engine/layout-object.ts
6065
6406
  import { MusicError as MusicError14, MusicErrorType as MusicErrorType14 } from "@tspro/web-music-score/core";
6066
6407
  var WidenColumnList = [
6067
- 1 /* NoteLabel */,
6068
- 6 /* ChordLabel */
6408
+ 2 /* NoteLabel */,
6409
+ 7 /* ChordLabel */
6069
6410
  ];
6070
6411
  var RowAlignList = [
6071
- 2 /* Navigation */,
6072
- 3 /* Ending */,
6073
- 4 /* TempoAnnotation */,
6074
- 5 /* DynamicsAnnotation */,
6075
- 6 /* ChordLabel */,
6076
- 7 /* LyricsVerse1 */,
6077
- 8 /* LyricsVerse2 */,
6078
- 9 /* LyricsVerse3 */
6412
+ 0 /* TabRhythm */,
6413
+ 3 /* Navigation */,
6414
+ 4 /* Ending */,
6415
+ 5 /* TempoAnnotation */,
6416
+ 6 /* DynamicsAnnotation */,
6417
+ 7 /* ChordLabel */,
6418
+ 8 /* LyricsVerse1 */,
6419
+ 9 /* LyricsVerse2 */,
6420
+ 10 /* LyricsVerse3 */
6079
6421
  ];
6080
6422
  function requireParentMeasure(p) {
6081
6423
  while (p) {
@@ -6251,7 +6593,7 @@ var ObjNotationLine4 = class extends MusicObject {
6251
6593
  let rowLayoutObjs = layoutGroup.getLayoutObjects(verticalPos).filter((layoutObj) => !layoutObj.isPositionResolved());
6252
6594
  rowLayoutObjs.forEach((layoutObj) => {
6253
6595
  let { musicObj, anchor } = layoutObj;
6254
- if (musicObj instanceof ObjEnding || musicObj instanceof ObjExtensionLine) {
6596
+ if (musicObj instanceof ObjEnding || musicObj instanceof ObjExtensionLine || musicObj instanceof ObjTabRhythm) {
6255
6597
  musicObj.layoutFitToMeasure(renderer);
6256
6598
  } else {
6257
6599
  musicObj.offset(anchor.getRect().centerX - musicObj.getRect().centerX, 0);
@@ -6373,9 +6715,6 @@ var ObjStaff = class extends ObjNotationLine4 {
6373
6715
  containsVoiceId(voiceId) {
6374
6716
  return !this.staffConfig.voiceIds || this.staffConfig.voiceIds.includes(voiceId);
6375
6717
  }
6376
- isGrand() {
6377
- return this.staffConfig.isGrand === true;
6378
- }
6379
6718
  calcTop() {
6380
6719
  let top = this.topLineY;
6381
6720
  this.objects.forEach((o) => top = Math.min(top, o.getRect().top));
@@ -6436,7 +6775,7 @@ var ObjTab = class extends ObjNotationLine4 {
6436
6775
  __publicField(this, "tuningName");
6437
6776
  __publicField(this, "tuningStrings");
6438
6777
  __publicField(this, "mi");
6439
- if (Utils12.Is.isArray(tabConfig.tuning)) {
6778
+ if (Utils13.Is.isArray(tabConfig.tuning)) {
6440
6779
  this.tuningName = void 0;
6441
6780
  this.tuningStrings = tabConfig.tuning.map((noteName) => Note8.getNote(noteName)).reverse();
6442
6781
  } else if (typeof tabConfig.tuning === "string") {
@@ -6490,10 +6829,14 @@ var ObjTab = class extends ObjNotationLine4 {
6490
6829
  return true;
6491
6830
  }
6492
6831
  calcTop() {
6493
- return this.top;
6832
+ let { top } = this;
6833
+ this.objects.forEach((o) => top = Math.min(top, o.getRect().top));
6834
+ return top;
6494
6835
  }
6495
6836
  calcBottom() {
6496
- return this.bottom;
6837
+ let { bottom } = this;
6838
+ this.objects.forEach((o) => bottom = Math.max(bottom, o.getRect().bottom));
6839
+ return bottom;
6497
6840
  }
6498
6841
  pick(x, y) {
6499
6842
  return [this];
@@ -6557,7 +6900,7 @@ var ObjScoreRow = class extends MusicObject {
6557
6900
  for (let i = 0; i < notationLines.length - 1; i++) {
6558
6901
  let treble = notationLines[i];
6559
6902
  let bass = notationLines[i + 1];
6560
- if (treble instanceof ObjStaff && treble.isGrand() && treble.staffConfig.clef === "G" /* G */ && bass instanceof ObjStaff && bass.isGrand() && bass.staffConfig.clef === "F" /* F */) {
6903
+ if (treble instanceof ObjStaff && bass instanceof ObjStaff && treble.staffConfig.grandId !== void 0 && treble.staffConfig.grandId === bass.staffConfig.grandId) {
6561
6904
  treble.joinGrandStaff(bass);
6562
6905
  bass.joinGrandStaff(treble);
6563
6906
  }
@@ -6734,17 +7077,17 @@ var ObjScoreRow = class extends MusicObject {
6734
7077
  alignStemsToBeams() {
6735
7078
  this.measures.forEach((m) => m.alignStemsToBeams());
6736
7079
  }
6737
- layoutPositionLines(renderer) {
7080
+ layoutSetNotationLines(renderer) {
6738
7081
  let { unitSize } = renderer;
6739
7082
  for (let i = 1; i < this.notationLines.length; i++) {
6740
7083
  let prev = this.notationLines[i - 1];
6741
7084
  let cur = this.notationLines[i];
6742
- if (prev instanceof ObjStaff && prev.isGrand() && prev.staffConfig.clef === "G" /* G */ && cur instanceof ObjStaff && cur.isGrand() && cur.staffConfig.clef === "F" /* F */) {
6743
- let sep = unitSize * 6;
6744
- cur.offset(0, prev.getBottomLineY() - cur.getTopLineY() + sep);
7085
+ if (prev instanceof ObjStaff && cur instanceof ObjStaff && prev.staffConfig.grandId !== void 0 && prev.staffConfig.grandId === cur.staffConfig.grandId) {
7086
+ let dy = prev.getBottomLineY() - cur.getTopLineY() + unitSize * 6;
7087
+ cur.offset(0, dy);
6745
7088
  } else {
6746
- let sep = unitSize * 3;
6747
- cur.offset(0, prev.calcBottom() - cur.calcTop() + sep);
7089
+ let dy = prev.calcBottom() - cur.calcTop() + unitSize * 3;
7090
+ cur.offset(0, dy);
6748
7091
  }
6749
7092
  }
6750
7093
  this.measures.forEach((m) => {
@@ -6891,7 +7234,8 @@ var ObjHeader = class extends MusicObject {
6891
7234
  };
6892
7235
 
6893
7236
  // src/score/engine/obj-document.ts
6894
- import { Utils as Utils13 } from "@tspro/ts-utils-lib";
7237
+ import { Utils as Utils14 } from "@tspro/ts-utils-lib";
7238
+ import { MusicError as MusicError17, MusicErrorType as MusicErrorType17 } from "@tspro/web-music-score/core";
6895
7239
  var ObjDocument = class extends MusicObject {
6896
7240
  constructor() {
6897
7241
  super(void 0);
@@ -6912,7 +7256,7 @@ var ObjDocument = class extends MusicObject {
6912
7256
  return this.mi;
6913
7257
  }
6914
7258
  setScoreConfiguration(config) {
6915
- if (Utils13.Is.isEnumValue(config, StaffPreset)) {
7259
+ if (Utils14.Is.isEnumValue(config, StaffPreset)) {
6916
7260
  switch (config) {
6917
7261
  default:
6918
7262
  case "treble" /* Treble */:
@@ -6923,8 +7267,8 @@ var ObjDocument = class extends MusicObject {
6923
7267
  break;
6924
7268
  case "grand" /* Grand */:
6925
7269
  this.curScoreConfig = [
6926
- { type: "staff", clef: "G" /* G */, isGrand: true },
6927
- { type: "staff", clef: "F" /* F */, isGrand: true }
7270
+ { type: "staff", clef: "G" /* G */, grandId: "grand1" },
7271
+ { type: "staff", clef: "F" /* F */, grandId: "grand1" }
6928
7272
  ];
6929
7273
  break;
6930
7274
  case "guitarTreble" /* GuitarTreble */:
@@ -6940,26 +7284,57 @@ var ObjDocument = class extends MusicObject {
6940
7284
  ];
6941
7285
  break;
6942
7286
  }
6943
- } else if (Utils13.Is.isArray(config)) {
7287
+ } else if (Utils14.Is.isArray(config)) {
6944
7288
  this.curScoreConfig = config;
6945
7289
  } else {
6946
7290
  this.curScoreConfig = [config];
6947
7291
  }
6948
- for (let i = 0; i < this.curScoreConfig.length - 1; i++) {
6949
- let treble = this.curScoreConfig[i];
6950
- let bass = this.curScoreConfig[i + 1];
6951
- if (treble.type === "staff" && bass.type === "staff") {
6952
- if (treble.clef === "G" /* G */ && treble.isGrand && bass.clef === "F" /* F */ && bass.isGrand) {
6953
- treble.minNote = "C4";
6954
- bass.maxNote = "B3";
6955
- treble.isOctaveDown = bass.isOctaveDown = false;
7292
+ for (let cfgId = 0, grandId = "grand"; cfgId < this.curScoreConfig.length; ) {
7293
+ let treble = this.curScoreConfig[cfgId];
7294
+ let bass = this.curScoreConfig[cfgId + 1];
7295
+ while (this.curScoreConfig.filter((cfg) => cfg.type === "staff").findIndex((cfg) => cfg.grandId === grandId) >= 0) {
7296
+ grandId += "A";
7297
+ }
7298
+ if (treble && treble.type === "staff" && treble.isGrand) {
7299
+ if (treble.grandId !== void 0) {
7300
+ throw new MusicError17(MusicErrorType17.Score, `Grand staff error: mixing isGrand and grandId!`);
7301
+ } else if (bass && bass.type === "staff" && bass.isGrand) {
7302
+ if (bass.grandId !== void 0) {
7303
+ throw new MusicError17(MusicErrorType17.Score, `Grand staff error: mixing isGrand and grandId!`);
7304
+ } else {
7305
+ treble.grandId = grandId;
7306
+ bass.grandId = grandId;
7307
+ treble.isGrand = bass.isGrand = false;
7308
+ cfgId += 2;
7309
+ }
6956
7310
  } else {
6957
- treble.isGrand = bass.isGrand = false;
7311
+ throw new MusicError17(MusicErrorType17.Score, `Grand staff error: invalid use of isGrand!`);
7312
+ }
7313
+ } else {
7314
+ cfgId++;
7315
+ }
7316
+ }
7317
+ for (let cfgId = 0, usedGrandIdes = []; cfgId < this.curScoreConfig.length; ) {
7318
+ let treble = this.curScoreConfig[cfgId];
7319
+ let bass = this.curScoreConfig[cfgId + 1];
7320
+ if (treble && bass && treble.type === "staff" && bass.type === "staff" && treble.grandId !== void 0 && treble.grandId === bass.grandId) {
7321
+ if (usedGrandIdes.includes(treble.grandId)) {
7322
+ throw new MusicError17(MusicErrorType17.Score, `Grand staff error: grandId "${treble.grandId}" already used!`);
7323
+ } else if (treble.clef !== "G" /* G */) {
7324
+ throw new MusicError17(MusicErrorType17.Score, `Grand staff error: Invalid treble clef "${treble.clef}"!`);
7325
+ } else if (bass.clef !== "F" /* F */) {
7326
+ throw new MusicError17(MusicErrorType17.Score, `Grand staff error: Invalid treble clef "${treble.clef}"!`);
7327
+ } else if (treble.isOctaveDown || bass.isOctaveDown) {
7328
+ throw new MusicError17(MusicErrorType17.Score, `Grand staff error: cannot use isOctaveDown option!`);
6958
7329
  }
6959
- } else if (treble.type === "staff") {
6960
- treble.isGrand = false;
6961
- } else if (bass.type === "staff") {
6962
- bass.isGrand = false;
7330
+ usedGrandIdes.push(treble.grandId);
7331
+ treble.minNote = "C4";
7332
+ bass.maxNote = "B3";
7333
+ cfgId += 2;
7334
+ } else if (treble && treble.type === "staff" && treble.grandId !== void 0) {
7335
+ throw new MusicError17(MusicErrorType17.Score, `Grand staff error: invalid use of grandId "${treble.grandId}"!`);
7336
+ } else {
7337
+ cfgId++;
6963
7338
  }
6964
7339
  }
6965
7340
  this.requestNewRow();
@@ -7102,7 +7477,7 @@ var ObjDocument = class extends MusicObject {
7102
7477
  );
7103
7478
  this.rows.forEach((row) => row.layoutWidth(renderer, rowWidth));
7104
7479
  this.rows.forEach((row) => row.layoutLayoutGroups(renderer));
7105
- this.rows.forEach((row) => row.layoutPositionLines(renderer));
7480
+ this.rows.forEach((row) => row.layoutSetNotationLines(renderer));
7106
7481
  this.rows.forEach((row) => row.layoutPadding(renderer));
7107
7482
  this.rect = new DivRect();
7108
7483
  if (this.header) {
@@ -7166,11 +7541,11 @@ var ObjDocument = class extends MusicObject {
7166
7541
  };
7167
7542
 
7168
7543
  // src/score/pub/document-builder.ts
7169
- import { BeamGrouping, KeySignature as KeySignature3, Note as Note10, NoteLength as NoteLength8, RhythmProps as RhythmProps6, Scale as Scale2, ScaleType, SymbolSet as SymbolSet2, TimeSignature as TimeSignature2, TimeSignatures, TuningNameList, validateNoteLength as validateNoteLength3, validateTupletRatio } from "@tspro/web-music-score/theory";
7170
- import { MusicError as MusicError17, MusicErrorType as MusicErrorType17 } from "@tspro/web-music-score/core";
7544
+ import { BeamGrouping, KeySignature as KeySignature3, Note as Note10, NoteLength as NoteLength9, RhythmProps as RhythmProps6, Scale as Scale2, ScaleType, SymbolSet as SymbolSet2, TimeSignature as TimeSignature2, TimeSignatures, TuningNameList, validateNoteLength as validateNoteLength4, validateTupletRatio } from "@tspro/web-music-score/theory";
7545
+ import { MusicError as MusicError18, MusicErrorType as MusicErrorType18 } from "@tspro/web-music-score/core";
7171
7546
  function assertArg(condition, argName, argValue) {
7172
7547
  if (!condition) {
7173
- throw new MusicError17(MusicErrorType17.Score, `Invalid arg: ${argName} = ${argValue}`);
7548
+ throw new MusicError18(MusicErrorType18.Score, `Invalid arg: ${argName} = ${argValue}`);
7174
7549
  }
7175
7550
  }
7176
7551
  function isNote(note) {
@@ -7182,64 +7557,70 @@ function isNote(note) {
7182
7557
  }
7183
7558
  }
7184
7559
  function isVoiceId(value) {
7185
- return Utils14.Is.isNumber(value) && getVoiceIds().indexOf(value) >= 0;
7560
+ return Utils15.Is.isNumber(value) && getVoiceIds().indexOf(value) >= 0;
7186
7561
  }
7187
7562
  function isStringNumber(value) {
7188
- return Utils14.Is.isNumber(value) && getStringNumbers().indexOf(value) >= 0;
7563
+ return Utils15.Is.isNumber(value) && getStringNumbers().indexOf(value) >= 0;
7189
7564
  }
7190
7565
  function isVerseNumber(value) {
7191
- return Utils14.Is.isNumber(value) && getVerseNumbers().indexOf(value) >= 0;
7566
+ return Utils15.Is.isNumber(value) && getVerseNumbers().indexOf(value) >= 0;
7567
+ }
7568
+ function assertBaseConfig(baseConfig) {
7569
+ assertArg(Utils15.Is.isObject(baseConfig), "baseConfig", baseConfig);
7570
+ assertArg(Utils15.Is.isStringOrUndefined(baseConfig.name), "baseConfig.name", baseConfig.name);
7571
+ assertArg(Utils15.Is.isUndefined(baseConfig.voiceIds) || Utils15.Is.isArray(baseConfig.voiceIds) && baseConfig.voiceIds.every((voiceId) => Utils15.Is.isNumber(voiceId)), "baseConfig.voiceIds", baseConfig.voiceIds);
7192
7572
  }
7193
7573
  function assertStaffConfig(staffConfig) {
7194
- assertArg(Utils14.Is.isObject(staffConfig), "staffConfig", staffConfig);
7574
+ assertBaseConfig(staffConfig);
7575
+ assertArg(Utils15.Is.isObject(staffConfig), "staffConfig", staffConfig);
7195
7576
  assertArg(staffConfig.type === "staff", "staffConfig.type", staffConfig.type);
7196
- assertArg(Utils14.Is.isEnumValue(staffConfig.clef, Clef), "staffConfig.clef", staffConfig.clef);
7197
- assertArg(Utils14.Is.isBooleanOrUndefined(staffConfig.isOctaveDown), "staffConfig.isOctaveDown", staffConfig.isOctaveDown);
7198
- assertArg(Utils14.Is.isUndefined(staffConfig.minNote) || isNote(staffConfig.minNote), "staffConfig.minNote", staffConfig.minNote);
7199
- assertArg(Utils14.Is.isUndefined(staffConfig.maxNote) || isNote(staffConfig.maxNote), "staffConfig.maxNote", staffConfig.maxNote);
7200
- assertArg(Utils14.Is.isUndefined(staffConfig.voiceIds) || Utils14.Is.isArray(staffConfig.voiceIds) && staffConfig.voiceIds.every((voiceId) => Utils14.Is.isNumber(voiceId)), "staffConfig.voiceIds", staffConfig.voiceIds);
7201
- assertArg(Utils14.Is.isBooleanOrUndefined(staffConfig.isGrand), "staffConfig.isGrand", staffConfig.isGrand);
7577
+ assertArg(Utils15.Is.isEnumValue(staffConfig.clef, Clef), "staffConfig.clef", staffConfig.clef);
7578
+ assertArg(Utils15.Is.isBooleanOrUndefined(staffConfig.isOctaveDown), "staffConfig.isOctaveDown", staffConfig.isOctaveDown);
7579
+ assertArg(Utils15.Is.isUndefined(staffConfig.minNote) || isNote(staffConfig.minNote), "staffConfig.minNote", staffConfig.minNote);
7580
+ assertArg(Utils15.Is.isUndefined(staffConfig.maxNote) || isNote(staffConfig.maxNote), "staffConfig.maxNote", staffConfig.maxNote);
7581
+ assertArg(Utils15.Is.isStringOrUndefined(staffConfig.grandId), "staffConfig.grandId", staffConfig.grandId);
7582
+ assertArg(Utils15.Is.isBooleanOrUndefined(staffConfig.isGrand), "staffConfig.isGrand", staffConfig.isGrand);
7202
7583
  }
7203
7584
  function assertTabConfig(tabConfig) {
7204
- assertArg(Utils14.Is.isObject(tabConfig), "tabConfig", tabConfig);
7585
+ assertBaseConfig(tabConfig);
7586
+ assertArg(Utils15.Is.isObject(tabConfig), "tabConfig", tabConfig);
7205
7587
  assertArg(tabConfig.type === "tab", "tabConfig.type", tabConfig.type);
7206
- if (typeof tabConfig.tuning === "string") {
7588
+ if (Utils15.Is.isString(tabConfig.tuning)) {
7207
7589
  assertArg(TuningNameList.includes(tabConfig.tuning), "tabConfig.tuning", tabConfig.tuning);
7208
- } else if (Utils14.Is.isArray(tabConfig.tuning)) {
7590
+ } else if (Utils15.Is.isArray(tabConfig.tuning)) {
7209
7591
  assertArg(tabConfig.tuning.length === getStringNumbers().length && tabConfig.tuning.every((s) => isNote(s)), "tabConfig.tuning", tabConfig.tuning);
7210
7592
  }
7211
- assertArg(Utils14.Is.isUndefined(tabConfig.voiceIds) || Utils14.Is.isArray(tabConfig.voiceIds) && tabConfig.voiceIds.every((voiceId) => Utils14.Is.isNumber(voiceId)), "tabConfig.voiceIds", tabConfig.voiceIds);
7212
7593
  }
7213
7594
  function assertNoteOptions(noteOptions) {
7214
- assertArg(Utils14.Is.isObject(noteOptions), "noteOptions", noteOptions);
7215
- assertArg(Utils14.Is.isBooleanOrUndefined(noteOptions.dotted) || Utils14.Is.isIntegerGte(noteOptions.dotted, 0), "noteOptions.dotted", noteOptions.dotted);
7216
- assertArg(Utils14.Is.isEnumValueOrUndefined(noteOptions.stem, Stem), "noteOptions.stem", noteOptions.stem);
7217
- assertArg(Utils14.Is.isStringOrUndefined(noteOptions.color), "noteOptions.color", noteOptions.color);
7218
- assertArg(Utils14.Is.isBooleanOrUndefined(noteOptions.arpeggio) || Utils14.Is.isEnumValue(noteOptions.arpeggio, Arpeggio), "noteOptions.arpeggio", noteOptions.arpeggio);
7219
- assertArg(Utils14.Is.isBooleanOrUndefined(noteOptions.staccato), "noteOptions.staccato", noteOptions.staccato);
7220
- assertArg(Utils14.Is.isBooleanOrUndefined(noteOptions.diamond), "noteOptions.diamond", noteOptions.diamond);
7221
- assertArg(Utils14.Is.isBooleanOrUndefined(noteOptions.triplet), "noteOptions.triplet", noteOptions.triplet);
7222
- assertArg(Utils14.Is.isUndefined(noteOptions.string) || isStringNumber(noteOptions.string) || Utils14.Is.isNonEmptyArray(noteOptions.string) && noteOptions.string.every((string) => isStringNumber(string)), "noteOptions.string", noteOptions.string);
7223
- assertArg(Utils14.Is.isUndefined(noteOptions.tieSpan), 'NoteOptions.tieSpan was removed. Use addConnective("tie", tieSpan)', "");
7224
- assertArg(Utils14.Is.isUndefined(noteOptions.slurSpan), 'NoteOptions.slurSpan was removed. Use addConnective("slur", slurSpan)', "");
7595
+ assertArg(Utils15.Is.isObject(noteOptions), "noteOptions", noteOptions);
7596
+ assertArg(Utils15.Is.isBooleanOrUndefined(noteOptions.dotted) || Utils15.Is.isIntegerGte(noteOptions.dotted, 0), "noteOptions.dotted", noteOptions.dotted);
7597
+ assertArg(Utils15.Is.isEnumValueOrUndefined(noteOptions.stem, Stem), "noteOptions.stem", noteOptions.stem);
7598
+ assertArg(Utils15.Is.isStringOrUndefined(noteOptions.color), "noteOptions.color", noteOptions.color);
7599
+ assertArg(Utils15.Is.isBooleanOrUndefined(noteOptions.arpeggio) || Utils15.Is.isEnumValue(noteOptions.arpeggio, Arpeggio), "noteOptions.arpeggio", noteOptions.arpeggio);
7600
+ assertArg(Utils15.Is.isBooleanOrUndefined(noteOptions.staccato), "noteOptions.staccato", noteOptions.staccato);
7601
+ assertArg(Utils15.Is.isBooleanOrUndefined(noteOptions.diamond), "noteOptions.diamond", noteOptions.diamond);
7602
+ assertArg(Utils15.Is.isBooleanOrUndefined(noteOptions.triplet), "noteOptions.triplet", noteOptions.triplet);
7603
+ assertArg(Utils15.Is.isUndefined(noteOptions.string) || isStringNumber(noteOptions.string) || Utils15.Is.isNonEmptyArray(noteOptions.string) && noteOptions.string.every((string) => isStringNumber(string)), "noteOptions.string", noteOptions.string);
7604
+ assertArg(Utils15.Is.isUndefined(noteOptions.tieSpan), 'NoteOptions.tieSpan was removed. Use addConnective("tie", tieSpan)', "");
7605
+ assertArg(Utils15.Is.isUndefined(noteOptions.slurSpan), 'NoteOptions.slurSpan was removed. Use addConnective("slur", slurSpan)', "");
7225
7606
  }
7226
7607
  function assertRestOptions(restOptions) {
7227
- assertArg(Utils14.Is.isObject(restOptions), "restOptions", restOptions);
7228
- assertArg(Utils14.Is.isBooleanOrUndefined(restOptions.dotted) || Utils14.Is.isIntegerGte(restOptions.dotted, 0), "restOptions.dotted", restOptions.dotted);
7229
- assertArg(Utils14.Is.isStringOrUndefined(restOptions.staffPos) || Utils14.Is.isInteger(restOptions.staffPos) || restOptions.staffPos instanceof Note10, "restOptions.staffPos", restOptions.staffPos);
7230
- assertArg(Utils14.Is.isStringOrUndefined(restOptions.color), "restOptions.color", restOptions.color);
7231
- assertArg(Utils14.Is.isBooleanOrUndefined(restOptions.hide), "restOptions.hide", restOptions.hide);
7232
- assertArg(Utils14.Is.isBooleanOrUndefined(restOptions.triplet), "restOptions.triplet", restOptions.triplet);
7608
+ assertArg(Utils15.Is.isObject(restOptions), "restOptions", restOptions);
7609
+ assertArg(Utils15.Is.isBooleanOrUndefined(restOptions.dotted) || Utils15.Is.isIntegerGte(restOptions.dotted, 0), "restOptions.dotted", restOptions.dotted);
7610
+ assertArg(Utils15.Is.isStringOrUndefined(restOptions.staffPos) || Utils15.Is.isInteger(restOptions.staffPos) || restOptions.staffPos instanceof Note10, "restOptions.staffPos", restOptions.staffPos);
7611
+ assertArg(Utils15.Is.isStringOrUndefined(restOptions.color), "restOptions.color", restOptions.color);
7612
+ assertArg(Utils15.Is.isBooleanOrUndefined(restOptions.hide), "restOptions.hide", restOptions.hide);
7613
+ assertArg(Utils15.Is.isBooleanOrUndefined(restOptions.triplet), "restOptions.triplet", restOptions.triplet);
7233
7614
  }
7234
7615
  function assertLyricsOptions(lyricsOptions) {
7235
- assertArg(Utils14.Is.isObject(lyricsOptions), "lyricsOptions", lyricsOptions);
7236
- assertArg(Utils14.Is.isEnumValueOrUndefined(lyricsOptions.align, LyricsAlign), "lyricsOptions.align", lyricsOptions.align);
7237
- assertArg(Utils14.Is.isEnumValueOrUndefined(lyricsOptions.hyphen, LyricsHyphen), "lyricsOptions.hyphen", lyricsOptions.hyphen);
7616
+ assertArg(Utils15.Is.isObject(lyricsOptions), "lyricsOptions", lyricsOptions);
7617
+ assertArg(Utils15.Is.isEnumValueOrUndefined(lyricsOptions.align, LyricsAlign), "lyricsOptions.align", lyricsOptions.align);
7618
+ assertArg(Utils15.Is.isEnumValueOrUndefined(lyricsOptions.hyphen, LyricsHyphen), "lyricsOptions.hyphen", lyricsOptions.hyphen);
7238
7619
  }
7239
7620
  function assertStaffTabOrGRoups(staffTabOrGroups) {
7240
7621
  assertArg(
7241
- Utils14.Is.isStringOrUndefined(staffTabOrGroups) || Utils14.Is.isIntegerGte(staffTabOrGroups, 0) || Utils14.Is.isNonEmptyArray(staffTabOrGroups) && staffTabOrGroups.every(
7242
- (staffTabOrGroup) => Utils14.Is.isString(staffTabOrGroup) || Utils14.Is.isIntegerGte(staffTabOrGroup, 0)
7622
+ Utils15.Is.isStringOrUndefined(staffTabOrGroups) || Utils15.Is.isIntegerGte(staffTabOrGroups, 0) || Utils15.Is.isNonEmptyArray(staffTabOrGroups) && staffTabOrGroups.every(
7623
+ (staffTabOrGroup) => Utils15.Is.isString(staffTabOrGroup) || Utils15.Is.isIntegerGte(staffTabOrGroup, 0)
7243
7624
  ),
7244
7625
  "staffTabOrGroup",
7245
7626
  staffTabOrGroups
@@ -7247,7 +7628,7 @@ function assertStaffTabOrGRoups(staffTabOrGroups) {
7247
7628
  }
7248
7629
  function isNoteLength(noteLen) {
7249
7630
  try {
7250
- validateNoteLength3(noteLen);
7631
+ validateNoteLength4(noteLen);
7251
7632
  return true;
7252
7633
  } catch (e) {
7253
7634
  return false;
@@ -7271,19 +7652,19 @@ var DocumentBuilder = class {
7271
7652
  this.doc = new ObjDocument();
7272
7653
  }
7273
7654
  setScoreConfiguration(config) {
7274
- if (Utils14.Is.isEnumValue(config, StaffPreset)) {
7655
+ if (Utils15.Is.isEnumValue(config, StaffPreset)) {
7275
7656
  this.doc.setScoreConfiguration(config);
7276
- } else if (Utils14.Is.isObject(config) && config.type === "staff") {
7657
+ } else if (Utils15.Is.isObject(config) && config.type === "staff") {
7277
7658
  assertStaffConfig(config);
7278
7659
  this.doc.setScoreConfiguration(config);
7279
- } else if (Utils14.Is.isObject(config) && config.type === "tab") {
7660
+ } else if (Utils15.Is.isObject(config) && config.type === "tab") {
7280
7661
  assertTabConfig(config);
7281
7662
  this.doc.setScoreConfiguration(config);
7282
- } else if (Utils14.Is.isNonEmptyArray(config)) {
7663
+ } else if (Utils15.Is.isNonEmptyArray(config)) {
7283
7664
  config.forEach((c) => {
7284
- if (Utils14.Is.isObject(c) && c.type === "staff") {
7665
+ if (Utils15.Is.isObject(c) && c.type === "staff") {
7285
7666
  assertStaffConfig(c);
7286
- } else if (Utils14.Is.isObject(c) && c.type === "tab") {
7667
+ } else if (Utils15.Is.isObject(c) && c.type === "tab") {
7287
7668
  assertTabConfig(c);
7288
7669
  } else {
7289
7670
  assertArg(false, "config", config);
@@ -7314,9 +7695,9 @@ var DocumentBuilder = class {
7314
7695
  * @returns - This document builder instance.
7315
7696
  */
7316
7697
  setHeader(title, composer, arranger) {
7317
- assertArg(Utils14.Is.isStringOrUndefined(title), "title", title);
7318
- assertArg(Utils14.Is.isStringOrUndefined(composer), "composer", composer);
7319
- assertArg(Utils14.Is.isStringOrUndefined(arranger), "arranger", arranger);
7698
+ assertArg(Utils15.Is.isStringOrUndefined(title), "title", title);
7699
+ assertArg(Utils15.Is.isStringOrUndefined(composer), "composer", composer);
7700
+ assertArg(Utils15.Is.isStringOrUndefined(arranger), "arranger", arranger);
7320
7701
  this.doc.setHeader(title, composer, arranger);
7321
7702
  return this;
7322
7703
  }
@@ -7326,7 +7707,7 @@ var DocumentBuilder = class {
7326
7707
  * @returns - This document builder instance.
7327
7708
  */
7328
7709
  setMeasuresPerRow(measuresPerRow) {
7329
- assertArg(Utils14.Is.isIntegerGte(measuresPerRow, 1) || Utils14.Is.isPosInfinity(measuresPerRow), "measuresPerRow", measuresPerRow);
7710
+ assertArg(Utils15.Is.isIntegerGte(measuresPerRow, 1) || Utils15.Is.isPosInfinity(measuresPerRow), "measuresPerRow", measuresPerRow);
7330
7711
  this.doc.setMeasuresPerRow(measuresPerRow);
7331
7712
  return this;
7332
7713
  }
@@ -7339,16 +7720,16 @@ var DocumentBuilder = class {
7339
7720
  return this;
7340
7721
  }
7341
7722
  setKeySignature(...args) {
7342
- assertArg(args[0] instanceof Scale2 || args[0] instanceof KeySignature3 || Utils14.Is.isNonEmptyString(args[0]) && (args.length === 1 || Utils14.Is.isEnumValue(args[1], ScaleType)), "keySignature", args);
7723
+ assertArg(args[0] instanceof Scale2 || args[0] instanceof KeySignature3 || Utils15.Is.isNonEmptyString(args[0]) && (args.length === 1 || Utils15.Is.isEnumValue(args[1], ScaleType)), "keySignature", args);
7343
7724
  this.getMeasure().setKeySignature(...args);
7344
7725
  return this;
7345
7726
  }
7346
7727
  setTimeSignature(...args) {
7347
7728
  if (args[0] instanceof TimeSignature2) {
7348
7729
  this.getMeasure().setTimeSignature(args[0]);
7349
- } else if (Utils14.Is.isEnumValue(args[0], TimeSignatures) && Utils14.Is.isEnumValueOrUndefined(args[1], BeamGrouping)) {
7730
+ } else if (Utils15.Is.isEnumValue(args[0], TimeSignatures) && Utils15.Is.isEnumValueOrUndefined(args[1], BeamGrouping)) {
7350
7731
  this.getMeasure().setTimeSignature(new TimeSignature2(args[0], args[1]));
7351
- } else if (Utils14.Is.isIntegerGte(args[0], 1) && Utils14.Is.isIntegerGte(args[1], 1) && Utils14.Is.isEnumValueOrUndefined(args[2], BeamGrouping)) {
7732
+ } else if (Utils15.Is.isIntegerGte(args[0], 1) && Utils15.Is.isIntegerGte(args[1], 1) && Utils15.Is.isEnumValueOrUndefined(args[2], BeamGrouping)) {
7352
7733
  this.getMeasure().setTimeSignature(new TimeSignature2(args[0], args[1], args[2]));
7353
7734
  } else {
7354
7735
  assertArg(false, "timeSignature args", args);
@@ -7356,12 +7737,12 @@ var DocumentBuilder = class {
7356
7737
  return this;
7357
7738
  }
7358
7739
  setTempo(beatsPerMinute, beatLength, dotted) {
7359
- assertArg(Utils14.Is.isIntegerGte(beatsPerMinute, 1), "beatsPerMinute", beatsPerMinute);
7740
+ assertArg(Utils15.Is.isIntegerGte(beatsPerMinute, 1), "beatsPerMinute", beatsPerMinute);
7360
7741
  if (beatLength === void 0) {
7361
- assertArg(Utils14.Is.isUndefined(dotted), "dotted", dotted);
7742
+ assertArg(Utils15.Is.isUndefined(dotted), "dotted", dotted);
7362
7743
  } else {
7363
- assertArg(Utils14.Is.isEnumValue(beatLength, NoteLength8) || isNoteLength(beatLength), "beatLength", beatLength);
7364
- assertArg(Utils14.Is.isBooleanOrUndefined(dotted) || Utils14.Is.isIntegerGte(dotted, 0), "dotted", dotted);
7744
+ assertArg(Utils15.Is.isEnumValue(beatLength, NoteLength9) || isNoteLength(beatLength), "beatLength", beatLength);
7745
+ assertArg(Utils15.Is.isBooleanOrUndefined(dotted) || Utils15.Is.isIntegerGte(dotted, 0), "dotted", dotted);
7365
7746
  }
7366
7747
  this.getMeasure().setTempo(beatsPerMinute, beatLength, dotted);
7367
7748
  return this;
@@ -7377,15 +7758,19 @@ var DocumentBuilder = class {
7377
7758
  addNote(voiceId, note, noteLength, noteOptions) {
7378
7759
  assertArg(isVoiceId(voiceId), "voiceId", voiceId);
7379
7760
  assertArg(
7380
- note instanceof Note10 || Utils14.Is.isNonEmptyString(note) || Utils14.Is.isArray(note) && note.every((note2) => note2 instanceof Note10 || Utils14.Is.isNonEmptyString(note2)),
7761
+ note instanceof Note10 || Utils15.Is.isNonEmptyString(note) || Utils15.Is.isArray(note) && note.every((note2) => note2 instanceof Note10 || Utils15.Is.isNonEmptyString(note2)),
7381
7762
  "note",
7382
7763
  note
7383
7764
  );
7384
- assertArg(Utils14.Is.isEnumValue(noteLength, NoteLength8) || isNoteLength(noteLength), "noteLength", noteLength);
7765
+ assertArg(Utils15.Is.isEnumValue(noteLength, NoteLength9) || isNoteLength(noteLength), "noteLength", noteLength);
7385
7766
  noteOptions != null ? noteOptions : noteOptions = {};
7386
7767
  assertNoteOptions(noteOptions);
7387
- if (Utils14.Is.isArray(note)) {
7388
- note.forEach((note2) => this.getMeasure().addNoteGroup(voiceId, [note2], noteLength, noteOptions));
7768
+ if (Utils15.Is.isArray(note)) {
7769
+ let string = noteOptions.string;
7770
+ note.forEach((note2, noteId) => {
7771
+ noteOptions.string = Utils15.Is.isArray(string) ? string[noteId] : string;
7772
+ this.getMeasure().addNoteGroup(voiceId, [note2], noteLength, noteOptions);
7773
+ });
7389
7774
  } else {
7390
7775
  this.getMeasure().addNoteGroup(voiceId, [note], noteLength, noteOptions);
7391
7776
  }
@@ -7401,8 +7786,8 @@ var DocumentBuilder = class {
7401
7786
  */
7402
7787
  addChord(voiceId, notes, noteLength, noteOptions) {
7403
7788
  assertArg(isVoiceId(voiceId), "voiceId", voiceId);
7404
- assertArg(Utils14.Is.isNonEmptyArray(notes) && notes.every((note) => note instanceof Note10 || Utils14.Is.isNonEmptyString(note)), "notes", notes);
7405
- assertArg(Utils14.Is.isEnumValue(noteLength, NoteLength8) || isNoteLength(noteLength), "noteLength", noteLength);
7789
+ assertArg(Utils15.Is.isNonEmptyArray(notes) && notes.every((note) => note instanceof Note10 || Utils15.Is.isNonEmptyString(note)), "notes", notes);
7790
+ assertArg(Utils15.Is.isEnumValue(noteLength, NoteLength9) || isNoteLength(noteLength), "noteLength", noteLength);
7406
7791
  noteOptions != null ? noteOptions : noteOptions = {};
7407
7792
  assertNoteOptions(noteOptions);
7408
7793
  this.getMeasure().addNoteGroup(voiceId, notes, noteLength, noteOptions);
@@ -7417,7 +7802,7 @@ var DocumentBuilder = class {
7417
7802
  */
7418
7803
  addRest(voiceId, restLength, restOptions) {
7419
7804
  assertArg(isVoiceId(voiceId), "voiceId", voiceId);
7420
- assertArg(Utils14.Is.isEnumValue(restLength, NoteLength8) || isNoteLength(restLength), "restLength", restLength);
7805
+ assertArg(Utils15.Is.isEnumValue(restLength, NoteLength9) || isNoteLength(restLength), "restLength", restLength);
7421
7806
  restOptions != null ? restOptions : restOptions = {};
7422
7807
  assertRestOptions(restOptions);
7423
7808
  this.getMeasure().addRest(voiceId, restLength, restOptions);
@@ -7440,22 +7825,24 @@ var DocumentBuilder = class {
7440
7825
  */
7441
7826
  addTuplet(voiceId, tupletRatio, tupletBuilder) {
7442
7827
  assertArg(isVoiceId(voiceId), "voiceId", voiceId);
7443
- assertArg(Utils14.Is.isFunction(tupletBuilder), "tupletBuilder", tupletBuilder);
7444
- assertArg(isTupletRatio(tupletRatio) && Utils14.Is.isBooleanOrUndefined(tupletRatio.showRatio), "tupletRatio", tupletRatio);
7828
+ assertArg(Utils15.Is.isFunction(tupletBuilder), "tupletBuilder", tupletBuilder);
7829
+ assertArg(isTupletRatio(tupletRatio) && Utils15.Is.isBooleanOrUndefined(tupletRatio.showRatio), "tupletRatio", tupletRatio);
7445
7830
  let tupletSymbols = [];
7446
7831
  const helper = {
7447
7832
  addNote: (note, noteLength, noteOptions) => {
7448
7833
  assertArg(
7449
- note instanceof Note10 || Utils14.Is.isNonEmptyString(note) || Utils14.Is.isArray(note) && note.every((note2) => note2 instanceof Note10 || Utils14.Is.isNonEmptyString(note2)),
7834
+ note instanceof Note10 || Utils15.Is.isNonEmptyString(note) || Utils15.Is.isArray(note) && note.every((note2) => note2 instanceof Note10 || Utils15.Is.isNonEmptyString(note2)),
7450
7835
  "note",
7451
7836
  note
7452
7837
  );
7453
- assertArg(Utils14.Is.isEnumValue(noteLength, NoteLength8) || isNoteLength(noteLength), "noteLength", noteLength);
7838
+ assertArg(Utils15.Is.isEnumValue(noteLength, NoteLength9) || isNoteLength(noteLength), "noteLength", noteLength);
7454
7839
  noteOptions != null ? noteOptions : noteOptions = {};
7455
7840
  delete noteOptions.triplet;
7456
7841
  assertNoteOptions(noteOptions);
7457
- if (Utils14.Is.isArray(note)) {
7458
- note.forEach((note2) => {
7842
+ if (Utils15.Is.isArray(note)) {
7843
+ let string = noteOptions.string;
7844
+ note.forEach((note2, noteId) => {
7845
+ noteOptions.string = Utils15.Is.isArray(string) ? string[noteId] : string;
7459
7846
  let s = this.getMeasure().addNoteGroup(voiceId, [note2], noteLength, noteOptions, tupletRatio);
7460
7847
  tupletSymbols.push(s);
7461
7848
  });
@@ -7466,8 +7853,8 @@ var DocumentBuilder = class {
7466
7853
  return helper;
7467
7854
  },
7468
7855
  addChord: (notes, noteLength, noteOptions) => {
7469
- assertArg(Utils14.Is.isNonEmptyArray(notes) && notes.every((note) => note instanceof Note10 || Utils14.Is.isNonEmptyString(note)), "notes", notes);
7470
- assertArg(Utils14.Is.isEnumValue(noteLength, NoteLength8) || isNoteLength(noteLength), "noteLength", noteLength);
7856
+ assertArg(Utils15.Is.isNonEmptyArray(notes) && notes.every((note) => note instanceof Note10 || Utils15.Is.isNonEmptyString(note)), "notes", notes);
7857
+ assertArg(Utils15.Is.isEnumValue(noteLength, NoteLength9) || isNoteLength(noteLength), "noteLength", noteLength);
7471
7858
  noteOptions != null ? noteOptions : noteOptions = {};
7472
7859
  delete noteOptions.triplet;
7473
7860
  assertNoteOptions(noteOptions);
@@ -7476,7 +7863,7 @@ var DocumentBuilder = class {
7476
7863
  return helper;
7477
7864
  },
7478
7865
  addRest: (restLength, restOptions) => {
7479
- assertArg(Utils14.Is.isEnumValue(restLength, NoteLength8) || isNoteLength(restLength), "restLength", restLength);
7866
+ assertArg(Utils15.Is.isEnumValue(restLength, NoteLength9) || isNoteLength(restLength), "restLength", restLength);
7480
7867
  restOptions != null ? restOptions : restOptions = {};
7481
7868
  delete restOptions.triplet;
7482
7869
  assertRestOptions(restOptions);
@@ -7493,8 +7880,8 @@ var DocumentBuilder = class {
7493
7880
  var _a;
7494
7881
  assertStaffTabOrGRoups(staffTabOrGroups);
7495
7882
  assertArg(isVerseNumber(verse), "verse", verse);
7496
- assertArg(Utils14.Is.isEnumValue(lyricsLength, NoteLength8), "lyricsLength", lyricsLength);
7497
- assertArg(Utils14.Is.isString(lyricsText) || Utils14.Is.isArray(lyricsText) && lyricsText.every((text) => Utils14.Is.isString(text)), "lyricsText", lyricsText);
7883
+ assertArg(Utils15.Is.isEnumValue(lyricsLength, NoteLength9), "lyricsLength", lyricsLength);
7884
+ assertArg(Utils15.Is.isString(lyricsText) || Utils15.Is.isArray(lyricsText) && lyricsText.every((text) => Utils15.Is.isString(text)), "lyricsText", lyricsText);
7498
7885
  lyricsOptions != null ? lyricsOptions : lyricsOptions = {};
7499
7886
  assertLyricsOptions(lyricsOptions);
7500
7887
  if (lyricsOptions.align !== void 0) {
@@ -7502,7 +7889,7 @@ var DocumentBuilder = class {
7502
7889
  } else {
7503
7890
  (_a = lyricsOptions.align) != null ? _a : lyricsOptions.align = this.currentLyricsAlign;
7504
7891
  }
7505
- if (Utils14.Is.isArray(lyricsText)) {
7892
+ if (Utils15.Is.isArray(lyricsText)) {
7506
7893
  lyricsText.forEach((text) => this.getMeasure().addLyrics(staffTabOrGroups, verse, lyricsLength, text, lyricsOptions));
7507
7894
  } else {
7508
7895
  this.getMeasure().addLyrics(staffTabOrGroups, verse, lyricsLength, lyricsText, lyricsOptions);
@@ -7534,7 +7921,7 @@ var DocumentBuilder = class {
7534
7921
  }
7535
7922
  addFermataInternal(staffTabOrGroups, fermata) {
7536
7923
  assertStaffTabOrGRoups(staffTabOrGroups);
7537
- assertArg(Utils14.Is.isEnumValue(fermata, Fermata), "fermata", fermata);
7924
+ assertArg(Utils15.Is.isEnumValue(fermata, Fermata), "fermata", fermata);
7538
7925
  this.getMeasure().addFermata(staffTabOrGroups, fermata);
7539
7926
  return this;
7540
7927
  }
@@ -7557,11 +7944,11 @@ var DocumentBuilder = class {
7557
7944
  }
7558
7945
  addNavigationInternal(staffTabOrGroups, navigation, ...args) {
7559
7946
  assertStaffTabOrGRoups(staffTabOrGroups);
7560
- assertArg(Utils14.Is.isEnumValue(navigation, Navigation), "navigation", navigation);
7947
+ assertArg(Utils15.Is.isEnumValue(navigation, Navigation), "navigation", navigation);
7561
7948
  if (navigation === "endRepeat" /* EndRepeat */ && args.length > 0) {
7562
- assertArg(Utils14.Is.isIntegerGte(args[0], 1), "playCount", args[0]);
7949
+ assertArg(Utils15.Is.isIntegerGte(args[0], 1), "playCount", args[0]);
7563
7950
  } else if (navigation === "ending" /* Ending */ && args.length > 0) {
7564
- assertArg(args.every((passage) => Utils14.Is.isIntegerGte(passage, 1)), "passages", args);
7951
+ assertArg(args.every((passage) => Utils15.Is.isIntegerGte(passage, 1)), "passages", args);
7565
7952
  }
7566
7953
  this.getMeasure().addNavigation(staffTabOrGroups, navigation, ...args);
7567
7954
  return this;
@@ -7575,11 +7962,11 @@ var DocumentBuilder = class {
7575
7962
  addAnnotationInternal(staffTabOrGroups, annotation, text) {
7576
7963
  annotation != null ? annotation : annotation = getAnnotation(text);
7577
7964
  if (annotation === void 0) {
7578
- throw new MusicError17(MusicErrorType17.Score, `Annotation text "${text}" is not known annotation.`);
7965
+ throw new MusicError18(MusicErrorType18.Score, `Annotation text "${text}" is not known annotation.`);
7579
7966
  }
7580
7967
  assertStaffTabOrGRoups(staffTabOrGroups);
7581
- assertArg(Utils14.Is.isEnumValue(annotation, Annotation), "annotation", annotation);
7582
- assertArg(Utils14.Is.isNonEmptyString(text), "text", text);
7968
+ assertArg(Utils15.Is.isEnumValue(annotation, Annotation), "annotation", annotation);
7969
+ assertArg(Utils15.Is.isNonEmptyString(text), "text", text);
7583
7970
  this.getMeasure().addAnnotation(staffTabOrGroups, annotation, text);
7584
7971
  return this;
7585
7972
  }
@@ -7599,8 +7986,8 @@ var DocumentBuilder = class {
7599
7986
  }
7600
7987
  addLabelInternal(staffTabOrGroups, label, text) {
7601
7988
  assertStaffTabOrGRoups(staffTabOrGroups);
7602
- assertArg(Utils14.Is.isEnumValue(label, Label), "label", label);
7603
- assertArg(Utils14.Is.isNonEmptyString(text), "text", text);
7989
+ assertArg(Utils15.Is.isEnumValue(label, Label), "label", label);
7990
+ assertArg(Utils15.Is.isNonEmptyString(text), "text", text);
7604
7991
  this.getMeasure().addLabel(staffTabOrGroups, label, text);
7605
7992
  return this;
7606
7993
  }
@@ -7624,21 +8011,21 @@ var DocumentBuilder = class {
7624
8011
  return this.addLabelInternal(staffTabOrGroups, label, text);
7625
8012
  }
7626
8013
  addConnective(connective, ...args) {
7627
- assertArg(Utils14.Is.isEnumValue(connective, Connective), "connective", connective);
8014
+ assertArg(Utils15.Is.isEnumValue(connective, Connective), "connective", connective);
7628
8015
  if (connective === "tie" /* Tie */) {
7629
- assertArg(Utils14.Is.isIntegerOrUndefined(args[0]) || Utils14.Is.isEnumValue(args[0], TieType), "tieSpan", args[0]);
7630
- assertArg(Utils14.Is.isEnumValueOrUndefined(args[1], NoteAnchor), "noteAnchor", args[1]);
8016
+ assertArg(Utils15.Is.isIntegerOrUndefined(args[0]) || Utils15.Is.isEnumValue(args[0], TieType), "tieSpan", args[0]);
8017
+ assertArg(Utils15.Is.isEnumValueOrUndefined(args[1], NoteAnchor), "noteAnchor", args[1]);
7631
8018
  let tieSpan = args[0];
7632
8019
  let noteAnchor = args[1];
7633
8020
  this.getMeasure().addConnective(connective, tieSpan, noteAnchor);
7634
8021
  } else if (connective === "slur" /* Slur */) {
7635
- assertArg(Utils14.Is.isIntegerOrUndefined(args[0]), "slurSpan", args[0]);
7636
- assertArg(Utils14.Is.isEnumValueOrUndefined(args[1], NoteAnchor), "noteAnchor", args[1]);
8022
+ assertArg(Utils15.Is.isIntegerOrUndefined(args[0]), "slurSpan", args[0]);
8023
+ assertArg(Utils15.Is.isEnumValueOrUndefined(args[1], NoteAnchor), "noteAnchor", args[1]);
7637
8024
  let slurSpan = args[0];
7638
8025
  let noteAnchor = args[1];
7639
8026
  this.getMeasure().addConnective(connective, slurSpan, noteAnchor);
7640
8027
  } else if (connective === "slide" /* Slide */) {
7641
- assertArg(Utils14.Is.isEnumValueOrUndefined(args[0], NoteAnchor), "noteAnchor", args[0]);
8028
+ assertArg(Utils15.Is.isEnumValueOrUndefined(args[0], NoteAnchor), "noteAnchor", args[0]);
7642
8029
  let noteAnchor = args[0];
7643
8030
  this.getMeasure().addConnective(connective, noteAnchor);
7644
8031
  }
@@ -7657,18 +8044,18 @@ var DocumentBuilder = class {
7657
8044
  * @returns - This document builder instance.
7658
8045
  */
7659
8046
  addExtension(extensionBuilder) {
7660
- assertArg(Utils14.Is.isFunctionOrUndefined(extensionBuilder), "addExtension() has new usage, for e.g. addExtension(ext => ext.measures(2)). Please refer to README or API Reference.", extensionBuilder);
8047
+ assertArg(Utils15.Is.isFunctionOrUndefined(extensionBuilder), "addExtension() has new usage, for e.g. addExtension(ext => ext.measures(2)). Please refer to README or API Reference.", extensionBuilder);
7661
8048
  let ticks = 0;
7662
8049
  let visible = true;
7663
8050
  const helper = {
7664
8051
  notes: (noteLength, noteCount) => {
7665
- assertArg(Utils14.Is.isEnumValue(noteLength, NoteLength8) || isNoteLength(noteLength), "noteLength", noteLength);
7666
- assertArg(Utils14.Is.isUndefined(noteCount) || Utils14.Is.isNumber(noteCount) && noteCount >= 0, "noteCount", noteCount);
8052
+ assertArg(Utils15.Is.isEnumValue(noteLength, NoteLength9) || isNoteLength(noteLength), "noteLength", noteLength);
8053
+ assertArg(Utils15.Is.isUndefined(noteCount) || Utils15.Is.isNumber(noteCount) && noteCount >= 0, "noteCount", noteCount);
7667
8054
  ticks += RhythmProps6.get(noteLength).ticks * (noteCount != null ? noteCount : 1);
7668
8055
  return helper;
7669
8056
  },
7670
8057
  measures: (measureCount) => {
7671
- assertArg(Utils14.Is.isNumber(measureCount) && measureCount >= 1, "measureCount", measureCount);
8058
+ assertArg(Utils15.Is.isNumber(measureCount) && measureCount >= 1, "measureCount", measureCount);
7672
8059
  ticks += this.getMeasure().getMeasureTicks() * measureCount;
7673
8060
  return helper;
7674
8061
  },
@@ -7697,13 +8084,13 @@ var DocumentBuilder = class {
7697
8084
  * @returns - This document builder instance.
7698
8085
  */
7699
8086
  addStaffGroup(groupName, staffsTabsAndGroups, verticalPosition = "auto" /* Auto */) {
7700
- assertArg(Utils14.Is.isNonEmptyString(groupName), "groupName", groupName);
8087
+ assertArg(Utils15.Is.isNonEmptyString(groupName), "groupName", groupName);
7701
8088
  assertArg(
7702
- Utils14.Is.isNonEmptyString(staffsTabsAndGroups) || Utils14.Is.isIntegerGte(staffsTabsAndGroups, 0) || Utils14.Is.isNonEmptyArray(staffsTabsAndGroups) && staffsTabsAndGroups.every((line) => Utils14.Is.isNonEmptyString(line) || Utils14.Is.isIntegerGte(line, 0)),
8089
+ Utils15.Is.isNonEmptyString(staffsTabsAndGroups) || Utils15.Is.isIntegerGte(staffsTabsAndGroups, 0) || Utils15.Is.isNonEmptyArray(staffsTabsAndGroups) && staffsTabsAndGroups.every((line) => Utils15.Is.isNonEmptyString(line) || Utils15.Is.isIntegerGte(line, 0)),
7703
8090
  "staffsTabsAndGroups",
7704
8091
  staffsTabsAndGroups
7705
8092
  );
7706
- assertArg(Utils14.Is.isEnumValue(verticalPosition, VerticalPosition), "verticalPosition", verticalPosition);
8093
+ assertArg(Utils15.Is.isEnumValue(verticalPosition, VerticalPosition), "verticalPosition", verticalPosition);
7707
8094
  this.doc.addStaffGroup(groupName, staffsTabsAndGroups, verticalPosition);
7708
8095
  return this;
7709
8096
  }
@@ -7738,7 +8125,7 @@ var DocumentBuilder = class {
7738
8125
  * @returns - This document builder instance.
7739
8126
  */
7740
8127
  completeRests(voiceId) {
7741
- assertArg(Utils14.Is.isUndefined(voiceId) || isVoiceId(voiceId) || Utils14.Is.isArray(voiceId) && voiceId.every((id) => isVoiceId(id)), "voiceId", voiceId);
8128
+ assertArg(Utils15.Is.isUndefined(voiceId) || isVoiceId(voiceId) || Utils15.Is.isArray(voiceId) && voiceId.every((id) => isVoiceId(id)), "voiceId", voiceId);
7742
8129
  this.getMeasure().completeRests(voiceId);
7743
8130
  return this;
7744
8131
  }
@@ -7750,8 +8137,8 @@ var DocumentBuilder = class {
7750
8137
  * @returns - This document builder instance.
7751
8138
  */
7752
8139
  addScaleArpeggio(scale, bottomNote, numOctaves) {
7753
- assertArg(Utils14.Is.isNonEmptyString(bottomNote), "bottomNote", bottomNote);
7754
- assertArg(Utils14.Is.isIntegerGte(numOctaves, 1), "numOctaves", numOctaves);
8140
+ assertArg(Utils15.Is.isNonEmptyString(bottomNote), "bottomNote", bottomNote);
8141
+ assertArg(Utils15.Is.isIntegerGte(numOctaves, 1), "numOctaves", numOctaves);
7755
8142
  let ts = this.getMeasure().getTimeSignature();
7756
8143
  let notes = scale.getScaleNotes(bottomNote, numOctaves);
7757
8144
  for (let i = 0; i < notes.length; i++) {
@@ -7767,7 +8154,7 @@ var DocumentBuilder = class {
7767
8154
  };
7768
8155
 
7769
8156
  // src/score/pub/event.ts
7770
- import { MusicError as MusicError18, MusicErrorType as MusicErrorType18 } from "@tspro/web-music-score/core";
8157
+ import { MusicError as MusicError19, MusicErrorType as MusicErrorType19 } from "@tspro/web-music-score/core";
7771
8158
  var ScoreEvent = class {
7772
8159
  /**
7773
8160
  * Create new score event instance.
@@ -7804,7 +8191,7 @@ var ScoreObjectEvent = class extends ScoreEvent {
7804
8191
  this.renderer = renderer;
7805
8192
  this.objects = objects;
7806
8193
  if (arguments.length === 0) {
7807
- throw new MusicError18(MusicErrorType18.Score, "Empty array in score object event!");
8194
+ throw new MusicError19(MusicErrorType19.Score, "Empty array in score object event!");
7808
8195
  }
7809
8196
  }
7810
8197
  /** Top object getter. */
@@ -7823,24 +8210,24 @@ var ScoreObjectEvent = class extends ScoreEvent {
7823
8210
 
7824
8211
  // src/score/pub/music-interface.ts
7825
8212
  import * as Audio2 from "@tspro/web-music-score/audio";
7826
- import { Utils as Utils16 } from "@tspro/ts-utils-lib";
8213
+ import { Utils as Utils17 } from "@tspro/ts-utils-lib";
7827
8214
 
7828
8215
  // src/score/pub/music-objects.ts
7829
- import { Utils as Utils15 } from "@tspro/ts-utils-lib";
7830
- import { MusicError as MusicError19, MusicErrorType as MusicErrorType19 } from "@tspro/web-music-score/core";
8216
+ import { Utils as Utils16 } from "@tspro/ts-utils-lib";
8217
+ import { MusicError as MusicError20, MusicErrorType as MusicErrorType20 } from "@tspro/web-music-score/core";
7831
8218
  function assertArg2(condition, argName, argValue) {
7832
8219
  if (!condition) {
7833
- throw new MusicError19(MusicErrorType19.Score, `Invalid arg: ${argName} = ${argValue}`);
8220
+ throw new MusicError20(MusicErrorType20.Score, `Invalid arg: ${argName} = ${argValue}`);
7834
8221
  }
7835
8222
  }
7836
8223
  function isVoiceId2(value) {
7837
- return Utils15.Is.isNumber(value) && getVoiceIds().indexOf(value) >= 0;
8224
+ return Utils16.Is.isNumber(value) && getVoiceIds().indexOf(value) >= 0;
7838
8225
  }
7839
8226
  function getNotationLine(line) {
7840
8227
  if (line instanceof ObjStaff || line instanceof ObjTab) {
7841
8228
  return line.getMusicInterface();
7842
8229
  } else {
7843
- throw new MusicError19(MusicErrorType19.Score, `Notation line not staff nor tab.`);
8230
+ throw new MusicError20(MusicErrorType20.Score, `Notation line not staff nor tab.`);
7844
8231
  }
7845
8232
  }
7846
8233
  var MusicInterface6 = class {
@@ -8010,7 +8397,7 @@ var _MDocument = class _MDocument extends MusicInterface6 {
8010
8397
  * @returns - Player instance.
8011
8398
  */
8012
8399
  play(playStateChangeListener) {
8013
- assertArg2(Utils15.Is.isFunctionOrUndefined(playStateChangeListener), "playStateChangeListener", playStateChangeListener);
8400
+ assertArg2(Utils16.Is.isFunctionOrUndefined(playStateChangeListener), "playStateChangeListener", playStateChangeListener);
8014
8401
  return new MPlayer(this, playStateChangeListener).play();
8015
8402
  }
8016
8403
  };
@@ -8040,7 +8427,7 @@ var _MEnding = class _MEnding extends MusicInterface6 {
8040
8427
  * @returns - Boolean whether this ending has asked passage number.
8041
8428
  */
8042
8429
  hasPassage(passage) {
8043
- assertArg2(Utils15.Is.isIntegerGte(passage, 1), "passage", passage);
8430
+ assertArg2(Utils16.Is.isIntegerGte(passage, 1), "passage", passage);
8044
8431
  return this.obj.hasPassage(passage);
8045
8432
  }
8046
8433
  };
@@ -8192,7 +8579,7 @@ var _MStaffTabBarLine = class _MStaffTabBarLine extends MusicInterface6 {
8192
8579
  if (barLine instanceof ObjBarLineLeft || barLine instanceof ObjBarLineRight) {
8193
8580
  return barLine.getMusicInterface();
8194
8581
  } else {
8195
- throw new MusicError19(MusicErrorType19.Score, `Bar line not let nor right.`);
8582
+ throw new MusicError20(MusicErrorType20.Score, `Bar line not let nor right.`);
8196
8583
  }
8197
8584
  }
8198
8585
  /**
@@ -8556,10 +8943,10 @@ var _MTab = class _MTab extends MusicInterface6 {
8556
8943
  /** Object name. */
8557
8944
  __publicField(_MTab, "Name", "Tab");
8558
8945
  var MTab = _MTab;
8559
- var _MSignature = class _MSignature extends MusicInterface6 {
8946
+ var _MStaffSignature = class _MStaffSignature extends MusicInterface6 {
8560
8947
  /** @internal */
8561
8948
  constructor(obj) {
8562
- super(_MSignature.Name);
8949
+ super(_MStaffSignature.Name);
8563
8950
  this.obj = obj;
8564
8951
  }
8565
8952
  /** @internal */
@@ -8575,8 +8962,57 @@ var _MSignature = class _MSignature extends MusicInterface6 {
8575
8962
  }
8576
8963
  };
8577
8964
  /** Object name. */
8578
- __publicField(_MSignature, "Name", "Signature");
8579
- var MSignature = _MSignature;
8965
+ __publicField(_MStaffSignature, "Name", "StaffSignature");
8966
+ var MStaffSignature = _MStaffSignature;
8967
+ var _MTabSignature = class _MTabSignature extends MusicInterface6 {
8968
+ /** @internal */
8969
+ constructor(obj) {
8970
+ super(_MTabSignature.Name);
8971
+ this.obj = obj;
8972
+ }
8973
+ /** @internal */
8974
+ getMusicObject() {
8975
+ return this.obj;
8976
+ }
8977
+ /**
8978
+ * Get tab notation line this signature is in.
8979
+ * @returns - Tab object.
8980
+ */
8981
+ getTab() {
8982
+ return this.obj.tab.getMusicInterface();
8983
+ }
8984
+ };
8985
+ /** Object name. */
8986
+ __publicField(_MTabSignature, "Name", "TabSignature");
8987
+ var MTabSignature = _MTabSignature;
8988
+ var _MTabRhythm = class _MTabRhythm extends MusicInterface6 {
8989
+ /** @internal */
8990
+ constructor(obj) {
8991
+ super(_MTabRhythm.Name);
8992
+ this.obj = obj;
8993
+ }
8994
+ /** @internal */
8995
+ getMusicObject() {
8996
+ return this.obj;
8997
+ }
8998
+ /**
8999
+ * Get measure.
9000
+ * @returns - Measure.
9001
+ */
9002
+ getMeasure() {
9003
+ return this.obj.measure.getMusicInterface();
9004
+ }
9005
+ /**
9006
+ * Get tab.
9007
+ * @returns - Tab.
9008
+ */
9009
+ getTab() {
9010
+ return this.obj.tab.getMusicInterface();
9011
+ }
9012
+ };
9013
+ /** Object name. */
9014
+ __publicField(_MTabRhythm, "Name", "TabRhythm");
9015
+ var MTabRhythm = _MTabRhythm;
8580
9016
  var _MSpecialText = class _MSpecialText extends MusicInterface6 {
8581
9017
  /** @internal */
8582
9018
  constructor(obj) {
@@ -8656,10 +9092,10 @@ __publicField(_MExtensionLine, "Name", "ExtensionLine");
8656
9092
  var MExtensionLine = _MExtensionLine;
8657
9093
 
8658
9094
  // src/score/pub/music-interface.ts
8659
- import { MusicError as MusicError20, MusicErrorType as MusicErrorType20 } from "@tspro/web-music-score/core";
9095
+ import { MusicError as MusicError21, MusicErrorType as MusicErrorType21 } from "@tspro/web-music-score/core";
8660
9096
  function assertArg3(condition, argName, argValue) {
8661
9097
  if (!condition) {
8662
- throw new MusicError20(MusicErrorType20.Score, `Invalid arg: ${argName} = ${argValue}`);
9098
+ throw new MusicError21(MusicErrorType21.Score, `Invalid arg: ${argName} = ${argValue}`);
8663
9099
  }
8664
9100
  }
8665
9101
  function require_t(t, message) {
@@ -8678,7 +9114,7 @@ var _MPlayer = class _MPlayer {
8678
9114
  constructor(doc, playStateChangeListener) {
8679
9115
  __publicField(this, "player");
8680
9116
  assertArg3(doc instanceof MDocument2, "doc", doc);
8681
- assertArg3(Utils16.Is.isFunctionOrUndefined(playStateChangeListener), "playStateChangeListener", playStateChangeListener);
9117
+ assertArg3(Utils17.Is.isFunctionOrUndefined(playStateChangeListener), "playStateChangeListener", playStateChangeListener);
8682
9118
  this.player = new Player();
8683
9119
  this.player.setDocument(doc.getMusicObject());
8684
9120
  this.player.setCursorPositionChangeListener((cursorRect) => doc.getMusicObject().updateCursorRect(cursorRect));
@@ -8736,7 +9172,7 @@ var MRenderer2 = class {
8736
9172
  * @returns - This renderer instance.
8737
9173
  */
8738
9174
  setDocument(doc) {
8739
- assertArg3(Utils16.Is.isUndefined(doc) || doc instanceof MDocument2, "doc", doc);
9175
+ assertArg3(Utils17.Is.isUndefined(doc) || doc instanceof MDocument2, "doc", doc);
8740
9176
  this.renderer.setDocument(doc);
8741
9177
  return this;
8742
9178
  }
@@ -8746,7 +9182,7 @@ var MRenderer2 = class {
8746
9182
  * @returns - This renderer instance.
8747
9183
  */
8748
9184
  setCanvas(canvas) {
8749
- canvas = require_t(Utils16.Dom.getCanvas(canvas), typeof canvas === "string" ? "Cannot set renderer canvas because invalid canvas id: " + canvas : "Cannot set renderer canvas because given canvas is undefined.");
9185
+ canvas = require_t(Utils17.Dom.getCanvas(canvas), typeof canvas === "string" ? "Cannot set renderer canvas because invalid canvas id: " + canvas : "Cannot set renderer canvas because given canvas is undefined.");
8750
9186
  this.renderer.setCanvas(canvas);
8751
9187
  return this;
8752
9188
  }
@@ -8755,7 +9191,7 @@ var MRenderer2 = class {
8755
9191
  * @param scoreEventListener - Score event listener.
8756
9192
  */
8757
9193
  setScoreEventListener(scoreEventListener) {
8758
- assertArg3(Utils16.Is.isFunctionOrUndefined(scoreEventListener), "scoreEventListener", scoreEventListener);
9194
+ assertArg3(Utils17.Is.isFunctionOrUndefined(scoreEventListener), "scoreEventListener", scoreEventListener);
8759
9195
  this.renderer.setScoreEventListener(scoreEventListener);
8760
9196
  }
8761
9197
  /**
@@ -8829,7 +9265,7 @@ var _MPlaybackButtons = class _MPlaybackButtons {
8829
9265
  * @returns
8830
9266
  */
8831
9267
  setDocument(doc) {
8832
- assertArg3(Utils16.Is.isUndefined(doc) || doc instanceof MDocument2, "doc", doc);
9268
+ assertArg3(Utils17.Is.isUndefined(doc) || doc instanceof MDocument2, "doc", doc);
8833
9269
  this.onStop();
8834
9270
  if (doc) {
8835
9271
  this.player = new MPlayer(doc, (playState) => {
@@ -8873,9 +9309,9 @@ var _MPlaybackButtons = class _MPlaybackButtons {
8873
9309
  * @returns - This playback buttons class instance.
8874
9310
  */
8875
9311
  setPlayButton(btn, btnLabel) {
8876
- assertArg3(Utils16.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
9312
+ assertArg3(Utils17.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
8877
9313
  _MPlaybackButtons.removeOnClickListeners(this.playButton, this.onPlay);
8878
- this.playButton = require_t(Utils16.Dom.getButton(btn), "Play button required!");
9314
+ this.playButton = require_t(Utils17.Dom.getButton(btn), "Play button required!");
8879
9315
  this.playLabel = btnLabel != null ? btnLabel : "Play";
8880
9316
  _MPlaybackButtons.removeOnClickListeners(this.playButton, "all");
8881
9317
  _MPlaybackButtons.addOnClickListener(this.playButton, this.onPlay);
@@ -8889,9 +9325,9 @@ var _MPlaybackButtons = class _MPlaybackButtons {
8889
9325
  * @returns - This playback buttons class instance.
8890
9326
  */
8891
9327
  setStopButton(btn, btnLabel) {
8892
- assertArg3(Utils16.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
9328
+ assertArg3(Utils17.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
8893
9329
  _MPlaybackButtons.removeOnClickListeners(this.stopButton, this.onStop);
8894
- this.stopButton = require_t(Utils16.Dom.getButton(btn), "Stop button required!");
9330
+ this.stopButton = require_t(Utils17.Dom.getButton(btn), "Stop button required!");
8895
9331
  this.stopLabel = btnLabel != null ? btnLabel : "Stop";
8896
9332
  _MPlaybackButtons.removeOnClickListeners(this.stopButton, "all");
8897
9333
  _MPlaybackButtons.addOnClickListener(this.stopButton, this.onStop);
@@ -8906,10 +9342,10 @@ var _MPlaybackButtons = class _MPlaybackButtons {
8906
9342
  * @returns - This playback buttons class instance.
8907
9343
  */
8908
9344
  setPlayStopButton(btn, playLabel, stopLabel) {
8909
- assertArg3(Utils16.Is.isStringOrUndefined(playLabel), "playLabel", playLabel);
8910
- assertArg3(Utils16.Is.isStringOrUndefined(stopLabel), "stopLabel", stopLabel);
9345
+ assertArg3(Utils17.Is.isStringOrUndefined(playLabel), "playLabel", playLabel);
9346
+ assertArg3(Utils17.Is.isStringOrUndefined(stopLabel), "stopLabel", stopLabel);
8911
9347
  _MPlaybackButtons.removeOnClickListeners(this.playStopButton, this.onPlayStop);
8912
- this.playStopButton = require_t(Utils16.Dom.getButton(btn), "Play/stop button required!");
9348
+ this.playStopButton = require_t(Utils17.Dom.getButton(btn), "Play/stop button required!");
8913
9349
  this.playLabel = playLabel != null ? playLabel : "Play";
8914
9350
  this.stopLabel = stopLabel != null ? stopLabel : "Stop";
8915
9351
  _MPlaybackButtons.removeOnClickListeners(this.playStopButton, "all");
@@ -8924,9 +9360,9 @@ var _MPlaybackButtons = class _MPlaybackButtons {
8924
9360
  * @returns - This playback buttons class instance.
8925
9361
  */
8926
9362
  setPauseButton(btn, btnLabel) {
8927
- assertArg3(Utils16.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
9363
+ assertArg3(Utils17.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
8928
9364
  _MPlaybackButtons.removeOnClickListeners(this.pauseButton, this.onPause);
8929
- this.pauseButton = require_t(Utils16.Dom.getButton(btn), "Pause button required!");
9365
+ this.pauseButton = require_t(Utils17.Dom.getButton(btn), "Pause button required!");
8930
9366
  this.pauseLabel = btnLabel != null ? btnLabel : "Pause";
8931
9367
  _MPlaybackButtons.removeOnClickListeners(this.pauseButton, "all");
8932
9368
  _MPlaybackButtons.addOnClickListener(this.pauseButton, this.onPause);
@@ -8948,7 +9384,7 @@ var _MPlaybackButtons = class _MPlaybackButtons {
8948
9384
  }
8949
9385
  }
8950
9386
  static addOnClickListener(btn, onClick) {
8951
- assertArg3(Utils16.Is.isFunction(onClick), "onClick", onClick);
9387
+ assertArg3(Utils17.Is.isFunction(onClick), "onClick", onClick);
8952
9388
  btn.addEventListener("click", onClick);
8953
9389
  let clickListeners = this.savedOnClickListeners.get(btn) || [];
8954
9390
  this.savedOnClickListeners.set(btn, [...clickListeners, onClick]);
@@ -8993,15 +9429,17 @@ export {
8993
9429
  MRest,
8994
9430
  MRhythmColumn,
8995
9431
  MScoreRow,
8996
- MSignature,
8997
9432
  MSpecialText,
8998
9433
  MStaff,
8999
9434
  MStaffBeamGroup,
9000
9435
  MStaffNoteGroup,
9001
9436
  MStaffRest,
9437
+ MStaffSignature,
9002
9438
  MStaffTabBarLine,
9003
9439
  MTab,
9004
9440
  MTabNoteGroup,
9441
+ MTabRhythm,
9442
+ MTabSignature,
9005
9443
  MText,
9006
9444
  MusicInterface6 as MusicInterface,
9007
9445
  Navigation,