@tspro/web-music-score 3.2.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/CHANGELOG.md +26 -10
  2. package/README.md +189 -331
  3. package/dist/audio/index.d.ts +1 -1
  4. package/dist/audio/index.js +1 -1
  5. package/dist/audio/index.mjs +2 -2
  6. package/dist/audio-cg/index.js +1 -1
  7. package/dist/audio-cg/index.mjs +2 -2
  8. package/dist/{chunk-LCTM7BID.mjs → chunk-D643HZHM.mjs} +2 -2
  9. package/dist/core/index.js +2 -2
  10. package/dist/core/index.mjs +3 -3
  11. package/dist/{guitar-C2Cp71NZ.d.ts → guitar-cNmE-EvH.d.ts} +1 -1
  12. package/dist/iife/index.global.js +11 -11
  13. package/dist/{interface-BlNl69uT.d.ts → interface-7k8qGG44.d.ts} +89 -81
  14. package/dist/{interface-Bn5HFt_U.d.mts → interface-XoKiryoV.d.mts} +88 -80
  15. package/dist/{note-BFa43I86.d.ts → note-CcVdUFqS.d.ts} +1 -1
  16. package/dist/pieces/index.d.mts +2 -2
  17. package/dist/pieces/index.d.ts +3 -3
  18. package/dist/pieces/index.js +4 -7
  19. package/dist/pieces/index.mjs +8 -11
  20. package/dist/react-ui/index.d.mts +3 -3
  21. package/dist/react-ui/index.d.ts +5 -5
  22. package/dist/react-ui/index.js +1 -1
  23. package/dist/react-ui/index.mjs +2 -2
  24. package/dist/{scale-DRR-t4Kr.d.mts → scale-C2pCNxdE.d.mts} +4 -3
  25. package/dist/{scale-ebJm37q1.d.ts → scale-CvPbJvfN.d.ts} +5 -4
  26. package/dist/score/index.d.mts +98 -31
  27. package/dist/score/index.d.ts +99 -32
  28. package/dist/score/index.js +748 -567
  29. package/dist/score/index.mjs +755 -574
  30. package/dist/tempo-BAYoZ_Li.d.mts +187 -0
  31. package/dist/tempo-r2sb6Ku2.d.ts +187 -0
  32. package/dist/theory/index.d.mts +3 -3
  33. package/dist/theory/index.d.ts +6 -6
  34. package/dist/theory/index.js +221 -78
  35. package/dist/theory/index.mjs +218 -76
  36. package/package.json +2 -2
  37. package/dist/tempo-B4h5Ktob.d.mts +0 -104
  38. package/dist/tempo-DgqDEsn0.d.ts +0 -104
@@ -1,7 +1,7 @@
1
- /* WebMusicScore v3.2.0 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
1
+ /* WebMusicScore v4.0.0 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
2
2
  import {
3
3
  __publicField
4
- } from "../chunk-LCTM7BID.mjs";
4
+ } from "../chunk-D643HZHM.mjs";
5
5
 
6
6
  // src/score/pub/div-rect.ts
7
7
  import { Utils } from "@tspro/ts-utils-lib";
@@ -277,16 +277,16 @@ var DivRect = class _DivRect {
277
277
  };
278
278
 
279
279
  // src/score/pub/document-builder.ts
280
- import { Utils as Utils11 } from "@tspro/ts-utils-lib";
280
+ import { Utils as Utils13 } from "@tspro/ts-utils-lib";
281
281
 
282
282
  // src/score/pub/types.ts
283
283
  var StaffPreset = /* @__PURE__ */ ((StaffPreset3) => {
284
- StaffPreset3[StaffPreset3["Treble"] = 1] = "Treble";
285
- StaffPreset3[StaffPreset3["Bass"] = 2] = "Bass";
286
- StaffPreset3[StaffPreset3["Grand"] = 3] = "Grand";
287
- StaffPreset3[StaffPreset3["GuitarTreble"] = 4] = "GuitarTreble";
288
- StaffPreset3[StaffPreset3["GuitarTab"] = 8] = "GuitarTab";
289
- StaffPreset3[StaffPreset3["GuitarCombined"] = 12] = "GuitarCombined";
284
+ StaffPreset3["Treble"] = "treble";
285
+ StaffPreset3["Bass"] = "bass";
286
+ StaffPreset3["Grand"] = "grand";
287
+ StaffPreset3["GuitarTreble"] = "guitarTreble";
288
+ StaffPreset3["GuitarTab"] = "guitarTab";
289
+ StaffPreset3["GuitarCombined"] = "guitarCombined";
290
290
  return StaffPreset3;
291
291
  })(StaffPreset || {});
292
292
  var Clef = /* @__PURE__ */ ((Clef2) => {
@@ -301,77 +301,77 @@ function getStringNumbers() {
301
301
  return [1, 2, 3, 4, 5, 6];
302
302
  }
303
303
  var Stem = /* @__PURE__ */ ((Stem2) => {
304
- Stem2[Stem2["Auto"] = 0] = "Auto";
305
- Stem2[Stem2["Up"] = 1] = "Up";
306
- Stem2[Stem2["Down"] = 2] = "Down";
304
+ Stem2["Auto"] = "auto";
305
+ Stem2["Up"] = "up";
306
+ Stem2["Down"] = "down";
307
307
  return Stem2;
308
308
  })(Stem || {});
309
309
  var Arpeggio = /* @__PURE__ */ ((Arpeggio2) => {
310
- Arpeggio2[Arpeggio2["Up"] = 0] = "Up";
311
- Arpeggio2[Arpeggio2["Down"] = 1] = "Down";
310
+ Arpeggio2["Up"] = "up";
311
+ Arpeggio2["Down"] = "down";
312
312
  return Arpeggio2;
313
313
  })(Arpeggio || {});
314
314
  var TieType = /* @__PURE__ */ ((TieType2) => {
315
- TieType2[TieType2["Stub"] = -1] = "Stub";
316
- TieType2[TieType2["ToMeasureEnd"] = -2] = "ToMeasureEnd";
315
+ TieType2["Stub"] = "stub";
316
+ TieType2["ToMeasureEnd"] = "toMeasureEnd";
317
317
  return TieType2;
318
318
  })(TieType || {});
319
319
  var NoteAnchor = /* @__PURE__ */ ((NoteAnchor2) => {
320
- NoteAnchor2[NoteAnchor2["Auto"] = 0] = "Auto";
321
- NoteAnchor2[NoteAnchor2["Above"] = 1] = "Above";
322
- NoteAnchor2[NoteAnchor2["Center"] = 2] = "Center";
323
- NoteAnchor2[NoteAnchor2["Below"] = 3] = "Below";
324
- NoteAnchor2[NoteAnchor2["StemTip"] = 4] = "StemTip";
320
+ NoteAnchor2["Auto"] = "auto";
321
+ NoteAnchor2["Above"] = "above";
322
+ NoteAnchor2["Center"] = "center";
323
+ NoteAnchor2["Below"] = "below";
324
+ NoteAnchor2["StemTip"] = "stemTip";
325
325
  return NoteAnchor2;
326
326
  })(NoteAnchor || {});
327
327
  var Connective = /* @__PURE__ */ ((Connective2) => {
328
- Connective2[Connective2["Tie"] = 0] = "Tie";
329
- Connective2[Connective2["Slur"] = 1] = "Slur";
330
- Connective2[Connective2["Slide"] = 2] = "Slide";
328
+ Connective2["Tie"] = "tie";
329
+ Connective2["Slur"] = "slur";
330
+ Connective2["Slide"] = "slide";
331
331
  return Connective2;
332
332
  })(Connective || {});
333
333
  var VerticalPosition = /* @__PURE__ */ ((VerticalPosition4) => {
334
- VerticalPosition4[VerticalPosition4["Above"] = 0] = "Above";
335
- VerticalPosition4[VerticalPosition4["Below"] = 1] = "Below";
336
- VerticalPosition4[VerticalPosition4["Both"] = 2] = "Both";
337
- VerticalPosition4[VerticalPosition4["Auto"] = 3] = "Auto";
334
+ VerticalPosition4["Auto"] = "auto";
335
+ VerticalPosition4["Above"] = "above";
336
+ VerticalPosition4["Below"] = "below";
337
+ VerticalPosition4["Both"] = "both";
338
338
  return VerticalPosition4;
339
339
  })(VerticalPosition || {});
340
- var PlayState = /* @__PURE__ */ ((PlayState2) => {
341
- PlayState2[PlayState2["Playing"] = 0] = "Playing";
342
- PlayState2[PlayState2["Paused"] = 1] = "Paused";
343
- PlayState2[PlayState2["Stopped"] = 2] = "Stopped";
344
- return PlayState2;
345
- })(PlayState || {});
346
340
  var Fermata = /* @__PURE__ */ ((Fermata2) => {
347
- Fermata2[Fermata2["AtNote"] = 0] = "AtNote";
348
- Fermata2[Fermata2["AtMeasureEnd"] = 1] = "AtMeasureEnd";
341
+ Fermata2["AtNote"] = "atNote";
342
+ Fermata2["AtMeasureEnd"] = "atMeasureEnd";
349
343
  return Fermata2;
350
344
  })(Fermata || {});
351
345
  var Navigation = /* @__PURE__ */ ((Navigation2) => {
352
- Navigation2[Navigation2["DC_al_Fine"] = 0] = "DC_al_Fine";
353
- Navigation2[Navigation2["DC_al_Coda"] = 1] = "DC_al_Coda";
354
- Navigation2[Navigation2["DS_al_Fine"] = 2] = "DS_al_Fine";
355
- Navigation2[Navigation2["DS_al_Coda"] = 3] = "DS_al_Coda";
356
- Navigation2[Navigation2["Coda"] = 4] = "Coda";
357
- Navigation2[Navigation2["toCoda"] = 5] = "toCoda";
358
- Navigation2[Navigation2["Segno"] = 6] = "Segno";
359
- Navigation2[Navigation2["Fine"] = 7] = "Fine";
360
- Navigation2[Navigation2["StartRepeat"] = 8] = "StartRepeat";
361
- Navigation2[Navigation2["EndRepeat"] = 9] = "EndRepeat";
362
- Navigation2[Navigation2["Ending"] = 10] = "Ending";
346
+ Navigation2["DC_al_Fine"] = "D.C. al Fine";
347
+ Navigation2["DC_al_Coda"] = "D.C. al Coda";
348
+ Navigation2["DS_al_Fine"] = "D.S. al Fine";
349
+ Navigation2["DS_al_Coda"] = "D.S. al Coda";
350
+ Navigation2["Coda"] = "Coda";
351
+ Navigation2["toCoda"] = "toCoda";
352
+ Navigation2["Segno"] = "Segno";
353
+ Navigation2["Fine"] = "Fine";
354
+ Navigation2["StartRepeat"] = "startRepeat";
355
+ Navigation2["EndRepeat"] = "endRepeat";
356
+ Navigation2["Ending"] = "ending";
363
357
  return Navigation2;
364
358
  })(Navigation || {});
365
359
  var Annotation = /* @__PURE__ */ ((Annotation2) => {
366
- Annotation2[Annotation2["Dynamics"] = 0] = "Dynamics";
367
- Annotation2[Annotation2["Tempo"] = 1] = "Tempo";
360
+ Annotation2["Dynamics"] = "dynamics";
361
+ Annotation2["Tempo"] = "tempo";
368
362
  return Annotation2;
369
363
  })(Annotation || {});
370
364
  var Label = /* @__PURE__ */ ((Label2) => {
371
- Label2[Label2["Note"] = 0] = "Note";
372
- Label2[Label2["Chord"] = 1] = "Chord";
365
+ Label2["Note"] = "note";
366
+ Label2["Chord"] = "chord";
373
367
  return Label2;
374
368
  })(Label || {});
369
+ var PlayState = /* @__PURE__ */ ((PlayState2) => {
370
+ PlayState2[PlayState2["Playing"] = 0] = "Playing";
371
+ PlayState2[PlayState2["Paused"] = 1] = "Paused";
372
+ PlayState2[PlayState2["Stopped"] = 2] = "Stopped";
373
+ return PlayState2;
374
+ })(PlayState || {});
375
375
 
376
376
  // src/score/engine/music-object.ts
377
377
  var MusicObjectLink = class {
@@ -870,11 +870,11 @@ var Renderer = class {
870
870
 
871
871
  // src/score/engine/obj-staff-and-tab.ts
872
872
  import { MusicError as MusicError15, MusicErrorType as MusicErrorType15 } from "@tspro/web-music-score/core";
873
- import { Utils as Utils9 } from "@tspro/ts-utils-lib";
873
+ import { Utils as Utils11 } from "@tspro/ts-utils-lib";
874
874
 
875
875
  // src/score/engine/obj-measure.ts
876
- import { Utils as Utils8 } from "@tspro/ts-utils-lib";
877
- import { getScale, Scale, validateScaleType, Note as Note7, NoteLength as NoteLength6, RhythmProps as RhythmProps4, KeySignature as KeySignature2, getDefaultKeySignature, PitchNotation, SymbolSet } from "@tspro/web-music-score/theory";
876
+ import { Utils as Utils10 } from "@tspro/ts-utils-lib";
877
+ import { getScale, Scale, validateScaleType, Note as Note7, RhythmProps as RhythmProps4, KeySignature as KeySignature2, getDefaultKeySignature, PitchNotation, SymbolSet, validateNoteLength, NoteLengthProps as NoteLengthProps4 } from "@tspro/web-music-score/theory";
878
878
  import { getDefaultTempo, TimeSignature, getDefaultTimeSignature } from "@tspro/web-music-score/theory";
879
879
 
880
880
  // src/score/engine/acc-state.ts
@@ -1462,12 +1462,12 @@ var ObjSignature = class extends MusicObject {
1462
1462
  };
1463
1463
 
1464
1464
  // src/score/engine/player.ts
1465
- import { Utils as Utils5 } from "@tspro/ts-utils-lib";
1465
+ import { Utils as Utils6 } from "@tspro/ts-utils-lib";
1466
1466
  import { NoteLength as NoteLength5, RhythmProps as RhythmProps3, alterTempoSpeed } from "@tspro/web-music-score/theory";
1467
1467
  import * as Audio from "@tspro/web-music-score/audio";
1468
1468
 
1469
1469
  // src/score/engine/obj-rhythm-column.ts
1470
- import { Note as Note5, NoteLength as NoteLength4 } from "@tspro/web-music-score/theory";
1470
+ import { Note as Note5 } from "@tspro/web-music-score/theory";
1471
1471
 
1472
1472
  // src/score/engine/obj-arpeggio.ts
1473
1473
  var ObjArpeggio = class extends MusicObject {
@@ -1492,8 +1492,8 @@ var ObjArpeggio = class extends MusicObject {
1492
1492
  }
1493
1493
  layout(renderer) {
1494
1494
  let { unitSize } = renderer;
1495
- this.topArrowHeight = this.arpeggioDir === 0 /* Up */ ? unitSize : 0;
1496
- this.bottomArrowHeight = this.arpeggioDir === 1 /* Down */ ? unitSize : 0;
1495
+ this.topArrowHeight = this.arpeggioDir === "up" /* Up */ ? unitSize : 0;
1496
+ this.bottomArrowHeight = this.arpeggioDir === "down" /* Down */ ? unitSize : 0;
1497
1497
  let top = this.line.getTopLineY();
1498
1498
  let bottom = this.line.getBottomLineY();
1499
1499
  this.cycleHeight = unitSize * 2;
@@ -1540,7 +1540,7 @@ var ObjArpeggio = class extends MusicObject {
1540
1540
  };
1541
1541
 
1542
1542
  // src/score/engine/obj-rest.ts
1543
- import { Note as Note3, NoteLength, RhythmProps } from "@tspro/web-music-score/theory";
1543
+ import { Note as Note3, NoteLength, NoteLengthProps, RhythmProps, Tuplet } from "@tspro/web-music-score/theory";
1544
1544
  import { MusicError as MusicError5, MusicErrorType as MusicErrorType5 } from "@tspro/web-music-score/core";
1545
1545
  function getDiatonicIdFromStaffPos(staffPos) {
1546
1546
  if (typeof staffPos === "number") {
@@ -1559,7 +1559,7 @@ var ObjStaffRest = class extends MusicObject {
1559
1559
  this.staff = staff;
1560
1560
  this.rest = rest;
1561
1561
  __publicField(this, "restRect", new DivRect());
1562
- __publicField(this, "dotRect");
1562
+ __publicField(this, "dotRects", []);
1563
1563
  __publicField(this, "mi");
1564
1564
  staff.addObject(this);
1565
1565
  this.mi = new MStaffRest(this);
@@ -1571,21 +1571,18 @@ var ObjStaffRest = class extends MusicObject {
1571
1571
  return this.getRect().contains(x, y) ? [this] : [];
1572
1572
  }
1573
1573
  offset(dx, dy) {
1574
- var _a;
1575
1574
  this.restRect.offsetInPlace(dx, dy);
1576
- (_a = this.dotRect) == null ? void 0 : _a.offsetInPlace(dx, dy);
1575
+ this.dotRects.forEach((r) => r.offsetInPlace(dx, dy));
1577
1576
  this.requestRectUpdate();
1578
1577
  this.rest.requestRectUpdate();
1579
1578
  }
1580
1579
  updateRect() {
1581
1580
  this.rect = this.restRect.copy();
1582
- if (this.dotRect) {
1583
- this.rect.expandInPlace(this.dotRect);
1584
- }
1581
+ this.dotRects.forEach((r) => this.rect.expandInPlace(r));
1585
1582
  }
1586
1583
  };
1587
1584
  var ObjRest = class extends MusicObject {
1588
- constructor(col, voiceId, noteLength, options) {
1585
+ constructor(col, voiceId, noteLength, options, tupletRatio) {
1589
1586
  var _a, _b;
1590
1587
  super(col);
1591
1588
  this.col = col;
@@ -1594,6 +1591,7 @@ var ObjRest = class extends MusicObject {
1594
1591
  __publicField(this, "ownDiatonicId");
1595
1592
  __publicField(this, "color");
1596
1593
  __publicField(this, "hide");
1594
+ __publicField(this, "oldStyleTriplet");
1597
1595
  __publicField(this, "rhythmProps");
1598
1596
  __publicField(this, "beamGroup");
1599
1597
  __publicField(this, "staffObjects", []);
@@ -1617,7 +1615,9 @@ var ObjRest = class extends MusicObject {
1617
1615
  }
1618
1616
  this.color = (_a = options == null ? void 0 : options.color) != null ? _a : "black";
1619
1617
  this.hide = (_b = options == null ? void 0 : options.hide) != null ? _b : false;
1620
- this.rhythmProps = new RhythmProps(noteLength, options == null ? void 0 : options.dotted, options == null ? void 0 : options.triplet);
1618
+ this.oldStyleTriplet = tupletRatio === void 0 && ((options == null ? void 0 : options.triplet) === true || NoteLengthProps.get(noteLength).isTriplet);
1619
+ 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;
1620
+ this.rhythmProps = RhythmProps.get(noteLength, dotCount, (tupletRatio != null ? tupletRatio : this.oldStyleTriplet) ? Tuplet.Triplet : void 0);
1621
1621
  this.mi = new MRest(this);
1622
1622
  }
1623
1623
  getMusicInterface() {
@@ -1635,15 +1635,9 @@ var ObjRest = class extends MusicObject {
1635
1635
  get noteLength() {
1636
1636
  return this.rhythmProps.noteLength;
1637
1637
  }
1638
- get dotted() {
1639
- return this.rhythmProps.dotted;
1640
- }
1641
1638
  get stemDir() {
1642
1639
  return this.beamGroup ? this.beamGroup.stemDir : this.ownStemDir;
1643
1640
  }
1644
- get triplet() {
1645
- return this.rhythmProps.triplet;
1646
- }
1647
1641
  getStaticObjects(line) {
1648
1642
  let staticObjects = [];
1649
1643
  this.staffObjects.forEach((obj) => {
@@ -1668,8 +1662,8 @@ var ObjRest = class extends MusicObject {
1668
1662
  getBeamGroup() {
1669
1663
  return this.beamGroup;
1670
1664
  }
1671
- setBeamGroup(beam) {
1672
- this.beamGroup = beam;
1665
+ setBeamGroup(beamGroup) {
1666
+ this.beamGroup = beamGroup;
1673
1667
  }
1674
1668
  resetBeamGroup() {
1675
1669
  this.beamGroup = void 0;
@@ -1678,7 +1672,7 @@ var ObjRest = class extends MusicObject {
1678
1672
  return this.staffObjects.map((obj) => {
1679
1673
  let staff = obj.staff;
1680
1674
  let x = obj.getRect().centerX;
1681
- let y = this.stemDir === 1 /* Up */ ? obj.getRect().top : obj.getRect().bottom;
1675
+ let y = this.stemDir === "up" /* Up */ ? obj.getRect().top : obj.getRect().bottom;
1682
1676
  let stemHeight = Math.abs(obj.getRect().centerY - y);
1683
1677
  return { staff, x, y, stemHeight };
1684
1678
  });
@@ -1719,7 +1713,7 @@ var ObjRest = class extends MusicObject {
1719
1713
  }
1720
1714
  let { unitSize } = renderer;
1721
1715
  let { ownDiatonicId } = this;
1722
- let { noteLength, dotted, flagCount } = this.rhythmProps;
1716
+ let { noteLength, dotCount, flagCount } = this.rhythmProps;
1723
1717
  let leftw = 0;
1724
1718
  let rightw = 0;
1725
1719
  let toph = 0;
@@ -1752,11 +1746,11 @@ var ObjRest = class extends MusicObject {
1752
1746
  }
1753
1747
  let obj = new ObjStaffRest(staff, this);
1754
1748
  obj.restRect = new DivRect(-leftw, 0, rightw, -toph, 0, bottomh);
1755
- if (dotted) {
1749
+ for (let i = 0; i < dotCount; i++) {
1756
1750
  let dotWidth = DocumentSettings.DotSize * unitSize;
1757
- let dotX = rightw + (DocumentSettings.RestDotSpace + DocumentSettings.DotSize / 2) * unitSize;
1751
+ let dotX = rightw + (DocumentSettings.RestDotSpace + DocumentSettings.DotSize * unitSize) + i * DocumentSettings.DotSize * unitSize * 1.5;
1758
1752
  let dotY = this.getRestDotVerticalDisplacement(noteLength) * unitSize;
1759
- obj.dotRect = DivRect.createCentered(dotX, dotY, dotWidth, dotWidth);
1753
+ obj.dotRects.push(DivRect.createCentered(dotX, dotY, dotWidth, dotWidth));
1760
1754
  }
1761
1755
  obj.offset(0, staff.getDiatonicIdY(ownDiatonicId));
1762
1756
  this.staffObjects.push(obj);
@@ -1790,7 +1784,7 @@ var ObjRest = class extends MusicObject {
1790
1784
  ctx.strokeStyle = ctx.fillStyle = color;
1791
1785
  ctx.lineWidth = lineWidth;
1792
1786
  this.staffObjects.forEach((obj) => {
1793
- let { dotRect, restRect } = obj;
1787
+ let { dotRects, restRect } = obj;
1794
1788
  let x = restRect.centerX;
1795
1789
  let y = restRect.centerY;
1796
1790
  if (noteLength === NoteLength.Whole) {
@@ -1855,20 +1849,20 @@ var ObjRest = class extends MusicObject {
1855
1849
  ctx.fill();
1856
1850
  }
1857
1851
  }
1858
- if (dotRect) {
1859
- renderer.fillCircle(dotRect.centerX, dotRect.centerY, dotRect.width / 2);
1860
- }
1852
+ dotRects.forEach((r) => {
1853
+ renderer.fillCircle(r.centerX, r.centerY, r.width / 2);
1854
+ });
1861
1855
  });
1862
1856
  }
1863
1857
  };
1864
1858
 
1865
1859
  // src/score/engine/obj-note-group.ts
1866
1860
  import { Utils as Utils4 } from "@tspro/ts-utils-lib";
1867
- import { Note as Note4, NoteLength as NoteLength3, RhythmProps as RhythmProps2 } from "@tspro/web-music-score/theory";
1861
+ import { Note as Note4, NoteLengthProps as NoteLengthProps3, RhythmProps as RhythmProps2, Tuplet as Tuplet3 } from "@tspro/web-music-score/theory";
1868
1862
 
1869
1863
  // src/score/engine/obj-beam-group.ts
1870
1864
  import { Utils as Utils3 } from "@tspro/ts-utils-lib";
1871
- import { MinNoteLength, NoteLength as NoteLength2 } from "@tspro/web-music-score/theory";
1865
+ import { NoteLength as NoteLength2, Tuplet as Tuplet2, NoteLengthProps as NoteLengthProps2 } from "@tspro/web-music-score/theory";
1872
1866
  import { MusicError as MusicError6, MusicErrorType as MusicErrorType6 } from "@tspro/web-music-score/core";
1873
1867
  var adjustBeamAngle = (dx, dy) => {
1874
1868
  let T = DocumentSettings.BeamAngleFactor;
@@ -1905,8 +1899,8 @@ var ObjStaffBeamGroup = class extends MusicObject {
1905
1899
  super(staff);
1906
1900
  this.staff = staff;
1907
1901
  this.beamGroup = beamGroup;
1908
- __publicField(this, "tripletNumber");
1909
- __publicField(this, "tripletNumberOffsetY", 0);
1902
+ __publicField(this, "tupletNumber");
1903
+ __publicField(this, "tupletNumberOffsetY", 0);
1910
1904
  __publicField(this, "points", []);
1911
1905
  __publicField(this, "mi");
1912
1906
  staff.addObject(this);
@@ -1921,48 +1915,47 @@ var ObjStaffBeamGroup = class extends MusicObject {
1921
1915
  offset(dx, dy) {
1922
1916
  var _a;
1923
1917
  this.points.forEach((p) => p.offset(dx, 0));
1924
- (_a = this.tripletNumber) == null ? void 0 : _a.offset(dx, dy);
1918
+ (_a = this.tupletNumber) == null ? void 0 : _a.offset(dx, dy);
1925
1919
  this.requestRectUpdate();
1926
1920
  this.beamGroup.requestRectUpdate();
1927
1921
  }
1928
1922
  updateRect() {
1929
1923
  if (this.points.length > 0) {
1930
1924
  this.rect = this.points[0].getRect().copy();
1931
- } else if (this.tripletNumber) {
1932
- this.rect = this.tripletNumber.getRect().copy();
1925
+ } else if (this.tupletNumber) {
1926
+ this.rect = this.tupletNumber.getRect().copy();
1933
1927
  }
1934
1928
  this.points.forEach((pt) => this.rect.expandInPlace(pt.getRect()));
1935
- if (this.tripletNumber) {
1936
- this.rect.expandInPlace(this.tripletNumber.getRect());
1929
+ if (this.tupletNumber) {
1930
+ this.rect.expandInPlace(this.tupletNumber.getRect());
1937
1931
  }
1938
1932
  }
1939
1933
  };
1940
1934
  var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
1941
- constructor(symbols, triplet) {
1935
+ constructor(symbols, tupletRatio) {
1942
1936
  super(symbols[0].measure);
1943
1937
  this.symbols = symbols;
1938
+ this.tupletRatio = tupletRatio;
1944
1939
  __publicField(this, "mi");
1945
1940
  __publicField(this, "type");
1946
1941
  __publicField(this, "staffObjects", []);
1947
1942
  this.mi = new MBeamGroup(this);
1943
+ let beamGroupName = tupletRatio ? "Tuplet" : "BeamGroup";
1948
1944
  if (!symbols.every((s) => s.measure === symbols[0].measure)) {
1949
- throw new MusicError6(MusicErrorType6.Score, "All beam group symbols are not in same measure.");
1945
+ throw new MusicError6(MusicErrorType6.Score, `All ${beamGroupName} symbols are not in same measure.`);
1950
1946
  } else if (symbols.length < 2) {
1951
- throw new MusicError6(MusicErrorType6.Score, "Beam group need minimum 2 symbols, but " + symbols.length + " given.");
1947
+ throw new MusicError6(MusicErrorType6.Score, `${beamGroupName} needs minimum 2 symbols, but ${symbols.length} given.`);
1952
1948
  }
1953
- if (triplet) {
1954
- if (!symbols.every((s) => s.triplet)) {
1955
- throw new MusicError6(MusicErrorType6.Score, "Not every symbol's triplet property is true.");
1956
- }
1949
+ if (tupletRatio !== void 0) {
1957
1950
  let isGroup = symbols.length < 3 || symbols.some((s) => !(s instanceof ObjNoteGroup)) || symbols.some((s) => s.rhythmProps.flagCount !== symbols[0].rhythmProps.flagCount);
1958
- if (symbols.length === 3 && symbols[0] instanceof ObjNoteGroup && symbols[symbols.length - 1] instanceof ObjNoteGroup && symbols[0].rhythmProps.flagCount === symbols[symbols.length - 1].rhythmProps.flagCount) {
1951
+ if (symbols.length >= 3 && symbols[0] instanceof ObjNoteGroup && symbols[symbols.length - 1] instanceof ObjNoteGroup && symbols[0].rhythmProps.flagCount === symbols[symbols.length - 1].rhythmProps.flagCount) {
1959
1952
  isGroup = false;
1960
1953
  }
1961
- if (symbols.some((s) => s.rhythmProps.noteLength >= NoteLength2.Quarter)) {
1954
+ if (symbols.some((s) => NoteLengthProps2.cmp(s.rhythmProps.noteLength, NoteLength2.Quarter) >= 0)) {
1962
1955
  isGroup = true;
1963
1956
  }
1964
- this.type = isGroup ? 2 /* TripletGroup */ : 1 /* TripletBeam */;
1965
- ObjNoteGroup.setTripletBeamCounts(this);
1957
+ this.type = isGroup ? 2 /* TupletGroup */ : 1 /* TupletBeam */;
1958
+ ObjNoteGroup.setTupletBeamCounts(this);
1966
1959
  } else {
1967
1960
  this.type = 0 /* RegularBeam */;
1968
1961
  }
@@ -1970,29 +1963,35 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
1970
1963
  symbols.forEach((s) => s.setBeamGroup(this));
1971
1964
  symbols[0].measure.addBeamGroup(this);
1972
1965
  } else {
1973
- throw new MusicError6(MusicErrorType6.Score, "Cannot add beam group because some symbol already has one.");
1966
+ throw new MusicError6(MusicErrorType6.Score, `Cannot add ${beamGroupName} because some symbol already has one.`);
1974
1967
  }
1975
1968
  }
1969
+ get showTupletRatio() {
1970
+ var _a;
1971
+ return ((_a = this.tupletRatio) == null ? void 0 : _a.showRatio) === true;
1972
+ }
1976
1973
  static createBeam(noteGroups) {
1977
1974
  if (noteGroups.length > 1) {
1978
- new _ObjBeamGroup(noteGroups, false);
1975
+ new _ObjBeamGroup(noteGroups, void 0);
1979
1976
  }
1980
1977
  }
1981
- static createTriplet(symbols) {
1982
- let MaxTripletNoteLenght = NoteLength2.Half;
1983
- let len = symbols.map((s) => s.rhythmProps.noteLength);
1984
- if (symbols.length == 2) {
1985
- if (len[0] <= MaxTripletNoteLenght && len[1] === len[0] / 2 && len[0] / 2 >= MinNoteLength || len[1] <= MaxTripletNoteLenght && len[0] === len[1] / 2 && len[1] / 2 >= MinNoteLength) {
1986
- new _ObjBeamGroup(symbols, true);
1987
- return true;
1988
- }
1989
- } else if (symbols.length === 3) {
1990
- if (len[0] <= MaxTripletNoteLenght && len.every((l) => l === len[0])) {
1991
- new _ObjBeamGroup(symbols, true);
1992
- return true;
1993
- }
1978
+ static createOldStyleTriplet(symbols) {
1979
+ let s2 = symbols.slice(0, 2);
1980
+ let n2 = s2.map((s) => s.rhythmProps.noteSize);
1981
+ if (s2.length === 2 && s2.every((s) => s.oldStyleTriplet && s.getBeamGroup() === void 0) && (n2[0] * 2 === n2[1] || n2[1] * 2 === n2[0])) {
1982
+ new _ObjBeamGroup(s2, Tuplet2.Triplet);
1983
+ return 2;
1994
1984
  }
1995
- return false;
1985
+ let s3 = symbols.slice(0, 3);
1986
+ let n3 = s3.map((s) => s.rhythmProps.noteSize);
1987
+ if (s3.length === 3 && s3.every((s) => s.oldStyleTriplet && s.getBeamGroup() === void 0) && n3.every((n) => n === n3[0])) {
1988
+ new _ObjBeamGroup(s3, Tuplet2.Triplet);
1989
+ return 3;
1990
+ }
1991
+ return 0;
1992
+ }
1993
+ static createTuplet(symbols, tupletRatio) {
1994
+ new _ObjBeamGroup(symbols, tupletRatio);
1996
1995
  }
1997
1996
  getMusicInterface() {
1998
1997
  return this.mi;
@@ -2018,8 +2017,8 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2018
2017
  getType() {
2019
2018
  return this.type;
2020
2019
  }
2021
- isTriplet() {
2022
- return this.type === 1 /* TripletBeam */ || this.type === 2 /* TripletGroup */;
2020
+ isTuplet() {
2021
+ return this.type === 1 /* TupletBeam */ || this.type === 2 /* TupletGroup */;
2023
2022
  }
2024
2023
  getSymbols() {
2025
2024
  return this.symbols;
@@ -2081,10 +2080,10 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2081
2080
  }
2082
2081
  let leftStemHeight = (_a = symbolStemHeight[0]) != null ? _a : 0;
2083
2082
  let rightStemHeight = (_b = symbolStemHeight[symbolStemHeight.length - 1]) != null ? _b : 0;
2084
- if (this.type !== 2 /* TripletGroup */) {
2083
+ if (this.type !== 2 /* TupletGroup */) {
2085
2084
  let leftDy = leftStemHeight < rightStemHeight ? Math.sqrt(rightStemHeight - leftStemHeight) : 0;
2086
2085
  let rightDy = rightStemHeight < leftStemHeight ? Math.sqrt(leftStemHeight - rightStemHeight) : 0;
2087
- if (stemDir === 1 /* Up */) {
2086
+ if (stemDir === "up" /* Up */) {
2088
2087
  leftDy *= -1;
2089
2088
  rightDy *= -1;
2090
2089
  }
@@ -2097,7 +2096,7 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2097
2096
  symbolY[symbolY.length - 1] += rightDy;
2098
2097
  }
2099
2098
  }
2100
- let groupLineDy = unitSize * 2 * (stemDir === 1 /* Up */ ? -1 : 1);
2099
+ let groupLineDy = unitSize * 2 * (stemDir === "up" /* Up */ ? -1 : 1);
2101
2100
  let centerY = (rightY + leftY) / 2;
2102
2101
  let halfDy = adjustBeamAngle(rightX - leftX, rightY - leftY) / 2;
2103
2102
  leftY = centerY - halfDy;
@@ -2108,9 +2107,9 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2108
2107
  if (symX !== void 0 && symY !== void 0) {
2109
2108
  let beamY = Utils3.Math.interpolateY(leftX, leftY, rightX, rightY, symX);
2110
2109
  let raiseY = symY - beamY;
2111
- if (stemDir === 1 /* Up */ && raiseY < 0) {
2110
+ if (stemDir === "up" /* Up */ && raiseY < 0) {
2112
2111
  raiseBeamY = Math.min(raiseBeamY, raiseY);
2113
- } else if (stemDir === 2 /* Down */ && raiseY > 0) {
2112
+ } else if (stemDir === "down" /* Down */ && raiseY > 0) {
2114
2113
  raiseBeamY = Math.max(raiseBeamY, raiseY);
2115
2114
  }
2116
2115
  }
@@ -2119,21 +2118,21 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2119
2118
  rightY += raiseBeamY;
2120
2119
  symbolY = symbolY.map((y) => y === void 0 ? void 0 : y + raiseBeamY);
2121
2120
  let obj = new ObjStaffBeamGroup(mainStaff, this);
2122
- if (this.type === 2 /* TripletGroup */) {
2121
+ if (this.type === 2 /* TupletGroup */) {
2123
2122
  let ef = unitSize / (rightX - leftX);
2124
2123
  let l = Utils3.Math.interpolateCoord(leftX, leftY + groupLineDy, rightX, rightY + groupLineDy, -ef);
2125
2124
  let r = Utils3.Math.interpolateCoord(leftX, leftY + groupLineDy, rightX, rightY + groupLineDy, 1 + ef);
2126
2125
  obj.points.push(new BeamPoint(leftStaff, this, leftSymbol, l.x, l.y));
2127
2126
  obj.points.push(new BeamPoint(rightStaff, this, rightSymbol, r.x, r.y));
2128
- obj.tripletNumberOffsetY = 0;
2129
- } else if (this.type === 0 /* RegularBeam */ || this.type === 1 /* TripletBeam */) {
2127
+ obj.tupletNumberOffsetY = 0;
2128
+ } else if (this.type === 0 /* RegularBeam */ || this.type === 1 /* TupletBeam */) {
2130
2129
  raiseBeamY *= 0.5;
2131
2130
  let { beamThickness } = renderer;
2132
2131
  const beamHeight = (i) => {
2133
2132
  let sym = symbols[i];
2134
2133
  if (sym instanceof ObjNoteGroup) {
2135
2134
  let beamCount = sym instanceof ObjNoteGroup ? Math.max(sym.getLeftBeamCount(), sym.getRightBeamCount()) : 0;
2136
- return DocumentSettings.BeamSeparation * unitSize * (this.stemDir === 1 /* Up */ ? beamCount - 1 : 0);
2135
+ return DocumentSettings.BeamSeparation * unitSize * (this.stemDir === "up" /* Up */ ? beamCount - 1 : 0);
2137
2136
  } else {
2138
2137
  return 0;
2139
2138
  }
@@ -2144,17 +2143,18 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2144
2143
  let symY = symbolY[i];
2145
2144
  if (symStaff && symX !== void 0 && symY !== void 0) {
2146
2145
  let pt = new BeamPoint(symStaff, this, sym, symX, symY);
2147
- pt.topBeamsHeight = beamThickness / 2 + (stemDir === 2 /* Down */ ? beamHeight(i) : 0);
2148
- pt.bottomBeamsHeight = beamThickness / 2 + (stemDir === 1 /* Up */ ? beamHeight(i) : 0);
2146
+ pt.topBeamsHeight = beamThickness / 2 + (stemDir === "down" /* Down */ ? beamHeight(i) : 0);
2147
+ pt.bottomBeamsHeight = beamThickness / 2 + (stemDir === "up" /* Up */ ? beamHeight(i) : 0);
2149
2148
  obj.points.push(pt);
2150
2149
  }
2151
2150
  });
2152
- obj.tripletNumberOffsetY = groupLineDy;
2151
+ obj.tupletNumberOffsetY = groupLineDy;
2153
2152
  }
2154
- if (this.isTriplet()) {
2155
- obj.tripletNumber = new ObjText(this, "3", 0.5, 0.5);
2156
- obj.tripletNumber.layout(renderer);
2157
- obj.tripletNumber.offset((leftX + rightX) / 2, (leftY + rightY) / 2 + obj.tripletNumberOffsetY);
2153
+ if (this.isTuplet() && this.tupletRatio) {
2154
+ let txt = this.showTupletRatio ? String(this.tupletRatio.parts) + ":" + String(this.tupletRatio.inTimeOf) : String(this.tupletRatio.parts);
2155
+ obj.tupletNumber = new ObjText(this, txt, 0.5, 0.5);
2156
+ obj.tupletNumber.layout(renderer);
2157
+ obj.tupletNumber.offset((leftX + rightX) / 2, (leftY + rightY) / 2 + obj.tupletNumberOffsetY);
2158
2158
  }
2159
2159
  if (obj.points.length >= 2) {
2160
2160
  this.staffObjects.push(obj);
@@ -2176,7 +2176,7 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2176
2176
  this.staffObjects.forEach((obj) => {
2177
2177
  let left = obj.points[0];
2178
2178
  let right = obj.points[obj.points.length - 1];
2179
- if (this.type !== 2 /* TripletGroup */) {
2179
+ if (this.type !== 2 /* TupletGroup */) {
2180
2180
  obj.points.forEach((pt) => {
2181
2181
  if (pt.symbol instanceof ObjNoteGroup) {
2182
2182
  if (pt !== left && pt !== right) {
@@ -2186,9 +2186,9 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2186
2186
  }
2187
2187
  });
2188
2188
  }
2189
- if (obj.tripletNumber) {
2190
- let y = (left.y + right.y) / 2 + obj.tripletNumberOffsetY;
2191
- obj.tripletNumber.offset(0, -obj.tripletNumber.getRect().centerY + y);
2189
+ if (obj.tupletNumber) {
2190
+ let y = (left.y + right.y) / 2 + obj.tupletNumberOffsetY;
2191
+ obj.tupletNumber.offset(0, -obj.tupletNumber.getRect().centerY + y);
2192
2192
  }
2193
2193
  });
2194
2194
  }
@@ -2200,21 +2200,21 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2200
2200
  let { unitSize, beamThickness, lineWidth } = renderer;
2201
2201
  let color = "black";
2202
2202
  this.staffObjects.forEach((obj) => {
2203
- if (this.type === 2 /* TripletGroup */) {
2203
+ if (this.type === 2 /* TupletGroup */) {
2204
2204
  let l = obj.points[0];
2205
2205
  let r = obj.points[obj.points.length - 1];
2206
2206
  if (l && r) {
2207
- let tf = obj.tripletNumber ? obj.tripletNumber.getRect().width / (r.x - l.x) * 1.2 : 0;
2207
+ let tf = obj.tupletNumber ? obj.tupletNumber.getRect().width / (r.x - l.x) * 1.2 : 0;
2208
2208
  let lc = Utils3.Math.interpolateCoord(l.x, l.y, r.x, r.y, 0.5 - tf / 2);
2209
2209
  let rc = Utils3.Math.interpolateCoord(l.x, l.y, r.x, r.y, 0.5 + tf / 2);
2210
- let tipH = this.stemDir === 1 /* Up */ ? unitSize : -unitSize;
2210
+ let tipH = this.stemDir === "up" /* Up */ ? unitSize : -unitSize;
2211
2211
  renderer.drawLine(l.x, l.y, lc.x, lc.y, color, lineWidth);
2212
2212
  renderer.drawLine(rc.x, rc.y, r.x, r.y, color, lineWidth);
2213
2213
  renderer.drawLine(l.x, l.y, l.x, l.y + tipH, color, lineWidth);
2214
2214
  renderer.drawLine(r.x, r.y, r.x, r.y + tipH, color, lineWidth);
2215
2215
  }
2216
- } else if (this.type === 0 /* RegularBeam */ || this.type === 1 /* TripletBeam */) {
2217
- let beamSeparation = DocumentSettings.BeamSeparation * unitSize * (this.stemDir === 1 /* Up */ ? 1 : -1);
2216
+ } else if (this.type === 0 /* RegularBeam */ || this.type === 1 /* TupletBeam */) {
2217
+ let beamSeparation = DocumentSettings.BeamSeparation * unitSize * (this.stemDir === "up" /* Up */ ? 1 : -1);
2218
2218
  let noteGroupPoints = obj.points.filter((p) => p.symbol instanceof ObjNoteGroup);
2219
2219
  for (let i = 0; i < noteGroupPoints.length - 1; i++) {
2220
2220
  let left = noteGroupPoints[i];
@@ -2241,8 +2241,8 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2241
2241
  }
2242
2242
  }
2243
2243
  }
2244
- if (obj.tripletNumber) {
2245
- obj.tripletNumber.draw(renderer);
2244
+ if (obj.tupletNumber) {
2245
+ obj.tupletNumber.draw(renderer);
2246
2246
  }
2247
2247
  });
2248
2248
  }
@@ -2250,6 +2250,12 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2250
2250
 
2251
2251
  // src/score/engine/obj-note-group.ts
2252
2252
  import { MusicError as MusicError7, MusicErrorType as MusicErrorType7 } from "@tspro/web-music-score/core";
2253
+ function getStem(stem) {
2254
+ return Utils4.Is.isEnumValue(stem, Stem) ? stem : void 0;
2255
+ }
2256
+ function getArpeggio(a) {
2257
+ return Utils4.Is.isEnumValue(a, Arpeggio) ? a : a === true ? "up" /* Up */ : void 0;
2258
+ }
2253
2259
  function sortNoteStringData(notes, strings) {
2254
2260
  let stringArr = Utils4.Arr.isArray(strings) ? strings : strings !== void 0 ? [strings] : [];
2255
2261
  let noteStringData = notes.map((note, i) => {
@@ -2261,9 +2267,6 @@ function sortNoteStringData(notes, strings) {
2261
2267
  strings: noteStringData.every((e) => e.string === void 0) ? void 0 : noteStringData.map((e) => e.string)
2262
2268
  };
2263
2269
  }
2264
- function solveArpeggio(a) {
2265
- return a === true || a === 0 /* Up */ ? 0 /* Up */ : a === 1 /* Down */ ? 1 /* Down */ : void 0;
2266
- }
2267
2270
  var ObjStaffNoteGroup = class extends MusicObject {
2268
2271
  constructor(staff, noteGroup) {
2269
2272
  super(staff);
@@ -2353,7 +2356,7 @@ var ObjTabNoteGroup = class extends MusicObject {
2353
2356
  }
2354
2357
  };
2355
2358
  var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2356
- constructor(col, voiceId, notes, noteLength, options) {
2359
+ constructor(col, voiceId, notes, noteLength, options, tupletRatio) {
2357
2360
  var _a, _b, _c;
2358
2361
  super(col);
2359
2362
  this.col = col;
@@ -2369,6 +2372,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2369
2372
  __publicField(this, "staccato");
2370
2373
  __publicField(this, "diamond");
2371
2374
  __publicField(this, "arpeggio");
2375
+ __publicField(this, "oldStyleTriplet");
2372
2376
  __publicField(this, "rhythmProps");
2373
2377
  __publicField(this, "startConnnectives", []);
2374
2378
  __publicField(this, "runningConnectives", []);
@@ -2386,13 +2390,15 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2386
2390
  this.minDiatonicId = this.notes[0].diatonicId;
2387
2391
  this.maxDiatonicId = this.notes[this.notes.length - 1].diatonicId;
2388
2392
  this.ownDiatonicId = this.measure.updateOwnDiatonicId(voiceId, Math.round((this.minDiatonicId + this.maxDiatonicId) / 2));
2389
- this.ownStemDir = this.measure.updateOwnStemDir(this, options == null ? void 0 : options.stem);
2393
+ this.ownStemDir = this.measure.updateOwnStemDir(this, getStem(options == null ? void 0 : options.stem));
2390
2394
  this.ownString = this.measure.updateOwnString(this, noteStringData.strings);
2391
2395
  this.color = (_a = options == null ? void 0 : options.color) != null ? _a : "black";
2392
2396
  this.staccato = (_b = options == null ? void 0 : options.staccato) != null ? _b : false;
2393
2397
  this.diamond = (_c = options == null ? void 0 : options.diamond) != null ? _c : false;
2394
- this.arpeggio = solveArpeggio(options == null ? void 0 : options.arpeggio);
2395
- this.rhythmProps = new RhythmProps2(noteLength, options == null ? void 0 : options.dotted, options == null ? void 0 : options.triplet);
2398
+ this.arpeggio = getArpeggio(options == null ? void 0 : options.arpeggio);
2399
+ this.oldStyleTriplet = tupletRatio === void 0 && ((options == null ? void 0 : options.triplet) === true || NoteLengthProps3.get(noteLength).isTriplet);
2400
+ 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;
2401
+ this.rhythmProps = RhythmProps2.get(noteLength, dotCount, (tupletRatio != null ? tupletRatio : this.oldStyleTriplet) ? Tuplet3.Triplet : void 0);
2396
2402
  this.mi = new MNoteGroup(this);
2397
2403
  }
2398
2404
  getMusicInterface() {
@@ -2410,16 +2416,13 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2410
2416
  get stemDir() {
2411
2417
  return this.beamGroup ? this.beamGroup.stemDir : this.ownStemDir;
2412
2418
  }
2413
- get triplet() {
2414
- return this.rhythmProps.triplet;
2415
- }
2416
2419
  enableConnective(line) {
2417
2420
  return line.containsVoiceId(this.voiceId) && (line instanceof ObjTab || line.containsDiatonicId(this.ownDiatonicId));
2418
2421
  }
2419
2422
  startConnective(connectiveProps) {
2420
- if (!this.row.hasStaff && connectiveProps.connective === 0 /* Tie */) {
2423
+ if (!this.row.hasStaff && connectiveProps.connective === "tie" /* Tie */) {
2421
2424
  throw new MusicError7(MusicErrorType7.Score, "Ties not implemented for guitar tabs alone, staff is required!");
2422
- } else if (!this.row.hasStaff && connectiveProps.connective === 1 /* Slur */) {
2425
+ } else if (!this.row.hasStaff && connectiveProps.connective === "slur" /* Slur */) {
2423
2426
  throw new MusicError7(MusicErrorType7.Score, "Slurs not implemented for guitar tabs alone, staff is required!");
2424
2427
  }
2425
2428
  this.startConnnectives.push(connectiveProps);
@@ -2478,7 +2481,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2478
2481
  let stemTip = obj.stemTip;
2479
2482
  let stemDir = this.stemDir;
2480
2483
  let hasStem = stemTip !== void 0;
2481
- let stemSide = !hasStem ? void 0 : stemDir === 1 /* Up */ ? "right" : "left";
2484
+ let stemSide = !hasStem ? void 0 : stemDir === "up" /* Up */ ? "right" : "left";
2482
2485
  let padding = noteHeadRect.height / 2;
2483
2486
  let centerX = noteHeadRect.centerX;
2484
2487
  let centerY = noteHeadRect.centerY;
@@ -2486,16 +2489,16 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2486
2489
  let rightX = noteHeadRect.right + padding;
2487
2490
  let aboveY = noteHeadRect.top - padding;
2488
2491
  let belowY = noteHeadRect.bottom + padding;
2489
- if (noteAnchor === 0 /* Auto */) {
2490
- noteAnchor = 3 /* Below */;
2491
- } else if (noteAnchor === 4 /* StemTip */ && !hasStem) {
2492
- noteAnchor = stemDir === 1 /* Up */ ? 1 /* Above */ : 3 /* Below */;
2492
+ if (noteAnchor === "auto" /* Auto */) {
2493
+ noteAnchor = "below" /* Below */;
2494
+ } else if (noteAnchor === "stemTip" /* StemTip */ && !hasStem) {
2495
+ noteAnchor = stemDir === "up" /* Up */ ? "above" /* Above */ : "below" /* Below */;
2493
2496
  }
2494
2497
  switch (noteAnchor) {
2495
- case 2 /* Center */:
2498
+ case "center" /* Center */:
2496
2499
  return side === "left" ? { x: rightX, y: centerY } : { x: leftX, y: centerY };
2497
- case 1 /* Above */:
2498
- if (!hasStem || stemDir === 2 /* Down */) {
2500
+ case "above" /* Above */:
2501
+ if (!hasStem || stemDir === "down" /* Down */) {
2499
2502
  return { x: centerX, y: aboveY };
2500
2503
  } else {
2501
2504
  return {
@@ -2503,8 +2506,8 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2503
2506
  y: aboveY
2504
2507
  };
2505
2508
  }
2506
- case 3 /* Below */:
2507
- if (!hasStem || stemDir === 1 /* Up */) {
2509
+ case "below" /* Below */:
2510
+ if (!hasStem || stemDir === "up" /* Up */) {
2508
2511
  return { x: centerX, y: belowY };
2509
2512
  } else {
2510
2513
  return {
@@ -2512,8 +2515,8 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2512
2515
  y: belowY
2513
2516
  };
2514
2517
  }
2515
- case 4 /* StemTip */:
2516
- return { x: centerX, y: stemTip.centerY + (stemDir === 1 /* Up */ ? -padding : padding) };
2518
+ case "stemTip" /* StemTip */:
2519
+ return { x: centerX, y: stemTip.centerY + (stemDir === "up" /* Up */ ? -padding : padding) };
2517
2520
  default:
2518
2521
  throw new MusicError7(MusicErrorType7.Score, "Invalid noteAnchor: " + noteAnchor);
2519
2522
  }
@@ -2528,7 +2531,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2528
2531
  let x = side === "right" ? r.left : r.right;
2529
2532
  let y;
2530
2533
  let s = 0.9;
2531
- if (connectiveProps.connective === 2 /* Slide */) {
2534
+ if (connectiveProps.connective === "slide" /* Slide */) {
2532
2535
  let leftFretNumber = connectiveProps.noteGroups[0].getFretNumber(obj, 0);
2533
2536
  let rightFretNumber = connectiveProps.noteGroups[1].getFretNumber(obj, 0);
2534
2537
  let slideUp = leftFretNumber === void 0 || rightFretNumber === void 0 || leftFretNumber <= rightFretNumber;
@@ -2582,7 +2585,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2582
2585
  this.runningConnectives = [];
2583
2586
  }
2584
2587
  getPlaySlur() {
2585
- let slurs = this.runningConnectives.filter((c) => c.connective === 1 /* Slur */).map((c) => c.startsWith(this) ? "first" : "slurred");
2588
+ let slurs = this.runningConnectives.filter((c) => c.connective === "slur" /* Slur */).map((c) => c.startsWith(this) ? "first" : "slurred");
2586
2589
  if (slurs.indexOf("first") >= 0) {
2587
2590
  return "first";
2588
2591
  } else if (slurs.indexOf("slurred") >= 0) {
@@ -2594,8 +2597,8 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2594
2597
  getBeamGroup() {
2595
2598
  return this.beamGroup;
2596
2599
  }
2597
- setBeamGroup(beam) {
2598
- this.beamGroup = beam;
2600
+ setBeamGroup(beamGroup) {
2601
+ this.beamGroup = beamGroup;
2599
2602
  }
2600
2603
  resetBeamGroup() {
2601
2604
  this.leftBeamCount = this.rightBeamCount = 0;
@@ -2606,19 +2609,19 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2606
2609
  var _a, _b, _c, _d;
2607
2610
  let staff = obj.staff;
2608
2611
  let x = (_b = (_a = obj.stemTip) == null ? void 0 : _a.centerX) != null ? _b : obj.noteHeadRects[0].centerX;
2609
- let y = (_d = (_c = obj.stemTip) == null ? void 0 : _c.centerY) != null ? _d : this.stemDir === 1 /* Up */ ? obj.getRect().top : obj.getRect().bottom;
2610
- let stemHeight = this.stemDir === 1 /* Up */ ? Math.abs(obj.noteHeadRects[0].centerY - y) : Math.abs(obj.noteHeadRects[obj.noteHeadRects.length - 1].centerY - y);
2612
+ let y = (_d = (_c = obj.stemTip) == null ? void 0 : _c.centerY) != null ? _d : this.stemDir === "up" /* Up */ ? obj.getRect().top : obj.getRect().bottom;
2613
+ let stemHeight = this.stemDir === "up" /* Up */ ? Math.abs(obj.noteHeadRects[0].centerY - y) : Math.abs(obj.noteHeadRects[obj.noteHeadRects.length - 1].centerY - y);
2611
2614
  return { staff, x, y, stemHeight };
2612
2615
  });
2613
2616
  }
2614
2617
  getStemHeight(renderer) {
2615
2618
  let { unitSize } = renderer;
2616
- let { noteLength, flagCount } = this.rhythmProps;
2617
- if (noteLength >= NoteLength3.Whole) {
2618
- return 0;
2619
- } else {
2619
+ let { flagCount, hasStem } = this.rhythmProps;
2620
+ if (hasStem) {
2620
2621
  let addY = this.hasBeamCount() ? DocumentSettings.BeamSeparation : DocumentSettings.FlagSeparation;
2621
2622
  return (DocumentSettings.StemHeight + Math.max(0, flagCount - 1) * addY) * unitSize;
2623
+ } else {
2624
+ return 0;
2622
2625
  }
2623
2626
  }
2624
2627
  hasBeamCount() {
@@ -2637,13 +2640,13 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2637
2640
  return staff.containsVoiceId(this.voiceId) && this.staffObjects.some((obj) => obj instanceof ObjStaffNoteGroup && obj.staff === staff);
2638
2641
  }
2639
2642
  getPlayTicks(note) {
2640
- let tiedTicks = this.runningConnectives.filter((c) => c.connective === 0 /* Tie */).map((tie) => {
2643
+ let tiedTicks = this.runningConnectives.filter((c) => c.connective === "tie" /* Tie */).map((tie) => {
2641
2644
  let tieNoteGroups = tie.noteGroups;
2642
2645
  let j = tieNoteGroups.indexOf(this);
2643
2646
  if (j < 0) {
2644
2647
  return 0;
2645
2648
  }
2646
- if (tie.span === -1 /* Stub */ || tie.span === -2 /* ToMeasureEnd */) {
2649
+ if (tie.span === "stub" /* Stub */ || tie.span === "toMeasureEnd" /* ToMeasureEnd */) {
2647
2650
  return Math.max(this.rhythmProps.ticks, this.measure.getMeasureTicks() - this.col.positionTicks);
2648
2651
  }
2649
2652
  let prev = tieNoteGroups[j - 1];
@@ -2670,7 +2673,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2670
2673
  this.requestRectUpdate();
2671
2674
  let { unitSize } = renderer;
2672
2675
  let { row, stemDir } = this;
2673
- let { dotted, flagCount } = this.rhythmProps;
2676
+ let { dotCount, flagCount, hasStem } = this.rhythmProps;
2674
2677
  let dotWidth = DocumentSettings.DotSize * unitSize;
2675
2678
  let noteHeadWidth = (this.diamond ? DocumentSettings.DiamondNoteHeadSize : DocumentSettings.NoteHeadWidth) * unitSize;
2676
2679
  let noteHeadHeight = (this.diamond ? DocumentSettings.DiamondNoteHeadSize : DocumentSettings.NoteHeadHeight) * unitSize;
@@ -2690,10 +2693,10 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2690
2693
  let noteX = this.col.getNoteHeadDisplacement(this, note) * noteHeadWidth;
2691
2694
  let noteY = noteStaff.getDiatonicIdY(note.diatonicId);
2692
2695
  let isNoteOnLine = noteStaff.isLine(note.diatonicId);
2693
- if (isBottomNote && stemDir === 1 /* Up */) stemBaseStaff = noteStaff;
2694
- if (isTopNote && stemDir === 1 /* Up */) stemTipStaff = noteStaff;
2695
- if (isBottomNote && stemDir === 2 /* Down */) stemTipStaff = noteStaff;
2696
- if (isTopNote && stemDir === 2 /* Down */) stemBaseStaff = noteStaff;
2696
+ if (isBottomNote && stemDir === "up" /* Up */) stemBaseStaff = noteStaff;
2697
+ if (isTopNote && stemDir === "up" /* Up */) stemTipStaff = noteStaff;
2698
+ if (isBottomNote && stemDir === "down" /* Down */) stemTipStaff = noteStaff;
2699
+ if (isTopNote && stemDir === "down" /* Down */) stemBaseStaff = noteStaff;
2697
2700
  let noteHeadRect = obj.noteHeadRects[noteIndex] = DivRect.createCentered(noteX, noteY, noteHeadWidth, noteHeadHeight);
2698
2701
  noteStaff.addObject(noteHeadRect);
2699
2702
  if (accState.needAccidental(note)) {
@@ -2704,21 +2707,21 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2704
2707
  }
2705
2708
  noteStaff.addObject(acc);
2706
2709
  }
2707
- if (dotted) {
2708
- let dotX = noteHeadRect.right + DocumentSettings.NoteDotSpace * unitSize + dotWidth / 2;
2710
+ for (let i = 0; i < dotCount; i++) {
2711
+ let dotX = noteHeadRect.right + DocumentSettings.NoteDotSpace * unitSize + dotWidth / 2 + i * dotWidth * 1.5;
2709
2712
  let dotY = noteY + this.getDotVerticalDisplacement(staff, note.diatonicId, stemDir) * unitSize;
2710
2713
  let r = DivRect.createCentered(dotX, dotY, dotWidth, dotWidth);
2711
2714
  obj.dotRects.push(r);
2712
2715
  noteStaff.addObject(r);
2713
2716
  }
2714
2717
  if (this.staccato) {
2715
- if (stemDir === 1 /* Up */ && isBottomNote) {
2718
+ if (stemDir === "up" /* Up */ && isBottomNote) {
2716
2719
  let dotX = noteX;
2717
2720
  let dotY = noteY + unitSize * (isNoteOnLine ? 3 : 2);
2718
2721
  let r = DivRect.createCentered(dotX, dotY, dotWidth, dotWidth);
2719
2722
  obj.dotRects.push(r);
2720
2723
  stemBaseStaff.addObject(r);
2721
- } else if (stemDir === 2 /* Down */ && isTopNote) {
2724
+ } else if (stemDir === "down" /* Down */ && isTopNote) {
2722
2725
  let dotX = noteX;
2723
2726
  let dotY = noteY - unitSize * (isNoteOnLine ? 3 : 2);
2724
2727
  let r = DivRect.createCentered(dotX, dotY, dotWidth, dotWidth);
@@ -2729,11 +2732,11 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2729
2732
  });
2730
2733
  let bottomNoteY = obj.noteHeadRects[0].centerY;
2731
2734
  let topNoteY = obj.noteHeadRects[obj.noteHeadRects.length - 1].centerY;
2732
- let stemX = stemDir === 1 /* Up */ ? noteHeadWidth / 2 : -noteHeadWidth / 2;
2735
+ let stemX = stemDir === "up" /* Up */ ? noteHeadWidth / 2 : -noteHeadWidth / 2;
2733
2736
  let stemHeight = this.getStemHeight(renderer);
2734
- let stemTipY = stemDir === 1 /* Up */ ? topNoteY - stemHeight : bottomNoteY + stemHeight;
2735
- let stemBaseY = stemDir === 1 /* Up */ ? bottomNoteY : topNoteY;
2736
- if (this.rhythmProps.hasStem()) {
2737
+ let stemTipY = stemDir === "up" /* Up */ ? topNoteY - stemHeight : bottomNoteY + stemHeight;
2738
+ let stemBaseY = stemDir === "up" /* Up */ ? bottomNoteY : topNoteY;
2739
+ if (hasStem) {
2737
2740
  obj.stemTip = new DivRect(stemX, stemX, stemTipY, stemTipY);
2738
2741
  obj.stemBase = new DivRect(stemX, stemX, stemBaseY, stemBaseY);
2739
2742
  stemTipStaff.addObject(obj.stemTip);
@@ -2744,7 +2747,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2744
2747
  let flagHeight = flagCount === 0 ? 0 : DocumentSettings.FlagHeight * unitSize;
2745
2748
  for (let i = 0; i < flagCount; i++) {
2746
2749
  let flagAddY = i * unitSize * DocumentSettings.FlagSeparation;
2747
- let r = obj.flagRects[i] = stemDir === 1 /* Up */ ? new DivRect(stemX, stemX + flagWidth, stemTipY + flagAddY, stemTipY + flagHeight + flagAddY) : new DivRect(stemX, stemX + flagWidth, stemTipY - flagHeight - flagAddY, stemTipY - flagAddY);
2750
+ let r = obj.flagRects[i] = stemDir === "up" /* Up */ ? new DivRect(stemX, stemX + flagWidth, stemTipY + flagAddY, stemTipY + flagHeight + flagAddY) : new DivRect(stemX, stemX + flagWidth, stemTipY - flagHeight - flagAddY, stemTipY - flagAddY);
2748
2751
  stemTipStaff.addObject(r);
2749
2752
  }
2750
2753
  }
@@ -2757,7 +2760,6 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2757
2760
  }
2758
2761
  let obj = new ObjTabNoteGroup(tab, this);
2759
2762
  this.notes.forEach((note, noteIndex) => {
2760
- var _a, _b;
2761
2763
  if (this.ownString[noteIndex] !== void 0) {
2762
2764
  let stringId = this.ownString[noteIndex] - 1;
2763
2765
  let fretId = note.chromaticId - tab.getTuningStrings()[stringId].chromaticId;
@@ -2765,9 +2767,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2765
2767
  let fretNumber = new ObjText(this, { text: String(fretId), color, bgcolor: "white" }, 0.5, 0.5);
2766
2768
  obj.fretNumbers.push(fretNumber);
2767
2769
  fretNumber.layout(renderer);
2768
- let noteX = this.col.getNoteHeadDisplacement(this, note) * noteHeadWidth;
2769
- let stemX = (_b = (_a = this.staffObjects[0]) == null ? void 0 : _a.stemBase) == null ? void 0 : _b.centerX;
2770
- let x = stemX != null ? stemX : noteX;
2770
+ let x = this.col.getRect().centerX;
2771
2771
  let y = tab.getStringY(stringId);
2772
2772
  fretNumber.offset(x, y);
2773
2773
  }
@@ -2810,15 +2810,22 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2810
2810
  renderer.drawDebugRect(this.getRect());
2811
2811
  let { lineWidth } = renderer;
2812
2812
  let { color, stemDir } = this;
2813
- let { noteLength } = this.rhythmProps;
2813
+ let { isSolidNoteHead } = this.rhythmProps;
2814
2814
  this.staffObjects.forEach((obj) => {
2815
2815
  obj.accidentals.forEach((d) => d.draw(renderer));
2816
2816
  ctx.strokeStyle = ctx.fillStyle = color;
2817
2817
  ctx.lineWidth = lineWidth;
2818
2818
  obj.noteHeadRects.forEach((r) => {
2819
- let outlinedNoteHead = noteLength >= NoteLength3.Half;
2820
2819
  if (this.diamond) {
2821
- if (outlinedNoteHead) {
2820
+ if (isSolidNoteHead) {
2821
+ ctx.beginPath();
2822
+ ctx.moveTo(r.centerX, r.top);
2823
+ ctx.lineTo(r.right, r.centerY);
2824
+ ctx.lineTo(r.centerX, r.bottom);
2825
+ ctx.lineTo(r.left, r.centerY);
2826
+ ctx.lineTo(r.centerX, r.top);
2827
+ ctx.fill();
2828
+ } else {
2822
2829
  ctx.beginPath();
2823
2830
  ctx.lineWidth = lineWidth * 2.5;
2824
2831
  ctx.moveTo(r.centerX, r.top);
@@ -2833,22 +2840,14 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2833
2840
  ctx.moveTo(r.centerX, r.top);
2834
2841
  ctx.lineTo(r.left, r.centerY);
2835
2842
  ctx.stroke();
2836
- } else {
2837
- ctx.beginPath();
2838
- ctx.moveTo(r.centerX, r.top);
2839
- ctx.lineTo(r.right, r.centerY);
2840
- ctx.lineTo(r.centerX, r.bottom);
2841
- ctx.lineTo(r.left, r.centerY);
2842
- ctx.lineTo(r.centerX, r.top);
2843
- ctx.fill();
2844
2843
  }
2845
2844
  } else {
2846
2845
  ctx.beginPath();
2847
2846
  ctx.ellipse(r.centerX, r.centerY, r.leftw, r.toph, -0.3, 0, Math.PI * 2);
2848
- if (outlinedNoteHead) {
2849
- ctx.stroke();
2850
- } else {
2847
+ if (isSolidNoteHead) {
2851
2848
  ctx.fill();
2849
+ } else {
2850
+ ctx.stroke();
2852
2851
  }
2853
2852
  }
2854
2853
  });
@@ -2863,8 +2862,8 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2863
2862
  let left = rect.left;
2864
2863
  let right = rect.right;
2865
2864
  let width = right - left;
2866
- let top = stemDir === 1 /* Up */ ? rect.top : rect.bottom;
2867
- let bottom = stemDir === 1 /* Up */ ? rect.bottom : rect.top;
2865
+ let top = stemDir === "up" /* Up */ ? rect.top : rect.bottom;
2866
+ let bottom = stemDir === "up" /* Up */ ? rect.bottom : rect.top;
2868
2867
  ctx.beginPath();
2869
2868
  ctx.moveTo(left, top);
2870
2869
  ctx.bezierCurveTo(
@@ -2878,13 +2877,13 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2878
2877
  ctx.stroke();
2879
2878
  });
2880
2879
  });
2881
- this.tabObjects.forEach((obj) => {
2882
- obj.fretNumbers.forEach((fn) => fn.draw(renderer));
2883
- });
2880
+ this.tabObjects.forEach((obj) => obj.fretNumbers.forEach((fn) => fn.draw(renderer)));
2884
2881
  }
2885
2882
  static setBeamCounts(groupNotes) {
2886
2883
  const isADottedBHalf = (a, b) => {
2887
- return a.rhythmProps.noteLength === b.rhythmProps.noteLength * 2 && a.rhythmProps.dotted && !b.rhythmProps.dotted && a.rhythmProps.flagCount > 0 && b.rhythmProps.flagCount > 0;
2884
+ let { flagCount: aFlagCount, noteSize: aNoteSize, dotCount: aDotCount } = a.rhythmProps;
2885
+ let { flagCount: bFlagCount, noteSize: bNoteSize, dotCount: bDotCount } = b.rhythmProps;
2886
+ return aFlagCount > 0 && bFlagCount > 0 && aDotCount > 0 && bDotCount === 0 && aNoteSize * Math.pow(2, aDotCount) === bNoteSize;
2888
2887
  };
2889
2888
  for (let i = 0; i < groupNotes.length; i++) {
2890
2889
  let center = groupNotes[i];
@@ -2930,29 +2929,27 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2930
2929
  }
2931
2930
  } while (fixAgain);
2932
2931
  }
2933
- static setTripletBeamCounts(triplet) {
2934
- let type = triplet.getType();
2935
- let symbols = triplet.getSymbols();
2936
- if (type === 1 /* TripletBeam */) {
2932
+ static setTupletBeamCounts(tuplet) {
2933
+ let type = tuplet.getType();
2934
+ let symbols = tuplet.getSymbols();
2935
+ if (type === 1 /* TupletBeam */) {
2937
2936
  symbols.forEach((s, i) => {
2938
2937
  if (s instanceof _ObjNoteGroup) {
2939
2938
  s.leftBeamCount = i === 0 ? 0 : s.rhythmProps.flagCount;
2940
2939
  s.rightBeamCount = i === symbols.length - 1 ? 0 : s.rhythmProps.flagCount;
2941
2940
  }
2942
2941
  });
2943
- } else if (type === 2 /* TripletGroup */) {
2942
+ } else if (type === 2 /* TupletGroup */) {
2944
2943
  symbols.forEach((s) => {
2945
2944
  if (s instanceof _ObjNoteGroup) {
2946
2945
  s.leftBeamCount = s.rightBeamCount = 0;
2947
2946
  }
2948
2947
  });
2949
- } else {
2950
- throw new MusicError7(MusicErrorType7.Score, "Cannot set triplet beam count because triplet beam group type is invalid.");
2951
2948
  }
2952
2949
  }
2953
2950
  getDotVerticalDisplacement(staff, diatonicId, stemDir) {
2954
2951
  if (staff.isLine(diatonicId)) {
2955
- return stemDir === 1 /* Up */ ? -1 : 1;
2952
+ return stemDir === "up" /* Up */ ? -1 : 1;
2956
2953
  } else {
2957
2954
  return 0;
2958
2955
  }
@@ -2977,7 +2974,7 @@ import { MusicError as MusicError8, MusicErrorType as MusicErrorType8 } from "@t
2977
2974
  var noteHeadDataCompareFunc = (a, b) => {
2978
2975
  let cmp = Note5.compareFunc(a.note, b.note);
2979
2976
  if (cmp === 0) {
2980
- cmp = a.noteGroup.stemDir === b.noteGroup.stemDir ? 0 : a.noteGroup.stemDir === 1 /* Up */ ? 1 : -1;
2977
+ cmp = a.noteGroup.stemDir === b.noteGroup.stemDir ? 0 : a.noteGroup.stemDir === "up" /* Up */ ? 1 : -1;
2981
2978
  }
2982
2979
  return cmp;
2983
2980
  };
@@ -3090,16 +3087,14 @@ var ObjRhythmColumn = class extends MusicObject {
3090
3087
  }
3091
3088
  getArpeggioDir() {
3092
3089
  var _a;
3093
- return (_a = this.arpeggioDir) != null ? _a : 0 /* Up */;
3090
+ return (_a = this.arpeggioDir) != null ? _a : "up" /* Up */;
3094
3091
  }
3095
3092
  setVoiceSymbol(voiceId, symbol) {
3096
3093
  validateVoiceId(voiceId);
3097
3094
  this.voiceSymbol[voiceId] = symbol;
3098
- if (symbol instanceof ObjRest) {
3099
- if (!symbol.hide && symbol.noteLength >= NoteLength4.Half) {
3100
- this.minDiatonicId = this.minDiatonicId === void 0 ? symbol.ownDiatonicId : Math.min(this.minDiatonicId, symbol.ownDiatonicId);
3101
- this.maxDiatonicId = this.maxDiatonicId === void 0 ? symbol.ownDiatonicId : Math.max(this.maxDiatonicId, symbol.ownDiatonicId);
3102
- }
3095
+ if (symbol instanceof ObjRest && !symbol.hide) {
3096
+ this.minDiatonicId = this.minDiatonicId === void 0 ? symbol.ownDiatonicId : Math.min(this.minDiatonicId, symbol.ownDiatonicId);
3097
+ this.maxDiatonicId = this.maxDiatonicId === void 0 ? symbol.ownDiatonicId : Math.max(this.maxDiatonicId, symbol.ownDiatonicId);
3103
3098
  } else if (symbol instanceof ObjNoteGroup) {
3104
3099
  this.minDiatonicId = this.minDiatonicId === void 0 ? symbol.notes[0].diatonicId : Math.min(this.minDiatonicId, symbol.notes[0].diatonicId);
3105
3100
  this.maxDiatonicId = this.maxDiatonicId === void 0 ? symbol.notes[symbol.notes.length - 1].diatonicId : Math.max(this.maxDiatonicId, symbol.notes[symbol.notes.length - 1].diatonicId);
@@ -3115,15 +3110,18 @@ var ObjRhythmColumn = class extends MusicObject {
3115
3110
  return this.voiceSymbol[voiceId];
3116
3111
  }
3117
3112
  getMinWidth() {
3118
- let maxNoteLength = Math.max(...this.voiceSymbol.map((s) => s.rhythmProps.noteLength));
3113
+ let maxNoteSize = Math.max(...this.voiceSymbol.map((s) => s.rhythmProps.noteSize));
3119
3114
  let w = DocumentSettings.NoteHeadWidth;
3120
- switch (maxNoteLength) {
3121
- case NoteLength4.Whole:
3115
+ switch (maxNoteSize) {
3116
+ case 1:
3122
3117
  return w * 5;
3123
- case NoteLength4.Half:
3118
+ // whole note
3119
+ case 2:
3124
3120
  return w * 3;
3125
- case NoteLength4.Quarter:
3121
+ // half note
3122
+ case 4:
3126
3123
  return w * 2;
3124
+ // quarter note
3127
3125
  default:
3128
3126
  return w;
3129
3127
  }
@@ -3155,7 +3153,7 @@ var ObjRhythmColumn = class extends MusicObject {
3155
3153
  if (cur.displacement !== void 0) {
3156
3154
  continue;
3157
3155
  }
3158
- let d = cur.noteGroup.stemDir === 2 /* Down */ ? -1 : 1;
3156
+ let d = cur.noteGroup.stemDir === "down" /* Down */ ? -1 : 1;
3159
3157
  if (prev && cur.note.diatonicId - prev.note.diatonicId <= 1) {
3160
3158
  cur.displacement = prev.displacement === 0 ? d : 0;
3161
3159
  } else if (next && next.note.diatonicId - cur.note.diatonicId <= 1) {
@@ -3209,7 +3207,7 @@ var ObjRhythmColumn = class extends MusicObject {
3209
3207
  }
3210
3208
  });
3211
3209
  playerNotes.sort((a, b) => Note5.compareFunc(a.note, b.note));
3212
- if (this.hasArpeggio() && this.getArpeggioDir() === 1 /* Down */) {
3210
+ if (this.hasArpeggio() && this.getArpeggioDir() === "down" /* Down */) {
3213
3211
  playerNotes.reverse();
3214
3212
  }
3215
3213
  return playerNotes;
@@ -3326,6 +3324,9 @@ var ObjRhythmColumn = class extends MusicObject {
3326
3324
  }
3327
3325
  };
3328
3326
 
3327
+ // src/score/engine/element-data.ts
3328
+ import { Utils as Utils5 } from "@tspro/ts-utils-lib";
3329
+
3329
3330
  // src/score/engine/obj-special-text.ts
3330
3331
  var _ObjSpecialText = class _ObjSpecialText extends MusicObject {
3331
3332
  constructor(parent, text) {
@@ -3423,36 +3424,71 @@ __publicField(_ObjSpecialText, "Segno", "\u{1D10B}");
3423
3424
  var ObjSpecialText = _ObjSpecialText;
3424
3425
 
3425
3426
  // src/score/engine/element-data.ts
3426
- function getNavigationString(n) {
3427
- switch (n) {
3428
- case 1 /* DC_al_Coda */:
3427
+ function getNavigationString(navigation) {
3428
+ switch (navigation) {
3429
+ case "D.C. al Coda" /* DC_al_Coda */:
3429
3430
  return "D.C. al Coda";
3430
- case 0 /* DC_al_Fine */:
3431
+ case "D.C. al Fine" /* DC_al_Fine */:
3431
3432
  return "D.C. al Fine";
3432
- case 3 /* DS_al_Coda */:
3433
+ case "D.S. al Coda" /* DS_al_Coda */:
3433
3434
  return "D.S. al Coda";
3434
- case 2 /* DS_al_Fine */:
3435
+ case "D.S. al Fine" /* DS_al_Fine */:
3435
3436
  return "D.S. al Fine";
3436
- case 7 /* Fine */:
3437
+ case "Fine" /* Fine */:
3437
3438
  return "Fine";
3438
- case 6 /* Segno */:
3439
+ case "Segno" /* Segno */:
3439
3440
  return ObjSpecialText.Segno;
3440
- case 4 /* Coda */:
3441
+ case "Coda" /* Coda */:
3441
3442
  return ObjSpecialText.Coda;
3442
- case 5 /* toCoda */:
3443
+ case "toCoda" /* toCoda */:
3443
3444
  return ObjSpecialText.toCoda;
3444
3445
  default:
3445
- return Navigation[n];
3446
+ return navigation[0].toUpperCase() + navigation.substring(1);
3446
3447
  }
3447
3448
  }
3449
+ var DynamicsAnnotations = /* @__PURE__ */ ((DynamicsAnnotations2) => {
3450
+ DynamicsAnnotations2["cresc"] = "cresc.";
3451
+ DynamicsAnnotations2["decresc"] = "decresc.";
3452
+ DynamicsAnnotations2["dim"] = "dim.";
3453
+ DynamicsAnnotations2["ppp"] = "ppp";
3454
+ DynamicsAnnotations2["pp"] = "pp";
3455
+ DynamicsAnnotations2["p"] = "p";
3456
+ DynamicsAnnotations2["mp"] = "mp";
3457
+ DynamicsAnnotations2["m"] = "m";
3458
+ DynamicsAnnotations2["mf"] = "mf";
3459
+ DynamicsAnnotations2["f"] = "f";
3460
+ DynamicsAnnotations2["ff"] = "ff";
3461
+ DynamicsAnnotations2["fff"] = "fff";
3462
+ return DynamicsAnnotations2;
3463
+ })(DynamicsAnnotations || {});
3464
+ var TempoAnnotations = /* @__PURE__ */ ((TempoAnnotations2) => {
3465
+ TempoAnnotations2["accel"] = "accel.";
3466
+ TempoAnnotations2["rit"] = "rit.";
3467
+ TempoAnnotations2["a_tempo"] = "a tempo";
3468
+ return TempoAnnotations2;
3469
+ })(TempoAnnotations || {});
3448
3470
  function isDynamicsText(text) {
3449
- return ["ppp", "pp", "p", "mp", "m", "mf", "f", "ff", "fff", "cresc.", "decresc.", "dim."].indexOf(text) >= 0;
3471
+ return Utils5.Is.isEnumValue(text, DynamicsAnnotations);
3450
3472
  }
3451
- function isDynamicsLevelText(text) {
3452
- return ["ppp", "pp", "p", "mp", "m", "mf", "f", "ff", "fff"].indexOf(text) >= 0;
3473
+ function getDynamicsVolume(text) {
3474
+ if (/^(p+|f+|m|mp|mf)$/.test(text)) {
3475
+ let volume = 0.5 - Utils5.Str.charCount(text, "p") * 0.1 + Utils5.Str.charCount(text, "f") * 0.1;
3476
+ return Utils5.Math.clamp(volume, 0, 1);
3477
+ } else {
3478
+ return void 0;
3479
+ }
3453
3480
  }
3454
3481
  function isTempoText(text) {
3455
- return ["accel.", "rit.", "a tempo"].indexOf(text) >= 0;
3482
+ return Utils5.Is.isEnumValue(text, TempoAnnotations);
3483
+ }
3484
+ function getAnnotation(text) {
3485
+ if (Utils5.Is.isEnumValue(text, DynamicsAnnotations)) {
3486
+ return "dynamics" /* Dynamics */;
3487
+ } else if (Utils5.Is.isEnumValue(text, TempoAnnotations)) {
3488
+ return "tempo" /* Tempo */;
3489
+ } else {
3490
+ return void 0;
3491
+ }
3456
3492
  }
3457
3493
 
3458
3494
  // src/score/engine/extension.ts
@@ -3511,7 +3547,7 @@ var Extension = class extends MusicObjectLink {
3511
3547
  if (prevMeasure.hasEndSection() || prevMeasure.hasEndSong()) {
3512
3548
  return "section-break";
3513
3549
  }
3514
- let elemArr = [9 /* EndRepeat */, 10 /* Ending */];
3550
+ let elemArr = ["endRepeat" /* EndRepeat */, "ending" /* Ending */];
3515
3551
  for (let i = 0; i < elemArr.length; i++) {
3516
3552
  if (prevMeasure.hasNavigation(elemArr[i])) {
3517
3553
  return "section-break";
@@ -3572,35 +3608,12 @@ var RitardandoSpeedDiv = 2;
3572
3608
  var CrescendoVolumeAdd = 0.5;
3573
3609
  var DiminuendoVolumeSub = 0.5;
3574
3610
  function calcTicksDuration(ticks, tempo) {
3575
- let beatTicks = new RhythmProps3(tempo.options.beatLength, tempo.options.dotted).ticks;
3611
+ let beatTicks = RhythmProps3.get(tempo.options.beatLength, tempo.options.dotCount).ticks;
3576
3612
  let ticksPerMinute = tempo.beatsPerMinute * beatTicks;
3577
3613
  return 60 * ticks / ticksPerMinute;
3578
3614
  }
3579
- function getVolume(dynamicsLevelText) {
3580
- switch (dynamicsLevelText) {
3581
- case "fff":
3582
- return 0.9;
3583
- case "ff":
3584
- return 0.8;
3585
- case "f":
3586
- return 0.7;
3587
- case "mf":
3588
- return 0.6;
3589
- default:
3590
- case "m":
3591
- return 0.5;
3592
- case "mp":
3593
- return 0.4;
3594
- case "p":
3595
- return 0.3;
3596
- case "pp":
3597
- return 0.2;
3598
- case "ppp":
3599
- return 0.1;
3600
- }
3601
- }
3602
3615
  function getDefaultVolume() {
3603
- return getVolume("m");
3616
+ return getDynamicsVolume("m");
3604
3617
  }
3605
3618
  function adjustVolume(linearVolume) {
3606
3619
  return linearVolume * 1.25;
@@ -3628,7 +3641,7 @@ var PlayerColumnProps = class {
3628
3641
  return this.speed;
3629
3642
  }
3630
3643
  getTempo() {
3631
- let speed = Utils5.Math.clamp(this.getSpeed(), 0.1, 10);
3644
+ let speed = Utils6.Math.clamp(this.getSpeed(), 0.1, 10);
3632
3645
  return alterTempoSpeed(this.measure.getTempo(), speed);
3633
3646
  }
3634
3647
  setVolume(volume) {
@@ -3653,7 +3666,7 @@ var PlayerColumnProps = class {
3653
3666
  if (symbolsTicks.length === 0) {
3654
3667
  return 0;
3655
3668
  } else {
3656
- return Utils5.Math.sum(symbolsTicks) / symbolsTicks.length;
3669
+ return Utils6.Math.sum(symbolsTicks) / symbolsTicks.length;
3657
3670
  }
3658
3671
  }
3659
3672
  }
@@ -3716,34 +3729,34 @@ var Player = class _Player {
3716
3729
  continue;
3717
3730
  }
3718
3731
  measureSequence.push(curMeasure);
3719
- if (curMeasure.hasNavigation(8 /* StartRepeat */)) {
3732
+ if (curMeasure.hasNavigation("startRepeat" /* StartRepeat */)) {
3720
3733
  startRepeatMeasure = curMeasure;
3721
3734
  }
3722
- if (curMeasure.hasNavigation(6 /* Segno */)) {
3735
+ if (curMeasure.hasNavigation("Segno" /* Segno */)) {
3723
3736
  segnoMeasure = curMeasure;
3724
3737
  }
3725
- if (alCoda && curMeasure.hasNavigation(5 /* toCoda */)) {
3726
- while (curMeasure && !curMeasure.hasNavigation(4 /* Coda */)) {
3738
+ if (alCoda && curMeasure.hasNavigation("toCoda" /* toCoda */)) {
3739
+ while (curMeasure && !curMeasure.hasNavigation("Coda" /* Coda */)) {
3727
3740
  curMeasure = curMeasure.getNextMeasure();
3728
3741
  }
3729
- } else if (alFine && curMeasure.hasNavigation(7 /* Fine */)) {
3742
+ } else if (alFine && curMeasure.hasNavigation("Fine" /* Fine */)) {
3730
3743
  curMeasure = void 0;
3731
- } else if (curMeasure.hasNavigation(1 /* DC_al_Coda */)) {
3744
+ } else if (curMeasure.hasNavigation("D.C. al Coda" /* DC_al_Coda */)) {
3732
3745
  alCoda = true;
3733
3746
  curMeasure = this.doc.getFirstMeasure();
3734
- } else if (curMeasure.hasNavigation(0 /* DC_al_Fine */)) {
3747
+ } else if (curMeasure.hasNavigation("D.C. al Fine" /* DC_al_Fine */)) {
3735
3748
  alFine = true;
3736
3749
  curMeasure = this.doc.getFirstMeasure();
3737
- } else if (curMeasure.hasNavigation(3 /* DS_al_Coda */)) {
3750
+ } else if (curMeasure.hasNavigation("D.S. al Coda" /* DS_al_Coda */)) {
3738
3751
  alCoda = true;
3739
3752
  curMeasure = segnoMeasure;
3740
- } else if (curMeasure.hasNavigation(2 /* DS_al_Fine */)) {
3753
+ } else if (curMeasure.hasNavigation("D.S. al Fine" /* DS_al_Fine */)) {
3741
3754
  alFine = true;
3742
3755
  curMeasure = segnoMeasure;
3743
- } else if (curMeasure.hasNavigation(9 /* EndRepeat */)) {
3756
+ } else if (curMeasure.hasNavigation("endRepeat" /* EndRepeat */)) {
3744
3757
  let passage = curMeasure.getPassCount();
3745
3758
  let repeatCount = curMeasure.getEndRepeatPlayCount() - 1;
3746
- let cannotPassThrough = ((_a = curMeasure.getNextMeasure()) == null ? void 0 : _a.hasNavigation(10 /* Ending */)) === true;
3759
+ let cannotPassThrough = ((_a = curMeasure.getNextMeasure()) == null ? void 0 : _a.hasNavigation("ending" /* Ending */)) === true;
3747
3760
  if (passage <= repeatCount || cannotPassThrough) {
3748
3761
  curMeasure = startRepeatMeasure;
3749
3762
  } else {
@@ -3794,14 +3807,15 @@ var Player = class _Player {
3794
3807
  col.getAnchoredLayoutObjects().forEach((layoutObj) => {
3795
3808
  var _a2;
3796
3809
  let text = (_a2 = layoutObj.getTextContent()) != null ? _a2 : "";
3797
- if (text === "a tempo") {
3810
+ let vol;
3811
+ if (text === "a tempo" /* a_tempo */) {
3798
3812
  curSpeed = 1;
3799
- } else if (isDynamicsLevelText(text)) {
3800
- curVolume = getVolume(text);
3813
+ } else if ((vol = getDynamicsVolume(text)) !== void 0) {
3814
+ curVolume = vol;
3801
3815
  } else if (layoutObj.musicObj.getLink() instanceof Extension) {
3802
3816
  let extension = layoutObj.musicObj.getLink();
3803
3817
  let { columnRange, extensionBreakText } = extension.getExtensionRangeInfo();
3804
- let totalTicks = Utils5.Math.sum(columnRange.map((c) => c.getTicksToNextColumn()));
3818
+ let totalTicks = Utils6.Math.sum(columnRange.map((c) => c.getTicksToNextColumn()));
3805
3819
  switch (text) {
3806
3820
  case "accel." /* accel */: {
3807
3821
  let startSpeed = curSpeed;
@@ -3826,8 +3840,8 @@ var Player = class _Player {
3826
3840
  case "cresc." /* cresc */: {
3827
3841
  let startVol = curVolume;
3828
3842
  let endVol = startVol + CrescendoVolumeAdd;
3829
- if (extensionBreakText && isDynamicsLevelText(extensionBreakText) && getVolume(extensionBreakText) > startVol) {
3830
- endVol = getVolume(extensionBreakText);
3843
+ if (extensionBreakText && (vol = getDynamicsVolume(extensionBreakText)) !== void 0 && vol > startVol) {
3844
+ endVol = vol;
3831
3845
  }
3832
3846
  let accuTicks = 0;
3833
3847
  columnRange.forEach((c) => {
@@ -3840,8 +3854,8 @@ var Player = class _Player {
3840
3854
  case "dim." /* dim */: {
3841
3855
  let startVol = curVolume;
3842
3856
  let endVol = startVol - DiminuendoVolumeSub;
3843
- if (extensionBreakText && isDynamicsLevelText(extensionBreakText) && getVolume(extensionBreakText) < startVol) {
3844
- endVol = getVolume(extensionBreakText);
3857
+ if (extensionBreakText && (vol = getDynamicsVolume(extensionBreakText)) !== void 0 && vol < startVol) {
3858
+ endVol = vol;
3845
3859
  }
3846
3860
  let accuTicks = 0;
3847
3861
  columnRange.forEach((c) => {
@@ -3855,11 +3869,11 @@ var Player = class _Player {
3855
3869
  });
3856
3870
  let speedArr = (_a = speedMap.get(col)) != null ? _a : [];
3857
3871
  if (speedArr.length > 0) {
3858
- curSpeed = Utils5.Math.sum(speedArr) / speedArr.length;
3872
+ curSpeed = Utils6.Math.sum(speedArr) / speedArr.length;
3859
3873
  }
3860
3874
  let volumeArr = (_b = volumeMap.get(col)) != null ? _b : [];
3861
3875
  if (volumeArr.length > 0) {
3862
- curVolume = Utils5.Math.sum(volumeArr) / volumeArr.length;
3876
+ curVolume = Utils6.Math.sum(volumeArr) / volumeArr.length;
3863
3877
  }
3864
3878
  col.getPlayerProps().setSpeed(curSpeed);
3865
3879
  col.getPlayerProps().setVolume(curVolume);
@@ -3872,7 +3886,7 @@ var Player = class _Player {
3872
3886
  return m;
3873
3887
  }
3874
3888
  let next = m == null ? void 0 : m.getNextMeasure();
3875
- if (!m || m.hasEndSong() || m.hasEndSection() || !next || next.hasNavigation(8 /* StartRepeat */)) {
3889
+ if (!m || m.hasEndSong() || m.hasEndSection() || !next || next.hasNavigation("startRepeat" /* StartRepeat */)) {
3876
3890
  return void 0;
3877
3891
  }
3878
3892
  }
@@ -3897,11 +3911,11 @@ var Player = class _Player {
3897
3911
  } else {
3898
3912
  let playerNotes = col.getPlayerNotes();
3899
3913
  playerNotes.forEach((note, i) => {
3900
- let arpeggioDelayTicks = col.hasArpeggio() ? NoteLength5.ThirtySecond * i : 0;
3914
+ let arpeggioDelayTicks = col.hasArpeggio() ? RhythmProps3.get(NoteLength5.ThirtySecond).ticks * i : 0;
3901
3915
  let noteSeconds = getDuration(note.ticks + fermataHoldTicks - arpeggioDelayTicks, tempo);
3902
3916
  if (noteSeconds > 0) {
3903
3917
  if (note.staccato) {
3904
- noteSeconds = Math.min(getDuration(NoteLength5.Eighth, tempo) / 2, noteSeconds / 2);
3918
+ noteSeconds = Math.min(getDuration(RhythmProps3.get(NoteLength5.Eighth).ticks, tempo) / 2, noteSeconds / 2);
3905
3919
  }
3906
3920
  let volume = adjustVolume(col.getPlayerProps().getVolume());
3907
3921
  if (note.slur === "slurred") {
@@ -4139,8 +4153,8 @@ var ObjBarLineLeft = class extends ObjBarLine {
4139
4153
  solveBarLineType() {
4140
4154
  let m = this.measure;
4141
4155
  let prev = m.getPrevMeasure();
4142
- if (m.hasNavigation(8 /* StartRepeat */)) {
4143
- if (prev && prev.row === m.row && prev.hasNavigation(9 /* EndRepeat */)) {
4156
+ if (m.hasNavigation("startRepeat" /* StartRepeat */)) {
4157
+ if (prev && prev.row === m.row && prev.hasNavigation("endRepeat" /* EndRepeat */)) {
4144
4158
  return 0 /* None */;
4145
4159
  } else {
4146
4160
  return 4 /* StartRepeat */;
@@ -4167,8 +4181,8 @@ var ObjBarLineRight = class extends ObjBarLine {
4167
4181
  solveBarLineType() {
4168
4182
  let m = this.measure;
4169
4183
  let next = m.getNextMeasure();
4170
- if (m.hasNavigation(9 /* EndRepeat */)) {
4171
- if (next && next.row === m.row && next.hasNavigation(8 /* StartRepeat */)) {
4184
+ if (m.hasNavigation("endRepeat" /* EndRepeat */)) {
4185
+ if (next && next.row === m.row && next.hasNavigation("startRepeat" /* StartRepeat */)) {
4172
4186
  return 6 /* EndStartRepeat */;
4173
4187
  } else {
4174
4188
  return 5 /* EndRepeat */;
@@ -4178,10 +4192,10 @@ var ObjBarLineRight = class extends ObjBarLine {
4178
4192
  } else if (m.hasEndSection()) {
4179
4193
  return 2 /* Double */;
4180
4194
  }
4181
- if (m === m.row.getLastMeasure() && next && next.row === m.row.getNextRow() && next.hasNavigation(8 /* StartRepeat */)) {
4195
+ if (m === m.row.getLastMeasure() && next && next.row === m.row.getNextRow() && next.hasNavigation("startRepeat" /* StartRepeat */)) {
4182
4196
  return 2 /* Double */;
4183
4197
  }
4184
- if (next && next.hasNavigation(8 /* StartRepeat */)) {
4198
+ if (next && next.hasNavigation("startRepeat" /* StartRepeat */)) {
4185
4199
  return 0 /* None */;
4186
4200
  }
4187
4201
  return 1 /* Single */;
@@ -4189,7 +4203,7 @@ var ObjBarLineRight = class extends ObjBarLine {
4189
4203
  };
4190
4204
 
4191
4205
  // src/score/engine/obj-ending.ts
4192
- import { Utils as Utils6 } from "@tspro/ts-utils-lib";
4206
+ import { Utils as Utils7 } from "@tspro/ts-utils-lib";
4193
4207
  import { MusicError as MusicError10, MusicErrorType as MusicErrorType10 } from "@tspro/web-music-score/core";
4194
4208
  var ObjEnding = class extends MusicObject {
4195
4209
  constructor(measure, passages) {
@@ -4200,9 +4214,9 @@ var ObjEnding = class extends MusicObject {
4200
4214
  __publicField(this, "shapeRects", []);
4201
4215
  __publicField(this, "mi");
4202
4216
  this.mi = new MEnding(this);
4203
- if (!Utils6.Is.isIntegerGte(passages.length, 1)) {
4217
+ if (!Utils7.Is.isIntegerGte(passages.length, 1)) {
4204
4218
  throw new MusicError10(MusicErrorType10.Score, "Passages is empty.");
4205
- } else if (!this.passages.every((p) => Utils6.Is.isIntegerGte(p, 1))) {
4219
+ } else if (!this.passages.every((p) => Utils7.Is.isIntegerGte(p, 1))) {
4206
4220
  throw new MusicError10(MusicErrorType10.Score, "Invalid passages: " + this.passages);
4207
4221
  }
4208
4222
  this.passages.sort((a, b) => a - b);
@@ -4218,7 +4232,7 @@ var ObjEnding = class extends MusicObject {
4218
4232
  isSingleMeasureEnding() {
4219
4233
  let { measure } = this;
4220
4234
  let next = measure.getNextMeasure();
4221
- return (next == null ? void 0 : next.hasNavigation(10 /* Ending */)) === true || measure.hasNavigation(9 /* EndRepeat */) || measure.isLastMeasure();
4235
+ return (next == null ? void 0 : next.hasNavigation("ending" /* Ending */)) === true || measure.hasNavigation("endRepeat" /* EndRepeat */) || measure.isLastMeasure();
4222
4236
  }
4223
4237
  hasPassage(pass) {
4224
4238
  return this.passages.some((p) => p === pass);
@@ -4417,7 +4431,7 @@ import { MusicError as MusicError13, MusicErrorType as MusicErrorType13 } from "
4417
4431
  import { Note as Note6 } from "@tspro/web-music-score/theory";
4418
4432
 
4419
4433
  // src/score/engine/obj-connective.ts
4420
- import { Utils as Utils7 } from "@tspro/ts-utils-lib";
4434
+ import { Utils as Utils8 } from "@tspro/ts-utils-lib";
4421
4435
  import { MusicError as MusicError11, MusicErrorType as MusicErrorType11 } from "@tspro/web-music-score/core";
4422
4436
  var ObjConnective = class extends MusicObject {
4423
4437
  constructor(connectiveProps, line, measure, leftNoteGroup, leftNoteId, ...args) {
@@ -4446,7 +4460,7 @@ var ObjConnective = class extends MusicObject {
4446
4460
  this.rightNoteGroup = args[0];
4447
4461
  this.rightNoteId = args[1];
4448
4462
  this.tieType = void 0;
4449
- } else if (Utils7.Is.isEnumValue(args[0], TieType)) {
4463
+ } else if (Utils8.Is.isEnumValue(args[0], TieType)) {
4450
4464
  this.rightNoteGroup = void 0;
4451
4465
  this.rightNoteId = void 0;
4452
4466
  this.tieType = args[0];
@@ -4477,7 +4491,7 @@ var ObjConnective = class extends MusicObject {
4477
4491
  if (rightNoteGroup !== void 0 && rightNoteId !== void 0) {
4478
4492
  rightPos = rightNoteGroup.getConnectiveAnchorPoint(connectiveProps, line, rightNoteId, noteAnchor, "right");
4479
4493
  } else {
4480
- rightPos = this.tieType === -2 /* ToMeasureEnd */ ? { x: measure.getColumnsContentRect().right, y: leftPos.y } : { x: leftPos.x + unitSize * DocumentSettings.StubTieLength, y: leftPos.y };
4494
+ rightPos = this.tieType === "toMeasureEnd" /* ToMeasureEnd */ ? { x: measure.getColumnsContentRect().right, y: leftPos.y } : { x: leftPos.x + unitSize * DocumentSettings.StubTieLength, y: leftPos.y };
4481
4495
  }
4482
4496
  let lx, ly, rx, ry;
4483
4497
  if (rightNoteGroup === void 0) {
@@ -4515,8 +4529,8 @@ var ObjConnective = class extends MusicObject {
4515
4529
  this.ly = ly;
4516
4530
  this.rx = rx;
4517
4531
  this.ry = ry;
4518
- this.arcHeight = this.connectiveProps.connective === 2 /* Slide */ ? 0 : arcHeight;
4519
- let { nx, ny } = Utils7.Math.calcNormal(lx, ly, rx, ry);
4532
+ this.arcHeight = this.connectiveProps.connective === "slide" /* Slide */ ? 0 : arcHeight;
4533
+ let { nx, ny } = Utils8.Math.calcNormal(lx, ly, rx, ry);
4520
4534
  this.cp1x = lx * 0.7 + rx * 0.3 + nx * this.arcHeight;
4521
4535
  this.cp1y = ly * 0.7 + ry * 0.3 + ny * this.arcHeight;
4522
4536
  this.cp2x = lx * 0.3 + rx * 0.7 + nx * this.arcHeight;
@@ -4577,6 +4591,7 @@ var ObjConnective = class extends MusicObject {
4577
4591
 
4578
4592
  // src/score/engine/connective-props.ts
4579
4593
  import { MusicError as MusicError12, MusicErrorType as MusicErrorType12 } from "@tspro/web-music-score/core";
4594
+ import { Utils as Utils9 } from "@tspro/ts-utils-lib";
4580
4595
  var ConnectiveProps = class {
4581
4596
  constructor(connective, span, noteAnchor, startNoteGroup) {
4582
4597
  this.connective = connective;
@@ -4598,7 +4613,7 @@ var ConnectiveProps = class {
4598
4613
  * @returns true if noteGroup was added, false if not.
4599
4614
  */
4600
4615
  addNoteGroup(noteGroup) {
4601
- if (this.span === -1 /* Stub */ || this.span === -2 /* ToMeasureEnd */) {
4616
+ if (this.span === "stub" /* Stub */ || this.span === "toMeasureEnd" /* ToMeasureEnd */) {
4602
4617
  return false;
4603
4618
  } else if (this.span > this.noteGroups.length) {
4604
4619
  this.noteGroups.push(noteGroup);
@@ -4608,29 +4623,29 @@ var ConnectiveProps = class {
4608
4623
  }
4609
4624
  }
4610
4625
  computeParams() {
4611
- let stemDir = this.noteGroups[0].stemDir;
4612
- let hasStem = this.noteGroups[0].rhythmProps.hasStem;
4613
- if (this.noteAnchor === 4 /* StemTip */) {
4614
- this.arcDir = stemDir === 1 /* Up */ ? "up" : "down";
4615
- } else if (this.noteAnchor === 0 /* Auto */) {
4616
- this.arcDir = stemDir === 1 /* Up */ || !hasStem ? "down" : "up";
4626
+ let { stemDir } = this.noteGroups[0];
4627
+ let { hasStem } = this.noteGroups[0].rhythmProps;
4628
+ if (this.noteAnchor === "stemTip" /* StemTip */) {
4629
+ this.arcDir = stemDir === "up" /* Up */ ? "up" : "down";
4630
+ } else if (this.noteAnchor === "auto" /* Auto */) {
4631
+ this.arcDir = stemDir === "up" /* Up */ || !hasStem ? "down" : "up";
4617
4632
  if (this.noteGroups[0].notes.length > 1) {
4618
- this.noteAnchor = 2 /* Center */;
4619
- } else if (this.connective === 2 /* Slide */) {
4620
- this.noteAnchor = 2 /* Center */;
4633
+ this.noteAnchor = "center" /* Center */;
4634
+ } else if (this.connective === "slide" /* Slide */) {
4635
+ this.noteAnchor = "center" /* Center */;
4621
4636
  } else if (this.arcDir === "up") {
4622
- this.noteAnchor = 1 /* Above */;
4637
+ this.noteAnchor = "above" /* Above */;
4623
4638
  } else {
4624
- this.noteAnchor = 3 /* Below */;
4639
+ this.noteAnchor = "below" /* Below */;
4625
4640
  }
4626
- } else if (this.noteAnchor === 2 /* Center */) {
4641
+ } else if (this.noteAnchor === "center" /* Center */) {
4627
4642
  let { row } = this.noteGroups[0].measure;
4628
4643
  let diatonicId = this.noteGroups[0].ownDiatonicId;
4629
4644
  let staff = row.getStaff(diatonicId);
4630
4645
  this.arcDir = !staff || diatonicId < staff.middleLineDiatonicId ? "down" : "up";
4631
- } else if (this.noteAnchor === 1 /* Above */) {
4646
+ } else if (this.noteAnchor === "above" /* Above */) {
4632
4647
  this.arcDir = "up";
4633
- } else if (this.noteAnchor === 3 /* Below */) {
4648
+ } else if (this.noteAnchor === "below" /* Below */) {
4634
4649
  this.arcDir = "down";
4635
4650
  }
4636
4651
  }
@@ -4645,8 +4660,8 @@ var ConnectiveProps = class {
4645
4660
  this.getStartNoteGroup().collectConnectiveProps();
4646
4661
  this.computeParams();
4647
4662
  let { connective, span } = this;
4648
- if (connective === 0 /* Tie */) {
4649
- if (span === -1 /* Stub */ || span === -2 /* ToMeasureEnd */) {
4663
+ if (connective === "tie" /* Tie */) {
4664
+ if (Utils9.Is.isEnumValue(span, TieType)) {
4650
4665
  let leftNoteGroup = this.noteGroups[0];
4651
4666
  for (let noteId = 0; noteId < leftNoteGroup.notes.length; noteId++) {
4652
4667
  this.createObjConnectiveWithTieType(leftNoteGroup, noteId, span);
@@ -4663,13 +4678,13 @@ var ConnectiveProps = class {
4663
4678
  });
4664
4679
  }
4665
4680
  }
4666
- } else if (connective === 1 /* Slur */) {
4681
+ } else if (connective === "slur" /* Slur */) {
4667
4682
  if (typeof span === "number" && span >= 2 && this.noteGroups.length === span) {
4668
4683
  let leftNoteGroup = this.noteGroups[0];
4669
4684
  let rightNoteGroup = this.noteGroups[this.noteGroups.length - 1];
4670
4685
  this.createObjConnective(leftNoteGroup, 0, rightNoteGroup, 0);
4671
4686
  }
4672
- } else if (connective === 2 /* Slide */) {
4687
+ } else if (connective === "slide" /* Slide */) {
4673
4688
  if (this.noteGroups.length >= 2) {
4674
4689
  for (let i = 0; i < this.noteGroups.length - 1; i++) {
4675
4690
  let leftNoteGroup = this.noteGroups[i];
@@ -4699,7 +4714,7 @@ var ConnectiveProps = class {
4699
4714
  } else {
4700
4715
  let leftString = leftNoteGroup2.getFretNumberString(leftNoteId2);
4701
4716
  let rightString = rightNoteGroup2.getFretNumberString(rightNoteId2);
4702
- if (leftString !== void 0 && rightString !== void 0 && (leftString === rightString || this.connective === 1 /* Slur */)) {
4717
+ if (leftString !== void 0 && rightString !== void 0 && (leftString === rightString || this.connective === "slur" /* Slur */)) {
4703
4718
  new ObjConnective(this, line, measure, leftNoteGroup2, leftNoteId2, rightNoteGroup2, rightNoteId2);
4704
4719
  }
4705
4720
  }
@@ -4724,6 +4739,32 @@ function validateVoiceId(voiceId) {
4724
4739
  return voiceId;
4725
4740
  }
4726
4741
  }
4742
+ function getExtensionTicks(extensionLength) {
4743
+ if (typeof extensionLength === "string") {
4744
+ extensionLength = [extensionLength];
4745
+ }
4746
+ if (Utils10.Is.isArray(extensionLength)) {
4747
+ let totalTicks = 0;
4748
+ for (let i = 0; i < extensionLength.length; ) {
4749
+ let str = extensionLength[i];
4750
+ let num = extensionLength[i + 1];
4751
+ if (typeof str === "string") {
4752
+ i++;
4753
+ let ticks = RhythmProps4.get(str).ticks;
4754
+ if (typeof num === "number") {
4755
+ i++;
4756
+ ticks *= num;
4757
+ }
4758
+ totalTicks += ticks;
4759
+ } else {
4760
+ i++;
4761
+ }
4762
+ }
4763
+ return totalTicks;
4764
+ } else {
4765
+ return extensionLength;
4766
+ }
4767
+ }
4727
4768
  var _ObjMeasure = class _ObjMeasure extends MusicObject {
4728
4769
  constructor(row) {
4729
4770
  super(row);
@@ -4827,15 +4868,15 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
4827
4868
  if (setStemDir !== void 0) {
4828
4869
  this.useStemDir[voiceId] = setStemDir;
4829
4870
  } else if (this.useStemDir[voiceId] === void 0) {
4830
- this.useStemDir[voiceId] = (_b = (_a = this.getPrevMeasure()) == null ? void 0 : _a.useStemDir[voiceId]) != null ? _b : 0 /* Auto */;
4871
+ this.useStemDir[voiceId] = (_b = (_a = this.getPrevMeasure()) == null ? void 0 : _a.useStemDir[voiceId]) != null ? _b : "auto" /* Auto */;
4831
4872
  }
4832
4873
  let stemDir = this.useStemDir[voiceId];
4833
- if (stemDir === 0 /* Auto */ || stemDir === void 0) {
4874
+ if (stemDir === "auto" /* Auto */ || stemDir === void 0) {
4834
4875
  let staff = this.row.getStaff(symbol.ownDiatonicId);
4835
4876
  if (staff) {
4836
- return symbol.ownDiatonicId > staff.middleLineDiatonicId ? 2 /* Down */ : 1 /* Up */;
4877
+ return symbol.ownDiatonicId > staff.middleLineDiatonicId ? "down" /* Down */ : "up" /* Up */;
4837
4878
  } else {
4838
- return 1 /* Up */;
4879
+ return "up" /* Up */;
4839
4880
  }
4840
4881
  } else {
4841
4882
  return stemDir;
@@ -4942,6 +4983,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
4942
4983
  // See MMeasure interface
4943
4984
  //setKeySignature(tonic: string, scaleType: ScaleType): void;
4944
4985
  //setKeySignature(keySignature: KeySignature): void;
4986
+ //setKeySignature(keySignature: string): void;
4945
4987
  //setKeySignature(scale: Scale): void;
4946
4988
  setKeySignature(...args) {
4947
4989
  var _a;
@@ -4950,13 +4992,17 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
4950
4992
  this.alterKeySignature = args[0];
4951
4993
  } else if (args[0] instanceof Scale) {
4952
4994
  this.alterKeySignature = args[0];
4953
- } else {
4954
- try {
4955
- let tonic = "" + args[0];
4956
- let scaleType = validateScaleType("" + args[1]);
4957
- this.alterKeySignature = getScale(tonic, scaleType);
4958
- } catch (e) {
4959
- throw new MusicError13(MusicErrorType13.Score, "Cannot set key signature because invalid args: " + args);
4995
+ } else if (Utils10.Is.isNonEmptyString(args[0])) {
4996
+ if (args.length === 1) {
4997
+ this.alterKeySignature = getScale(args[0]);
4998
+ } else if (args.length === 2) {
4999
+ try {
5000
+ let tonic = "" + args[0];
5001
+ let scaleType = validateScaleType("" + args[1]);
5002
+ this.alterKeySignature = getScale(tonic, scaleType);
5003
+ } catch (e) {
5004
+ throw new MusicError13(MusicErrorType13.Score, "Cannot set key signature because invalid args: " + args);
5005
+ }
4960
5006
  }
4961
5007
  }
4962
5008
  this.updateKeySignature();
@@ -4996,8 +5042,16 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
4996
5042
  setTempo(beatsPerMinute, beatLength, dotted) {
4997
5043
  var _a;
4998
5044
  (_a = this.getPrevMeasure()) == null ? void 0 : _a.endSection();
4999
- let options = beatLength !== void 0 ? { beatLength, dotted } : void 0;
5000
- this.alterTempo = { beatsPerMinute, options };
5045
+ if (beatLength === void 0) {
5046
+ this.alterTempo = { beatsPerMinute };
5047
+ } else {
5048
+ let dotCount = typeof dotted === "number" && dotted > 0 ? dotted : dotted === true ? 1 : NoteLengthProps4.get(beatLength).dotCount;
5049
+ let options = {
5050
+ beatLength: validateNoteLength(beatLength),
5051
+ dotCount: dotCount > 0 ? dotCount : void 0
5052
+ };
5053
+ this.alterTempo = { beatsPerMinute, options };
5054
+ }
5001
5055
  this.updateTempo();
5002
5056
  }
5003
5057
  updateTempo() {
@@ -5006,18 +5060,18 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5006
5060
  if (this.alterTempo) {
5007
5061
  let beatsPerMinute = this.alterTempo.beatsPerMinute;
5008
5062
  let beatLength;
5009
- let dotted;
5063
+ let dotCount;
5010
5064
  if (this.alterTempo.options) {
5011
5065
  beatLength = this.alterTempo.options.beatLength;
5012
- dotted = (_a = this.alterTempo.options.dotted) != null ? _a : false;
5066
+ dotCount = (_a = this.alterTempo.options.dotCount) != null ? _a : 0;
5013
5067
  } else if (this.alterTimeSignature) {
5014
5068
  beatLength = this.alterTimeSignature.beatLength;
5015
- dotted = false;
5069
+ dotCount = 0;
5016
5070
  } else {
5017
5071
  beatLength = this.tempo.options.beatLength;
5018
- dotted = this.tempo.options.dotted;
5072
+ dotCount = this.tempo.options.dotCount;
5019
5073
  }
5020
- this.tempo = { beatsPerMinute, options: { beatLength, dotted } };
5074
+ this.tempo = { beatsPerMinute, options: { beatLength, dotCount } };
5021
5075
  }
5022
5076
  if (this.nextMeasure) {
5023
5077
  this.nextMeasure.updateTempo();
@@ -5049,19 +5103,19 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5049
5103
  let grp = this.doc.getStaffGroup(staffTabOrGroup);
5050
5104
  if (grp && !prevGroups.includes(staffTabOrGroup)) {
5051
5105
  let curGroups = [...prevGroups, staffTabOrGroup];
5052
- (Utils8.Is.isArray(grp.staffsTabsAndGroups) ? grp.staffsTabsAndGroups : [grp.staffsTabsAndGroups]).forEach((staffTabOrGroup2) => {
5106
+ (Utils10.Is.isArray(grp.staffsTabsAndGroups) ? grp.staffsTabsAndGroups : [grp.staffsTabsAndGroups]).forEach((staffTabOrGroup2) => {
5053
5107
  switch (grp.verticalPosition) {
5054
- case 0 /* Above */:
5108
+ case "above" /* Above */:
5055
5109
  addToStaffTabOrGroup(staffTabOrGroup2, 0 /* Above */, curGroups);
5056
5110
  break;
5057
- case 1 /* Below */:
5111
+ case "below" /* Below */:
5058
5112
  addToStaffTabOrGroup(staffTabOrGroup2, 1 /* Below */, curGroups);
5059
5113
  break;
5060
- case 2 /* Both */:
5114
+ case "both" /* Both */:
5061
5115
  addToStaffTabOrGroup(staffTabOrGroup2, 0 /* Above */, curGroups);
5062
5116
  addToStaffTabOrGroup(staffTabOrGroup2, 1 /* Below */, curGroups);
5063
5117
  break;
5064
- case 3 /* Auto */:
5118
+ case "auto" /* Auto */:
5065
5119
  addToStaffTabOrGroup(staffTabOrGroup2, defaultVerticalPos, curGroups);
5066
5120
  break;
5067
5121
  }
@@ -5076,14 +5130,14 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5076
5130
  } else {
5077
5131
  addToStaffTabOrGroup(0, defaultVerticalPos);
5078
5132
  }
5079
- } else if (Utils8.Is.isArray(staffTabOrGroups)) {
5133
+ } else if (Utils10.Is.isArray(staffTabOrGroups)) {
5080
5134
  staffTabOrGroups.forEach((staffTabOrGroup) => addToStaffTabOrGroup(staffTabOrGroup, defaultVerticalPos));
5081
5135
  } else {
5082
5136
  addToStaffTabOrGroup(staffTabOrGroups, defaultVerticalPos);
5083
5137
  }
5084
5138
  }
5085
5139
  addFermata(staffTabOrGroups, fermata) {
5086
- let anchor = fermata === 1 /* AtMeasureEnd */ ? this.barLineRight : this.lastAddedRhythmColumn;
5140
+ let anchor = fermata === "atMeasureEnd" /* AtMeasureEnd */ ? this.barLineRight : this.lastAddedRhythmColumn;
5087
5141
  if (!anchor) {
5088
5142
  throw new MusicError13(MusicErrorType13.Score, "Cannot add Fermata because anchor is undefined.");
5089
5143
  }
@@ -5099,7 +5153,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5099
5153
  addNavigation(staffTabOrGroups, navigation, ...args) {
5100
5154
  let addLayoutObjectProps = void 0;
5101
5155
  switch (navigation) {
5102
- case 10 /* Ending */:
5156
+ case "ending" /* Ending */:
5103
5157
  if (this.navigationSet.has(navigation)) {
5104
5158
  throw new MusicError13(MusicErrorType13.Score, "Cannot add ending beasure measure already has one.");
5105
5159
  }
@@ -5111,10 +5165,10 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5111
5165
  defaultVerticalPos: 0 /* Above */
5112
5166
  };
5113
5167
  break;
5114
- case 1 /* DC_al_Coda */:
5115
- case 0 /* DC_al_Fine */:
5116
- case 3 /* DS_al_Coda */:
5117
- case 2 /* DS_al_Fine */: {
5168
+ case "D.C. al Coda" /* DC_al_Coda */:
5169
+ case "D.C. al Fine" /* DC_al_Fine */:
5170
+ case "D.S. al Coda" /* DS_al_Coda */:
5171
+ case "D.S. al Fine" /* DS_al_Fine */: {
5118
5172
  let anchor2 = this.barLineRight;
5119
5173
  let text = getNavigationString(navigation);
5120
5174
  addLayoutObjectProps = {
@@ -5122,11 +5176,11 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5122
5176
  layoutGroupId: 2 /* Navigation */,
5123
5177
  defaultVerticalPos: 0 /* Above */
5124
5178
  };
5125
- this.addNavigation(staffTabOrGroups, 9 /* EndRepeat */);
5179
+ this.addNavigation(staffTabOrGroups, "endRepeat" /* EndRepeat */);
5126
5180
  this.endSong();
5127
5181
  break;
5128
5182
  }
5129
- case 7 /* Fine */: {
5183
+ case "Fine" /* Fine */: {
5130
5184
  let anchor2 = this.barLineRight;
5131
5185
  let text = getNavigationString(navigation);
5132
5186
  addLayoutObjectProps = {
@@ -5136,8 +5190,8 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5136
5190
  };
5137
5191
  break;
5138
5192
  }
5139
- case 6 /* Segno */:
5140
- case 4 /* Coda */: {
5193
+ case "Segno" /* Segno */:
5194
+ case "Coda" /* Coda */: {
5141
5195
  let anchor2 = this.barLineLeft;
5142
5196
  let text = getNavigationString(navigation);
5143
5197
  addLayoutObjectProps = {
@@ -5147,7 +5201,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5147
5201
  };
5148
5202
  break;
5149
5203
  }
5150
- case 5 /* toCoda */: {
5204
+ case "toCoda" /* toCoda */: {
5151
5205
  let anchor2 = this.barLineRight;
5152
5206
  let text = getNavigationString(navigation);
5153
5207
  addLayoutObjectProps = {
@@ -5157,10 +5211,10 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5157
5211
  };
5158
5212
  break;
5159
5213
  }
5160
- case 9 /* EndRepeat */:
5214
+ case "endRepeat" /* EndRepeat */:
5161
5215
  if (args.length === 0) {
5162
5216
  this.endRepeatPlayCount = 2;
5163
- } else if (Utils8.Is.isIntegerGte(args[0], 2)) {
5217
+ } else if (Utils10.Is.isIntegerGte(args[0], 2)) {
5164
5218
  this.endRepeatPlayCount = args[0];
5165
5219
  } else {
5166
5220
  throw new MusicError13(MusicErrorType13.Score, "Invalid end repeat play count (should be 2 or greater integer): " + args[0]);
@@ -5196,17 +5250,18 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5196
5250
  let layoutGroupId;
5197
5251
  let defaultVerticalPos;
5198
5252
  switch (annotation) {
5199
- case 0 /* Dynamics */:
5253
+ case "dynamics" /* Dynamics */:
5200
5254
  layoutGroupId = 5 /* DynamicsAnnotation */;
5201
5255
  defaultVerticalPos = 0 /* Above */;
5202
5256
  textProps.italic = true;
5203
5257
  break;
5204
- case 1 /* Tempo */:
5258
+ case "tempo" /* Tempo */:
5205
5259
  layoutGroupId = 4 /* TempoAnnotation */;
5206
5260
  defaultVerticalPos = 0 /* Above */;
5207
5261
  textProps.italic = true;
5208
5262
  break;
5209
5263
  }
5264
+ this.disableExtension();
5210
5265
  this.forEachStaffGroup(staffTabOrGroups, defaultVerticalPos, (line, vpos) => {
5211
5266
  let textObj = new ObjText(anchor, textProps, 0.5, 1);
5212
5267
  this.addLayoutObject(textObj, line, layoutGroupId, vpos);
@@ -5224,15 +5279,16 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5224
5279
  let layoutGroupId;
5225
5280
  let defaultVerticalPos;
5226
5281
  switch (label) {
5227
- case 0 /* Note */:
5282
+ case "note" /* Note */:
5228
5283
  layoutGroupId = 1 /* NoteLabel */;
5229
5284
  defaultVerticalPos = 1 /* Below */;
5230
5285
  break;
5231
- case 1 /* Chord */:
5286
+ case "chord" /* Chord */:
5232
5287
  layoutGroupId = 6 /* ChordLabel */;
5233
5288
  defaultVerticalPos = 0 /* Above */;
5234
5289
  break;
5235
5290
  }
5291
+ this.disableExtension();
5236
5292
  this.forEachStaffGroup(staffTabOrGroups, defaultVerticalPos, (line, vpos) => {
5237
5293
  let textObj = new ObjText(anchor, textProps, 0.5, 1);
5238
5294
  this.addLayoutObject(textObj, line, layoutGroupId, vpos);
@@ -5244,17 +5300,17 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5244
5300
  if (!(anchor instanceof ObjNoteGroup)) {
5245
5301
  throw new MusicError13(MusicErrorType13.Score, "Connective can be added to note group only.");
5246
5302
  }
5247
- if (connective === 0 /* Tie */) {
5248
- let tieSpan = Utils8.Is.isInteger(args[0]) || Utils8.Is.isEnumValue(args[0], TieType) ? args[0] : 2;
5249
- let noteAnchor = Utils8.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : 0 /* Auto */;
5250
- anchor.startConnective(new ConnectiveProps(0 /* Tie */, tieSpan, noteAnchor, anchor));
5251
- } else if (connective === 1 /* Slur */) {
5252
- let slurSpan = Utils8.Is.isInteger(args[0]) ? args[0] : 2;
5253
- let noteAnchor = Utils8.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : 0 /* Auto */;
5254
- anchor.startConnective(new ConnectiveProps(1 /* Slur */, slurSpan, noteAnchor, anchor));
5255
- } else if (connective === 2 /* Slide */) {
5256
- let noteAnchor = Utils8.Is.isEnumValue(args[0], NoteAnchor) ? args[0] : 0 /* Auto */;
5257
- anchor.startConnective(new ConnectiveProps(2 /* Slide */, 2, noteAnchor, anchor));
5303
+ if (connective === "tie" /* Tie */) {
5304
+ let tieSpan = Utils10.Is.isInteger(args[0]) || Utils10.Is.isEnumValue(args[0], TieType) ? args[0] : 2;
5305
+ let noteAnchor = Utils10.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : "auto" /* Auto */;
5306
+ anchor.startConnective(new ConnectiveProps("tie" /* Tie */, tieSpan, noteAnchor, anchor));
5307
+ } else if (connective === "slur" /* Slur */) {
5308
+ let slurSpan = Utils10.Is.isInteger(args[0]) ? args[0] : 2;
5309
+ let noteAnchor = Utils10.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : "auto" /* Auto */;
5310
+ anchor.startConnective(new ConnectiveProps("slur" /* Slur */, slurSpan, noteAnchor, anchor));
5311
+ } else if (connective === "slide" /* Slide */) {
5312
+ let noteAnchor = Utils10.Is.isEnumValue(args[0], NoteAnchor) ? args[0] : "auto" /* Auto */;
5313
+ anchor.startConnective(new ConnectiveProps("slide" /* Slide */, 2, noteAnchor, anchor));
5258
5314
  }
5259
5315
  }
5260
5316
  addExtension(extensionLength, extensionVisible) {
@@ -5263,7 +5319,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5263
5319
  if (musicObj instanceof ObjText && anchor instanceof ObjRhythmColumn) {
5264
5320
  let lineStyle = "dashed";
5265
5321
  let linePos = "bottom";
5266
- let extension = new Extension(musicObj, anchor, extensionLength, extensionVisible, lineStyle, linePos);
5322
+ let extension = new Extension(musicObj, anchor, getExtensionTicks(extensionLength), extensionVisible, lineStyle, linePos);
5267
5323
  musicObj.setLink(extension);
5268
5324
  } else {
5269
5325
  throw new MusicError13(MusicErrorType13.Score, "Cannot add extension becaue no compatible music object to attach it to.");
@@ -5312,21 +5368,25 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5312
5368
  col.setVoiceSymbol(voiceId, symbol);
5313
5369
  this.getVoiceSymbols(voiceId);
5314
5370
  this.voiceSymbols[voiceId].push(symbol);
5315
- if (symbol.triplet) {
5371
+ if (symbol.oldStyleTriplet) {
5316
5372
  this.createOldStyleTriplets(voiceId);
5317
5373
  }
5318
5374
  this.requestBeamsUpdate();
5319
5375
  this.lastAddedRhythmColumn = col;
5320
5376
  this.lastAddedRhythmSymbol = symbol;
5321
5377
  }
5322
- addNoteGroup(voiceId, notes, noteLength, options) {
5323
- let notes2 = notes.map((note) => typeof note === "string" ? Note7.getNote(note) : note);
5378
+ addNoteGroup(voiceId, notes, noteLength, options, tupletRatio) {
5379
+ let realNotes = notes.map((note) => typeof note === "string" ? Note7.getNote(note) : note);
5324
5380
  let col = this.getRhythmColumn(voiceId);
5325
- this.addRhythmSymbol(voiceId, new ObjNoteGroup(col, voiceId, notes2, noteLength, options));
5381
+ let noteGroup = new ObjNoteGroup(col, voiceId, realNotes, noteLength, options, tupletRatio);
5382
+ this.addRhythmSymbol(voiceId, noteGroup);
5383
+ return noteGroup;
5326
5384
  }
5327
- addRest(voiceId, restLength, options) {
5385
+ addRest(voiceId, restLength, options, tupletRatio) {
5328
5386
  let col = this.getRhythmColumn(voiceId);
5329
- this.addRhythmSymbol(voiceId, new ObjRest(col, voiceId, restLength, options));
5387
+ let rest = new ObjRest(col, voiceId, restLength, options, tupletRatio);
5388
+ this.addRhythmSymbol(voiceId, rest);
5389
+ return rest;
5330
5390
  }
5331
5391
  /**
5332
5392
  *
@@ -5468,18 +5528,13 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5468
5528
  requestBeamsUpdate() {
5469
5529
  this.needBeamsUpdate = true;
5470
5530
  }
5531
+ // Create triplets by triplet property of NoteOptions/RestOptions.
5471
5532
  createOldStyleTriplets(voiceId) {
5472
5533
  let symbols = this.getVoiceSymbols(voiceId);
5473
- if (symbols.length <= 2) {
5474
- return;
5475
- }
5476
5534
  for (let i = 0; i < symbols.length; ) {
5477
- let s2 = symbols.slice(i, i + 2);
5478
- let s3 = symbols.slice(i, i + 3);
5479
- if (s2.length === 2 && s2.every((s) => s.triplet) && s2.every((s) => s.getBeamGroup() === void 0) && ObjBeamGroup.createTriplet(s2)) {
5480
- i += 2;
5481
- } else if (s3.length === 3 && s3.every((s) => s.triplet) && s3.every((s) => s.getBeamGroup() === void 0) && ObjBeamGroup.createTriplet(s3)) {
5482
- i += 3;
5535
+ if (symbols[i].oldStyleTriplet) {
5536
+ let n = ObjBeamGroup.createOldStyleTriplet(symbols.slice(i, i + 3));
5537
+ i += n === 0 ? 1 : n;
5483
5538
  } else {
5484
5539
  i++;
5485
5540
  }
@@ -5491,11 +5546,11 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5491
5546
  return;
5492
5547
  }
5493
5548
  this.beamGroups = this.beamGroups.filter((beamGroup) => {
5494
- if (beamGroup.getType() === 0 /* RegularBeam */) {
5549
+ if (beamGroup.isTuplet()) {
5550
+ return true;
5551
+ } else {
5495
5552
  beamGroup.detach();
5496
5553
  return false;
5497
- } else {
5498
- return true;
5499
5554
  }
5500
5555
  });
5501
5556
  getVoiceIds().forEach((voiceId) => {
@@ -5531,7 +5586,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5531
5586
  static setupBeamGroup(groupSymbols) {
5532
5587
  let groupNotes = groupSymbols.map((s) => {
5533
5588
  var _a;
5534
- return s instanceof ObjNoteGroup && ((_a = s.getBeamGroup()) == null ? void 0 : _a.isTriplet()) !== true ? s : void 0;
5589
+ return s instanceof ObjNoteGroup && ((_a = s.getBeamGroup()) == null ? void 0 : _a.isTuplet()) !== true ? s : void 0;
5535
5590
  });
5536
5591
  ObjNoteGroup.setBeamCounts(groupNotes);
5537
5592
  let beamNotes = [];
@@ -5563,36 +5618,32 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5563
5618
  if (this.getConsumedTicks() === 0) {
5564
5619
  this.completeRests(0);
5565
5620
  } else {
5566
- getVoiceIds().forEach((voiceId2) => {
5567
- if (this.getConsumedTicks(voiceId2) > 0) {
5568
- this.completeRests(voiceId2);
5569
- }
5570
- });
5621
+ this.completeRests(getVoiceIds().filter((id) => this.getConsumedTicks(id) > 0));
5571
5622
  }
5572
5623
  return;
5573
- }
5574
- let measureTicks = this.getMeasureTicks();
5575
- let consumedTicks = this.getConsumedTicks(voiceId);
5576
- let remainingTicks = measureTicks - consumedTicks;
5577
- let rests = [];
5578
- let noteLengthValues = Utils8.Enum.getEnumValues(NoteLength6);
5579
- while (remainingTicks > 0) {
5580
- noteLengthValues.forEach((restLength) => {
5581
- let restValue = new RhythmProps4(restLength, false);
5582
- if (restValue.canDot()) {
5583
- let dottedRestValue = new RhythmProps4(restLength, true);
5584
- while (dottedRestValue.ticks <= remainingTicks) {
5585
- rests.push(dottedRestValue);
5586
- remainingTicks -= dottedRestValue.ticks;
5624
+ } else if (Utils10.Is.isArray(voiceId)) {
5625
+ voiceId.forEach((id) => this.completeRests(id));
5626
+ return;
5627
+ } else {
5628
+ validateVoiceId(voiceId);
5629
+ let measureTicks = this.getMeasureTicks();
5630
+ let consumedTicks = this.getConsumedTicks(voiceId);
5631
+ let remainingTicks = measureTicks - consumedTicks;
5632
+ let rests = [];
5633
+ while (remainingTicks > 0) {
5634
+ for (let noteSize = NoteLengthProps4.LongestNoteSize; noteSize <= NoteLengthProps4.ShortestNoteSize; noteSize *= 2) {
5635
+ let restLength = NoteLengthProps4.create(noteSize).noteLength;
5636
+ for (let dotCount = NoteLengthProps4.get(restLength).maxDotCount; dotCount >= 0; dotCount--) {
5637
+ let restProps = RhythmProps4.get(restLength, dotCount);
5638
+ while (restProps.ticks <= remainingTicks) {
5639
+ rests.push(restProps);
5640
+ remainingTicks -= restProps.ticks;
5641
+ }
5587
5642
  }
5588
5643
  }
5589
- while (restValue.ticks <= remainingTicks) {
5590
- rests.push(restValue);
5591
- remainingTicks -= restValue.ticks;
5592
- }
5593
- });
5644
+ }
5645
+ rests.reverse().forEach((rest) => this.addRest(voiceId, rest.noteLength, { dotted: rest.dotCount }));
5594
5646
  }
5595
- rests.reverse().forEach((rest) => this.addRest(voiceId, rest.noteLength, { dotted: rest.dotted }));
5596
5647
  }
5597
5648
  requestLayout() {
5598
5649
  if (!this.needLayout) {
@@ -5685,7 +5736,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5685
5736
  let columnsAreaLeft = this.rect.left + this.leftSolidAreaWidth;
5686
5737
  let columnsAreaRight = this.rect.right - this.rightSolidAreaWidth;
5687
5738
  let columnsAreaWidth = columnsAreaRight - columnsAreaLeft;
5688
- let columnsWidth = Utils8.Math.sum(this.columns.map((col) => col.getRect().width));
5739
+ let columnsWidth = Utils10.Math.sum(this.columns.map((col) => col.getRect().width));
5689
5740
  let columnScale = columnsAreaWidth / columnsWidth;
5690
5741
  let columnLeft = columnsAreaLeft;
5691
5742
  this.columns.forEach((col) => {
@@ -6025,10 +6076,12 @@ var ObjStaff = class extends ObjNotationLine4 {
6025
6076
  this.clefImageAsset = 0 /* TrebleClefPng */;
6026
6077
  this.clefLineDiatonicId = getDiatonicId("G4", staffConfig.isOctaveDown === true);
6027
6078
  this.middleLineDiatonicId = this.clefLineDiatonicId + 2;
6028
- } else {
6079
+ } else if (staffConfig.clef === "F" /* F */) {
6029
6080
  this.clefImageAsset = 1 /* BassClefPng */;
6030
6081
  this.clefLineDiatonicId = getDiatonicId("F3", staffConfig.isOctaveDown === true);
6031
6082
  this.middleLineDiatonicId = this.clefLineDiatonicId - 2;
6083
+ } else {
6084
+ throw new MusicError15(MusicErrorType15.Score, `Invalid staffConfig.clef ${staffConfig.clef}.`);
6032
6085
  }
6033
6086
  this.topLineDiatonicId = this.middleLineDiatonicId + 4;
6034
6087
  this.bottomLineDiatonicId = this.middleLineDiatonicId - 4;
@@ -6164,7 +6217,7 @@ var ObjTab = class extends ObjNotationLine4 {
6164
6217
  __publicField(this, "tuningName");
6165
6218
  __publicField(this, "tuningStrings");
6166
6219
  __publicField(this, "mi");
6167
- if (Utils9.Is.isArray(tabConfig.tuning)) {
6220
+ if (Utils11.Is.isArray(tabConfig.tuning)) {
6168
6221
  this.tuningName = void 0;
6169
6222
  this.tuningStrings = tabConfig.tuning.map((noteName) => Note8.getNote(noteName)).reverse();
6170
6223
  } else if (typeof tabConfig.tuning === "string") {
@@ -6619,7 +6672,7 @@ var ObjHeader = class extends MusicObject {
6619
6672
  };
6620
6673
 
6621
6674
  // src/score/engine/obj-document.ts
6622
- import { Utils as Utils10 } from "@tspro/ts-utils-lib";
6675
+ import { Utils as Utils12 } from "@tspro/ts-utils-lib";
6623
6676
  var ObjDocument = class extends MusicObject {
6624
6677
  constructor() {
6625
6678
  super(void 0);
@@ -6640,35 +6693,35 @@ var ObjDocument = class extends MusicObject {
6640
6693
  return this.mi;
6641
6694
  }
6642
6695
  setScoreConfiguration(config) {
6643
- if (Utils10.Is.isEnumValue(config, StaffPreset)) {
6696
+ if (Utils12.Is.isEnumValue(config, StaffPreset)) {
6644
6697
  switch (config) {
6645
6698
  default:
6646
- case 1 /* Treble */:
6699
+ case "treble" /* Treble */:
6647
6700
  this.curScoreConfig = [{ type: "staff", clef: "G" /* G */ }];
6648
6701
  break;
6649
- case 2 /* Bass */:
6702
+ case "bass" /* Bass */:
6650
6703
  this.curScoreConfig = [{ type: "staff", clef: "F" /* F */ }];
6651
6704
  break;
6652
- case 3 /* Grand */:
6705
+ case "grand" /* Grand */:
6653
6706
  this.curScoreConfig = [
6654
6707
  { type: "staff", clef: "G" /* G */, isGrand: true },
6655
6708
  { type: "staff", clef: "F" /* F */, isGrand: true }
6656
6709
  ];
6657
6710
  break;
6658
- case 4 /* GuitarTreble */:
6711
+ case "guitarTreble" /* GuitarTreble */:
6659
6712
  this.curScoreConfig = [{ type: "staff", clef: "G" /* G */, isOctaveDown: true }];
6660
6713
  break;
6661
- case 8 /* GuitarTab */:
6714
+ case "guitarTab" /* GuitarTab */:
6662
6715
  this.curScoreConfig = [{ type: "tab", tuning: "Standard" }];
6663
6716
  break;
6664
- case 12 /* GuitarCombined */:
6717
+ case "guitarCombined" /* GuitarCombined */:
6665
6718
  this.curScoreConfig = [
6666
6719
  { type: "staff", clef: "G" /* G */, isOctaveDown: true },
6667
6720
  { type: "tab", tuning: "Standard" }
6668
6721
  ];
6669
6722
  break;
6670
6723
  }
6671
- } else if (Utils10.Is.isArray(config)) {
6724
+ } else if (Utils12.Is.isArray(config)) {
6672
6725
  this.curScoreConfig = config;
6673
6726
  } else {
6674
6727
  this.curScoreConfig = [config];
@@ -6894,7 +6947,7 @@ var ObjDocument = class extends MusicObject {
6894
6947
  };
6895
6948
 
6896
6949
  // src/score/pub/document-builder.ts
6897
- import { KeySignature as KeySignature3, Note as Note10, NoteLength as NoteLength7, Scale as Scale2, ScaleType, SymbolSet as SymbolSet2, TimeSignature as TimeSignature2, TuningNameList } from "@tspro/web-music-score/theory";
6950
+ import { KeySignature as KeySignature3, Note as Note10, NoteLength as NoteLength7, RhythmProps as RhythmProps5, Scale as Scale2, ScaleType, SymbolSet as SymbolSet2, TimeSignature as TimeSignature2, TuningNameList, validateNoteLength as validateNoteLength2, validateTupletRatio } from "@tspro/web-music-score/theory";
6898
6951
  import { MusicError as MusicError17, MusicErrorType as MusicErrorType17 } from "@tspro/web-music-score/core";
6899
6952
  function assertArg(condition, argName, argValue) {
6900
6953
  if (!condition) {
@@ -6910,85 +6963,105 @@ function isNote(note) {
6910
6963
  }
6911
6964
  }
6912
6965
  function isVoiceId(value) {
6913
- return Utils11.Is.isNumber(value) && getVoiceIds().indexOf(value) >= 0;
6966
+ return Utils13.Is.isNumber(value) && getVoiceIds().indexOf(value) >= 0;
6914
6967
  }
6915
6968
  function isStringNumber(value) {
6916
- return Utils11.Is.isNumber(value) && getStringNumbers().indexOf(value) >= 0;
6969
+ return Utils13.Is.isNumber(value) && getStringNumbers().indexOf(value) >= 0;
6917
6970
  }
6918
6971
  function assertStaffConfig(staffConfig) {
6919
- assertArg(Utils11.Is.isObject(staffConfig), "staffConfig", staffConfig);
6972
+ assertArg(Utils13.Is.isObject(staffConfig), "staffConfig", staffConfig);
6920
6973
  assertArg(staffConfig.type === "staff", "staffConfig.type", staffConfig.type);
6921
- assertArg(Utils11.Is.isEnumValue(staffConfig.clef, Clef), "staffConfig.clef", staffConfig.clef);
6922
- assertArg(Utils11.Is.isBooleanOrUndefined(staffConfig.isOctaveDown), "staffConfig.isOctaveDown", staffConfig.isOctaveDown);
6923
- assertArg(Utils11.Is.isUndefined(staffConfig.minNote) || isNote(staffConfig.minNote), "staffConfig.minNote", staffConfig.minNote);
6924
- assertArg(Utils11.Is.isUndefined(staffConfig.maxNote) || isNote(staffConfig.maxNote), "staffConfig.maxNote", staffConfig.maxNote);
6925
- assertArg(Utils11.Is.isUndefined(staffConfig.voiceIds) || Utils11.Is.isArray(staffConfig.voiceIds) && staffConfig.voiceIds.every((voiceId) => Utils11.Is.isNumber(voiceId)), "staffConfig.voiceIds", staffConfig.voiceIds);
6926
- assertArg(Utils11.Is.isBooleanOrUndefined(staffConfig.isGrand), "staffConfig.isGrand", staffConfig.isGrand);
6974
+ assertArg(Utils13.Is.isEnumValue(staffConfig.clef, Clef), "staffConfig.clef", staffConfig.clef);
6975
+ assertArg(Utils13.Is.isBooleanOrUndefined(staffConfig.isOctaveDown), "staffConfig.isOctaveDown", staffConfig.isOctaveDown);
6976
+ assertArg(Utils13.Is.isUndefined(staffConfig.minNote) || isNote(staffConfig.minNote), "staffConfig.minNote", staffConfig.minNote);
6977
+ assertArg(Utils13.Is.isUndefined(staffConfig.maxNote) || isNote(staffConfig.maxNote), "staffConfig.maxNote", staffConfig.maxNote);
6978
+ assertArg(Utils13.Is.isUndefined(staffConfig.voiceIds) || Utils13.Is.isArray(staffConfig.voiceIds) && staffConfig.voiceIds.every((voiceId) => Utils13.Is.isNumber(voiceId)), "staffConfig.voiceIds", staffConfig.voiceIds);
6979
+ assertArg(Utils13.Is.isBooleanOrUndefined(staffConfig.isGrand), "staffConfig.isGrand", staffConfig.isGrand);
6927
6980
  }
6928
6981
  function assertTabConfig(tabConfig) {
6929
- assertArg(Utils11.Is.isObject(tabConfig), "tabConfig", tabConfig);
6982
+ assertArg(Utils13.Is.isObject(tabConfig), "tabConfig", tabConfig);
6930
6983
  assertArg(tabConfig.type === "tab", "tabConfig.type", tabConfig.type);
6931
6984
  if (typeof tabConfig.tuning === "string") {
6932
6985
  assertArg(TuningNameList.includes(tabConfig.tuning), "tabConfig.tuning", tabConfig.tuning);
6933
- } else if (Utils11.Is.isArray(tabConfig.tuning)) {
6934
- assertArg(tabConfig.tuning.length === 6 && tabConfig.tuning.every((s) => isNote(s)), "tabConfig.tuning", tabConfig.tuning);
6986
+ } else if (Utils13.Is.isArray(tabConfig.tuning)) {
6987
+ assertArg(tabConfig.tuning.length === getStringNumbers().length && tabConfig.tuning.every((s) => isNote(s)), "tabConfig.tuning", tabConfig.tuning);
6935
6988
  }
6936
- assertArg(Utils11.Is.isUndefined(tabConfig.voiceIds) || Utils11.Is.isArray(tabConfig.voiceIds) && tabConfig.voiceIds.every((voiceId) => Utils11.Is.isNumber(voiceId)), "tabConfig.voiceIds", tabConfig.voiceIds);
6989
+ assertArg(Utils13.Is.isUndefined(tabConfig.voiceIds) || Utils13.Is.isArray(tabConfig.voiceIds) && tabConfig.voiceIds.every((voiceId) => Utils13.Is.isNumber(voiceId)), "tabConfig.voiceIds", tabConfig.voiceIds);
6937
6990
  }
6938
6991
  function assertNoteOptions(options) {
6939
- assertArg(Utils11.Is.isObject(options), "noteOptions", options);
6940
- assertArg(Utils11.Is.isBooleanOrUndefined(options.dotted), "noteOptions.dotted", options.dotted);
6941
- assertArg(Utils11.Is.isEnumValueOrUndefined(options.stem, Stem), "noteOptions.stem", options.stem);
6942
- assertArg(Utils11.Is.isStringOrUndefined(options.color), "noteOptions.color", options.color);
6943
- assertArg(Utils11.Is.isBooleanOrUndefined(options.arpeggio) || Utils11.Is.isEnumValue(options.arpeggio, Arpeggio), "noteOptions.arpeggio", options.arpeggio);
6944
- assertArg(Utils11.Is.isBooleanOrUndefined(options.staccato), "noteOptions.staccato", options.staccato);
6945
- assertArg(Utils11.Is.isBooleanOrUndefined(options.diamond), "noteOptions.diamond", options.diamond);
6946
- assertArg(Utils11.Is.isBooleanOrUndefined(options.triplet), "noteOptions.triplet", options.triplet);
6947
- assertArg(Utils11.Is.isUndefined(options.string) || isStringNumber(options.string) || Utils11.Is.isArray(options.string) && options.string.length > 0 && options.string.every((string) => isStringNumber(string)), "noteOptions.string", options.string);
6992
+ assertArg(Utils13.Is.isObject(options), "noteOptions", options);
6993
+ assertArg(Utils13.Is.isBooleanOrUndefined(options.dotted) || Utils13.Is.isIntegerGte(options.dotted, 0), "noteOptions.dotted", options.dotted);
6994
+ assertArg(Utils13.Is.isEnumValueOrUndefined(options.stem, Stem), "noteOptions.stem", options.stem);
6995
+ assertArg(Utils13.Is.isStringOrUndefined(options.color), "noteOptions.color", options.color);
6996
+ assertArg(Utils13.Is.isBooleanOrUndefined(options.arpeggio) || Utils13.Is.isEnumValue(options.arpeggio, Arpeggio), "noteOptions.arpeggio", options.arpeggio);
6997
+ assertArg(Utils13.Is.isBooleanOrUndefined(options.staccato), "noteOptions.staccato", options.staccato);
6998
+ assertArg(Utils13.Is.isBooleanOrUndefined(options.diamond), "noteOptions.diamond", options.diamond);
6999
+ assertArg(Utils13.Is.isBooleanOrUndefined(options.triplet), "noteOptions.triplet", options.triplet);
7000
+ assertArg(Utils13.Is.isUndefined(options.string) || isStringNumber(options.string) || Utils13.Is.isNonEmptyArray(options.string) && options.string.every((string) => isStringNumber(string)), "noteOptions.string", options.string);
7001
+ assertArg(Utils13.Is.isUndefined(options.tieSpan), 'NoteOptions.tieSpan was removed. Use addConnective("tie", tieSpan)', "");
7002
+ assertArg(Utils13.Is.isUndefined(options.slurSpan), 'NoteOptions.slurSpan was removed. Use addConnective("slur", slurSpan)', "");
6948
7003
  }
6949
7004
  function assertRestOptions(options) {
6950
- assertArg(Utils11.Is.isObject(options), "restOptions", options);
6951
- assertArg(Utils11.Is.isBooleanOrUndefined(options.dotted), "restOptions.dotted", options.dotted);
6952
- assertArg(Utils11.Is.isStringOrUndefined(options.staffPos) || Utils11.Is.isInteger(options.staffPos) || options.staffPos instanceof Note10, "restOptions.staffPos", options.staffPos);
6953
- assertArg(Utils11.Is.isStringOrUndefined(options.color), "restOptions.color", options.color);
6954
- assertArg(Utils11.Is.isBooleanOrUndefined(options.hide), "restOptions.hide", options.hide);
6955
- assertArg(Utils11.Is.isBooleanOrUndefined(options.triplet), "restOptions.triplet", options.triplet);
7005
+ assertArg(Utils13.Is.isObject(options), "restOptions", options);
7006
+ assertArg(Utils13.Is.isBooleanOrUndefined(options.dotted) || Utils13.Is.isIntegerGte(options.dotted, 0), "restOptions.dotted", options.dotted);
7007
+ assertArg(Utils13.Is.isStringOrUndefined(options.staffPos) || Utils13.Is.isInteger(options.staffPos) || options.staffPos instanceof Note10, "restOptions.staffPos", options.staffPos);
7008
+ assertArg(Utils13.Is.isStringOrUndefined(options.color), "restOptions.color", options.color);
7009
+ assertArg(Utils13.Is.isBooleanOrUndefined(options.hide), "restOptions.hide", options.hide);
7010
+ assertArg(Utils13.Is.isBooleanOrUndefined(options.triplet), "restOptions.triplet", options.triplet);
6956
7011
  }
6957
7012
  function assertStaffTabOrGRoups(staffTabOrGroups) {
6958
7013
  assertArg(
6959
- Utils11.Is.isStringOrUndefined(staffTabOrGroups) || Utils11.Is.isIntegerGte(staffTabOrGroups, 0) || Utils11.Is.isArray(staffTabOrGroups) && staffTabOrGroups.every(
6960
- (staffTabOrGroup) => Utils11.Is.isString(staffTabOrGroup) || Utils11.Is.isIntegerGte(staffTabOrGroup, 0)
7014
+ Utils13.Is.isStringOrUndefined(staffTabOrGroups) || Utils13.Is.isIntegerGte(staffTabOrGroups, 0) || Utils13.Is.isNonEmptyArray(staffTabOrGroups) && staffTabOrGroups.every(
7015
+ (staffTabOrGroup) => Utils13.Is.isString(staffTabOrGroup) || Utils13.Is.isIntegerGte(staffTabOrGroup, 0)
6961
7016
  ),
6962
7017
  "staffTabOrGroup",
6963
7018
  staffTabOrGroups
6964
7019
  );
6965
7020
  }
7021
+ function isNoteLength(noteLen) {
7022
+ try {
7023
+ validateNoteLength2(noteLen);
7024
+ return true;
7025
+ } catch (e) {
7026
+ return false;
7027
+ }
7028
+ }
7029
+ function isTupletRatio(tupletRatio) {
7030
+ try {
7031
+ validateTupletRatio(tupletRatio);
7032
+ return true;
7033
+ } catch (e) {
7034
+ return false;
7035
+ }
7036
+ }
6966
7037
  var DocumentBuilder = class {
6967
7038
  constructor() {
6968
7039
  __publicField(this, "doc");
6969
7040
  this.doc = new ObjDocument();
6970
7041
  }
6971
7042
  setScoreConfiguration(config) {
6972
- if (Utils11.Is.isEnumValue(config, StaffPreset)) {
6973
- } else if (Utils11.Is.isObject(config) && config.type === "staff") {
7043
+ if (Utils13.Is.isEnumValue(config, StaffPreset)) {
7044
+ this.doc.setScoreConfiguration(config);
7045
+ } else if (Utils13.Is.isObject(config) && config.type === "staff") {
6974
7046
  assertStaffConfig(config);
6975
- } else if (Utils11.Is.isObject(config) && config.type === "tab") {
7047
+ this.doc.setScoreConfiguration(config);
7048
+ } else if (Utils13.Is.isObject(config) && config.type === "tab") {
6976
7049
  assertTabConfig(config);
6977
- } else if (Utils11.Is.isArray(config)) {
6978
- assertArg(config.length > 0, "config", config);
7050
+ this.doc.setScoreConfiguration(config);
7051
+ } else if (Utils13.Is.isNonEmptyArray(config)) {
6979
7052
  config.forEach((c) => {
6980
- if (Utils11.Is.isObject(c) && c.type === "staff") {
7053
+ if (Utils13.Is.isObject(c) && c.type === "staff") {
6981
7054
  assertStaffConfig(c);
6982
- } else if (Utils11.Is.isObject(c) && c.type === "tab") {
7055
+ } else if (Utils13.Is.isObject(c) && c.type === "tab") {
6983
7056
  assertTabConfig(c);
6984
7057
  } else {
6985
7058
  assertArg(false, "config", config);
6986
7059
  }
6987
7060
  });
7061
+ this.doc.setScoreConfiguration(config);
6988
7062
  } else {
6989
7063
  assertArg(false, "config", config);
6990
7064
  }
6991
- this.doc.setScoreConfiguration(config);
6992
7065
  return this;
6993
7066
  }
6994
7067
  getMeasure() {
@@ -6999,14 +7072,14 @@ var DocumentBuilder = class {
6999
7072
  return this.doc.getMusicInterface();
7000
7073
  }
7001
7074
  setHeader(title, composer, arranger) {
7002
- assertArg(Utils11.Is.isStringOrUndefined(title), "title", title);
7003
- assertArg(Utils11.Is.isStringOrUndefined(composer), "composer", composer);
7004
- assertArg(Utils11.Is.isStringOrUndefined(arranger), "arranger", arranger);
7075
+ assertArg(Utils13.Is.isStringOrUndefined(title), "title", title);
7076
+ assertArg(Utils13.Is.isStringOrUndefined(composer), "composer", composer);
7077
+ assertArg(Utils13.Is.isStringOrUndefined(arranger), "arranger", arranger);
7005
7078
  this.doc.setHeader(title, composer, arranger);
7006
7079
  return this;
7007
7080
  }
7008
7081
  setMeasuresPerRow(measuresPerRow) {
7009
- assertArg(Utils11.Is.isIntegerGte(measuresPerRow, 1) || measuresPerRow === Infinity, "measuresPerRow", measuresPerRow);
7082
+ assertArg(Utils13.Is.isIntegerGte(measuresPerRow, 1) || Utils13.Is.isPosInfinity(measuresPerRow), "measuresPerRow", measuresPerRow);
7010
7083
  this.doc.setMeasuresPerRow(measuresPerRow);
7011
7084
  return this;
7012
7085
  }
@@ -7015,30 +7088,30 @@ var DocumentBuilder = class {
7015
7088
  return this;
7016
7089
  }
7017
7090
  setKeySignature(...args) {
7018
- assertArg(args[0] instanceof Scale2 || args[0] instanceof KeySignature3 || Utils11.Is.isString(args[0]) && Utils11.Is.isEnumValue(args[1], ScaleType), "keySignature", args);
7091
+ assertArg(args[0] instanceof Scale2 || args[0] instanceof KeySignature3 || Utils13.Is.isNonEmptyString(args[0]) && (args.length === 1 || Utils13.Is.isEnumValue(args[1], ScaleType)), "keySignature", args);
7019
7092
  this.getMeasure().setKeySignature(...args);
7020
7093
  return this;
7021
7094
  }
7022
7095
  setTimeSignature(timeSignature) {
7023
- assertArg(timeSignature instanceof TimeSignature2 || Utils11.Is.isString(timeSignature), "timeSignature", timeSignature);
7096
+ assertArg(timeSignature instanceof TimeSignature2 || Utils13.Is.isNonEmptyString(timeSignature), "timeSignature", timeSignature);
7024
7097
  this.getMeasure().setTimeSignature(timeSignature);
7025
7098
  return this;
7026
7099
  }
7027
7100
  setTempo(beatsPerMinute, beatLength, dotted) {
7028
- assertArg(Utils11.Is.isIntegerGte(beatsPerMinute, 1), "beatsPerMinute", beatsPerMinute);
7101
+ assertArg(Utils13.Is.isIntegerGte(beatsPerMinute, 1), "beatsPerMinute", beatsPerMinute);
7029
7102
  if (beatLength === void 0) {
7030
- assertArg(Utils11.Is.isUndefined(dotted), "dotted", dotted);
7103
+ assertArg(Utils13.Is.isUndefined(dotted), "dotted", dotted);
7031
7104
  } else {
7032
- assertArg(Utils11.Is.isEnumValue(beatLength, NoteLength7), "beatLength", beatLength);
7033
- assertArg(Utils11.Is.isBooleanOrUndefined(dotted), "dotted", dotted);
7105
+ assertArg(Utils13.Is.isEnumValue(beatLength, NoteLength7) || isNoteLength(beatLength), "beatLength", beatLength);
7106
+ assertArg(Utils13.Is.isBooleanOrUndefined(dotted) || Utils13.Is.isIntegerGte(dotted, 0), "dotted", dotted);
7034
7107
  }
7035
7108
  this.getMeasure().setTempo(beatsPerMinute, beatLength, dotted);
7036
7109
  return this;
7037
7110
  }
7038
7111
  addNote(voiceId, note, noteLength, options) {
7039
7112
  assertArg(isVoiceId(voiceId), "voiceId", voiceId);
7040
- assertArg(note instanceof Note10 || Utils11.Is.isString(note), "note", note);
7041
- assertArg(Utils11.Is.isEnumValue(noteLength, NoteLength7), "noteLength", noteLength);
7113
+ assertArg(note instanceof Note10 || Utils13.Is.isNonEmptyString(note), "note", note);
7114
+ assertArg(Utils13.Is.isEnumValue(noteLength, NoteLength7) || isNoteLength(noteLength), "noteLength", noteLength);
7042
7115
  if (options !== void 0) {
7043
7116
  assertNoteOptions(options);
7044
7117
  }
@@ -7047,8 +7120,8 @@ var DocumentBuilder = class {
7047
7120
  }
7048
7121
  addChord(voiceId, notes, noteLength, options) {
7049
7122
  assertArg(isVoiceId(voiceId), "voiceId", voiceId);
7050
- assertArg(Utils11.Is.isArray(notes) && notes.length >= 1 && notes.every((note) => note instanceof Note10 || Utils11.Is.isString(note)), "notes", notes);
7051
- assertArg(Utils11.Is.isEnumValue(noteLength, NoteLength7), "noteLength", noteLength);
7123
+ assertArg(Utils13.Is.isNonEmptyArray(notes) && notes.every((note) => note instanceof Note10 || Utils13.Is.isNonEmptyString(note)), "notes", notes);
7124
+ assertArg(Utils13.Is.isEnumValue(noteLength, NoteLength7) || isNoteLength(noteLength), "noteLength", noteLength);
7052
7125
  if (options !== void 0) {
7053
7126
  assertNoteOptions(options);
7054
7127
  }
@@ -7057,33 +7130,91 @@ var DocumentBuilder = class {
7057
7130
  }
7058
7131
  addRest(voiceId, restLength, options) {
7059
7132
  assertArg(isVoiceId(voiceId), "voiceId", voiceId);
7060
- assertArg(Utils11.Is.isEnumValue(restLength, NoteLength7), "restLength", restLength);
7133
+ assertArg(Utils13.Is.isEnumValue(restLength, NoteLength7) || isNoteLength(restLength), "restLength", restLength);
7061
7134
  if (options !== void 0) {
7062
7135
  assertRestOptions(options);
7063
7136
  }
7064
7137
  this.getMeasure().addRest(voiceId, restLength, options);
7065
7138
  return this;
7066
7139
  }
7140
+ /**
7141
+ * Usage:
7142
+ * <pre>
7143
+ * addTuplet(0, Theory.Tuplet.Triplet, notes => {
7144
+ * notes.addNote("G3", Theory.NoteLength.Eighth);
7145
+ * notes.addNote("B3", Theory.NoteLength.Eighth);
7146
+ * notes.addNote("D4", Theory.NoteLength.Eighth);
7147
+ * });
7148
+ * </pre>
7149
+ *
7150
+ * @param voiceId
7151
+ * @param tupletRatio - You can also use Theory.Tuplet presets (e.g. Theory.Tuplet.Triplet).
7152
+ * @param tupletBuilder
7153
+ * @returns
7154
+ */
7155
+ addTuplet(voiceId, tupletRatio, tupletBuilder) {
7156
+ assertArg(isVoiceId(voiceId), "voiceId", voiceId);
7157
+ assertArg(Utils13.Is.isFunction(tupletBuilder), "tupletBuilder", tupletBuilder);
7158
+ assertArg(isTupletRatio(tupletRatio) && Utils13.Is.isBooleanOrUndefined(tupletRatio.showRatio), "tupletRatio", tupletRatio);
7159
+ let tupletSymbols = [];
7160
+ const helper = {
7161
+ addNote: (note, noteLength, options) => {
7162
+ assertArg(note instanceof Note10 || Utils13.Is.isNonEmptyString(note), "note", note);
7163
+ assertArg(Utils13.Is.isEnumValue(noteLength, NoteLength7) || isNoteLength(noteLength), "noteLength", noteLength);
7164
+ if (options !== void 0) {
7165
+ delete options.triplet;
7166
+ assertNoteOptions(options);
7167
+ }
7168
+ let s = this.getMeasure().addNoteGroup(voiceId, [note], noteLength, options, tupletRatio);
7169
+ tupletSymbols.push(s);
7170
+ return helper;
7171
+ },
7172
+ addChord: (notes, noteLength, options) => {
7173
+ assertArg(Utils13.Is.isNonEmptyArray(notes) && notes.every((note) => note instanceof Note10 || Utils13.Is.isNonEmptyString(note)), "notes", notes);
7174
+ assertArg(Utils13.Is.isEnumValue(noteLength, NoteLength7) || isNoteLength(noteLength), "noteLength", noteLength);
7175
+ if (options !== void 0) {
7176
+ delete options.triplet;
7177
+ assertNoteOptions(options);
7178
+ }
7179
+ let s = this.getMeasure().addNoteGroup(voiceId, notes, noteLength, options, tupletRatio);
7180
+ tupletSymbols.push(s);
7181
+ return helper;
7182
+ },
7183
+ addRest: (restLength, options) => {
7184
+ assertArg(Utils13.Is.isEnumValue(restLength, NoteLength7) || isNoteLength(restLength), "restLength", restLength);
7185
+ if (options !== void 0) {
7186
+ delete options.triplet;
7187
+ assertRestOptions(options);
7188
+ }
7189
+ let s = this.getMeasure().addRest(voiceId, restLength, options, tupletRatio);
7190
+ tupletSymbols.push(s);
7191
+ return helper;
7192
+ }
7193
+ };
7194
+ tupletBuilder(helper);
7195
+ ObjBeamGroup.createTuplet(tupletSymbols, tupletRatio);
7196
+ return this;
7197
+ }
7067
7198
  addFermataInternal(staffTabOrGroups, fermata) {
7068
7199
  assertStaffTabOrGRoups(staffTabOrGroups);
7069
- assertArg(Utils11.Is.isEnumValue(fermata, Fermata), "fermata", fermata);
7200
+ assertArg(Utils13.Is.isEnumValue(fermata, Fermata), "fermata", fermata);
7070
7201
  this.getMeasure().addFermata(staffTabOrGroups, fermata);
7071
7202
  return this;
7072
7203
  }
7073
- addFermata(fermata = 0 /* AtNote */) {
7204
+ addFermata(fermata = "atNote" /* AtNote */) {
7074
7205
  return this.addFermataInternal(void 0, fermata);
7075
7206
  }
7076
7207
  /** @param staffTabOrGroups - staff/tab index (0=top), staff/tab name, or staff group name. */
7077
- addFermataTo(staffTabOrGroups, fermata = 0 /* AtNote */) {
7208
+ addFermataTo(staffTabOrGroups, fermata = "atNote" /* AtNote */) {
7078
7209
  return this.addFermataInternal(staffTabOrGroups, fermata);
7079
7210
  }
7080
7211
  addNavigationInternal(staffTabOrGroups, navigation, ...args) {
7081
7212
  assertStaffTabOrGRoups(staffTabOrGroups);
7082
- assertArg(Utils11.Is.isEnumValue(navigation, Navigation), "navigation", navigation);
7083
- if (navigation === 9 /* EndRepeat */ && args.length > 0) {
7084
- assertArg(Utils11.Is.isIntegerGte(args[0], 1), "playCount", args[0]);
7085
- } else if (navigation === 10 /* Ending */ && args.length > 0) {
7086
- assertArg(args.every((passage) => Utils11.Is.isIntegerGte(passage, 1)), "passages", args);
7213
+ assertArg(Utils13.Is.isEnumValue(navigation, Navigation), "navigation", navigation);
7214
+ if (navigation === "endRepeat" /* EndRepeat */ && args.length > 0) {
7215
+ assertArg(Utils13.Is.isIntegerGte(args[0], 1), "playCount", args[0]);
7216
+ } else if (navigation === "ending" /* Ending */ && args.length > 0) {
7217
+ assertArg(args.every((passage) => Utils13.Is.isIntegerGte(passage, 1)), "passages", args);
7087
7218
  }
7088
7219
  this.getMeasure().addNavigation(staffTabOrGroups, navigation, ...args);
7089
7220
  return this;
@@ -7094,10 +7225,35 @@ var DocumentBuilder = class {
7094
7225
  addNavigationTo(staffTabOrGroups, navigation, ...args) {
7095
7226
  return this.addNavigationInternal(staffTabOrGroups, navigation, ...args);
7096
7227
  }
7228
+ addAnnotationInternal(staffTabOrGroups, annotation, text) {
7229
+ annotation != null ? annotation : annotation = getAnnotation(text);
7230
+ if (annotation === void 0) {
7231
+ throw new MusicError17(MusicErrorType17.Score, `Annotation text "${text}" is not known annotation.`);
7232
+ }
7233
+ assertStaffTabOrGRoups(staffTabOrGroups);
7234
+ assertArg(Utils13.Is.isEnumValue(annotation, Annotation), "annotation", annotation);
7235
+ assertArg(Utils13.Is.isNonEmptyString(text), "text", text);
7236
+ this.getMeasure().addAnnotation(staffTabOrGroups, annotation, text);
7237
+ return this;
7238
+ }
7239
+ addAnnotation(...args) {
7240
+ if (args.length === 1) {
7241
+ return this.addAnnotationInternal(void 0, void 0, args[0]);
7242
+ } else {
7243
+ return this.addAnnotationInternal(void 0, args[0], args[1]);
7244
+ }
7245
+ }
7246
+ addAnnotationTo(staffTabOrGroups, ...args) {
7247
+ if (args.length === 1) {
7248
+ return this.addAnnotationInternal(staffTabOrGroups, void 0, args[0]);
7249
+ } else {
7250
+ return this.addAnnotationInternal(staffTabOrGroups, args[0], args[1]);
7251
+ }
7252
+ }
7097
7253
  addLabelInternal(staffTabOrGroups, label, text) {
7098
7254
  assertStaffTabOrGRoups(staffTabOrGroups);
7099
- assertArg(Utils11.Is.isEnumValue(label, Label), "label", label);
7100
- assertArg(Utils11.Is.isString(text), "text", text);
7255
+ assertArg(Utils13.Is.isEnumValue(label, Label), "label", label);
7256
+ assertArg(Utils13.Is.isNonEmptyString(text), "text", text);
7101
7257
  this.getMeasure().addLabel(staffTabOrGroups, label, text);
7102
7258
  return this;
7103
7259
  }
@@ -7108,45 +7264,70 @@ var DocumentBuilder = class {
7108
7264
  addLabelTo(staffTabOrGroups, label, text) {
7109
7265
  return this.addLabelInternal(staffTabOrGroups, label, text);
7110
7266
  }
7111
- addAnnotationInternal(staffTabOrGroups, annotation, text) {
7112
- assertStaffTabOrGRoups(staffTabOrGroups);
7113
- assertArg(Utils11.Is.isEnumValue(annotation, Annotation), "annotation", annotation);
7114
- assertArg(Utils11.Is.isString(text), "text", text);
7115
- this.getMeasure().addAnnotation(staffTabOrGroups, annotation, text);
7116
- return this;
7117
- }
7118
- addAnnotation(annotation, text) {
7119
- return this.addAnnotationInternal(void 0, annotation, text);
7120
- }
7121
- /** @param staffTabOrGroups - staff/tab index (0=top), staff/tab name, or staff group name. */
7122
- addAnnotationTo(staffTabOrGroups, annotation, text) {
7123
- return this.addAnnotationInternal(staffTabOrGroups, annotation, text);
7124
- }
7125
7267
  addConnective(connective, ...args) {
7126
- assertArg(Utils11.Is.isEnumValue(connective, Connective), "connective", connective);
7127
- if (connective === 0 /* Tie */) {
7128
- assertArg(Utils11.Is.isUndefined(args[0]) || Utils11.Is.isInteger(args[0]) || Utils11.Is.isEnumValue(args[0], TieType), "tieSpan", args[0]);
7129
- assertArg(Utils11.Is.isEnumValueOrUndefined(args[1], NoteAnchor), "noteAnchor", args[1]);
7268
+ assertArg(Utils13.Is.isEnumValue(connective, Connective), "connective", connective);
7269
+ if (connective === "tie" /* Tie */) {
7270
+ assertArg(Utils13.Is.isIntegerOrUndefined(args[0]) || Utils13.Is.isEnumValue(args[0], TieType), "tieSpan", args[0]);
7271
+ assertArg(Utils13.Is.isEnumValueOrUndefined(args[1], NoteAnchor), "noteAnchor", args[1]);
7130
7272
  let tieSpan = args[0];
7131
7273
  let noteAnchor = args[1];
7132
7274
  this.getMeasure().addConnective(connective, tieSpan, noteAnchor);
7133
- } else if (connective === 1 /* Slur */) {
7134
- assertArg(Utils11.Is.isUndefined(args[0]) || Utils11.Is.isInteger(args[0]), "slurSpan", args[0]);
7135
- assertArg(Utils11.Is.isEnumValueOrUndefined(args[1], NoteAnchor), "noteAnchor", args[1]);
7275
+ } else if (connective === "slur" /* Slur */) {
7276
+ assertArg(Utils13.Is.isIntegerOrUndefined(args[0]), "slurSpan", args[0]);
7277
+ assertArg(Utils13.Is.isEnumValueOrUndefined(args[1], NoteAnchor), "noteAnchor", args[1]);
7136
7278
  let slurSpan = args[0];
7137
7279
  let noteAnchor = args[1];
7138
7280
  this.getMeasure().addConnective(connective, slurSpan, noteAnchor);
7139
- } else if (connective === 2 /* Slide */) {
7140
- assertArg(Utils11.Is.isEnumValueOrUndefined(args[0], NoteAnchor), "noteAnchor", args[0]);
7281
+ } else if (connective === "slide" /* Slide */) {
7282
+ assertArg(Utils13.Is.isEnumValueOrUndefined(args[0], NoteAnchor), "noteAnchor", args[0]);
7141
7283
  let noteAnchor = args[0];
7142
7284
  this.getMeasure().addConnective(connective, noteAnchor);
7143
7285
  }
7144
7286
  return this;
7145
7287
  }
7146
- addExtension(extensionLength, extensionVisible) {
7147
- assertArg(Utils11.Is.isIntegerGte(extensionLength, 0) || extensionLength === Infinity || Utils11.Is.isEnumValue(extensionLength, NoteLength7), "extendionLength", extensionLength);
7148
- assertArg(Utils11.Is.isBooleanOrUndefined(extensionVisible), "extensionVisible", extensionVisible);
7149
- this.getMeasure().addExtension(extensionLength, extensionVisible != null ? extensionVisible : true);
7288
+ /**
7289
+ * Extension length example:
7290
+ * <pre>
7291
+ * addExtension(ext => ext.notes("1n", 2)) // length is 2 whole notes
7292
+ * addExtension(ext => ext.measures(3).hide()) // length is 3 measures, hidden
7293
+ * addExtension(ext => ext.measures(1).notes("8n")) // length is 1 measure + 1 eigth note
7294
+ * addExtension(ext => ext.infinity()) // length is as long as possible
7295
+ * </pre>
7296
+ * @param extensionLength
7297
+ * @param extensionVisible
7298
+ * @returns
7299
+ */
7300
+ addExtension(extensionBuilder) {
7301
+ assertArg(Utils13.Is.isFunctionOrUndefined(extensionBuilder), "addExtension() has new usage, for e.g. addExtension(ext => ext.measures(2)). Please refer to README or API Reference.", extensionBuilder);
7302
+ let ticks = 0;
7303
+ let visible = true;
7304
+ const helper = {
7305
+ notes: (noteLength, noteCount) => {
7306
+ assertArg(Utils13.Is.isEnumValue(noteLength, NoteLength7) || isNoteLength(noteLength), "noteLength", noteLength);
7307
+ assertArg(Utils13.Is.isUndefined(noteCount) || Utils13.Is.isNumber(noteCount) && noteCount >= 0, "noteCount", noteCount);
7308
+ ticks += RhythmProps5.get(noteLength).ticks * (noteCount != null ? noteCount : 1);
7309
+ return helper;
7310
+ },
7311
+ measures: (measureCount) => {
7312
+ assertArg(Utils13.Is.isNumber(measureCount) && measureCount >= 1, "measureCount", measureCount);
7313
+ ticks += this.getMeasure().getMeasureTicks() * measureCount;
7314
+ return helper;
7315
+ },
7316
+ infinity: () => {
7317
+ ticks = Infinity;
7318
+ return helper;
7319
+ },
7320
+ hide: () => {
7321
+ visible = false;
7322
+ return helper;
7323
+ }
7324
+ };
7325
+ if (extensionBuilder) {
7326
+ extensionBuilder(helper);
7327
+ } else {
7328
+ ticks = Infinity;
7329
+ }
7330
+ this.getMeasure().addExtension(ticks, visible);
7150
7331
  return this;
7151
7332
  }
7152
7333
  /**
@@ -7156,14 +7337,14 @@ var DocumentBuilder = class {
7156
7337
  * @param verticalPosition - Vertical position, are elements added above, below or both.
7157
7338
  * @returns
7158
7339
  */
7159
- addStaffGroup(groupName, staffsTabsAndGroups, verticalPosition = 3 /* Auto */) {
7160
- assertArg(Utils11.Is.isString(groupName) && groupName.length > 0, "groupName", groupName);
7340
+ addStaffGroup(groupName, staffsTabsAndGroups, verticalPosition = "auto" /* Auto */) {
7341
+ assertArg(Utils13.Is.isNonEmptyString(groupName), "groupName", groupName);
7161
7342
  assertArg(
7162
- Utils11.Is.isString(staffsTabsAndGroups) && staffsTabsAndGroups.length > 0 || Utils11.Is.isIntegerGte(staffsTabsAndGroups, 0) || Utils11.Is.isArray(staffsTabsAndGroups) && staffsTabsAndGroups.every((line) => Utils11.Is.isString(line) && line.length > 0 || Utils11.Is.isIntegerGte(line, 0)),
7343
+ Utils13.Is.isNonEmptyString(staffsTabsAndGroups) || Utils13.Is.isIntegerGte(staffsTabsAndGroups, 0) || Utils13.Is.isNonEmptyArray(staffsTabsAndGroups) && staffsTabsAndGroups.every((line) => Utils13.Is.isNonEmptyString(line) || Utils13.Is.isIntegerGte(line, 0)),
7163
7344
  "staffsTabsAndGroups",
7164
7345
  staffsTabsAndGroups
7165
7346
  );
7166
- assertArg(Utils11.Is.isEnumValue(verticalPosition, VerticalPosition), "verticalPosition", verticalPosition);
7347
+ assertArg(Utils13.Is.isEnumValue(verticalPosition, VerticalPosition), "verticalPosition", verticalPosition);
7167
7348
  this.doc.addStaffGroup(groupName, staffsTabsAndGroups, verticalPosition);
7168
7349
  return this;
7169
7350
  }
@@ -7181,13 +7362,13 @@ var DocumentBuilder = class {
7181
7362
  return this;
7182
7363
  }
7183
7364
  completeRests(voiceId) {
7184
- assertArg(Utils11.Is.isUndefined(voiceId) || isVoiceId(voiceId), "voiceId", voiceId);
7365
+ assertArg(Utils13.Is.isUndefined(voiceId) || isVoiceId(voiceId) || Utils13.Is.isArray(voiceId) && voiceId.every((id) => isVoiceId(id)), "voiceId", voiceId);
7185
7366
  this.getMeasure().completeRests(voiceId);
7186
7367
  return this;
7187
7368
  }
7188
7369
  addScaleArpeggio(scale, bottomNote, numOctaves) {
7189
- assertArg(Utils11.Is.isString(bottomNote), "bottomNote", bottomNote);
7190
- assertArg(Utils11.Is.isIntegerGte(numOctaves, 1), "numOctaves", numOctaves);
7370
+ assertArg(Utils13.Is.isNonEmptyString(bottomNote), "bottomNote", bottomNote);
7371
+ assertArg(Utils13.Is.isIntegerGte(numOctaves, 1), "numOctaves", numOctaves);
7191
7372
  let ts = this.getMeasure().getTimeSignature();
7192
7373
  let notes = scale.getScaleNotes(bottomNote, numOctaves);
7193
7374
  for (let i = 0; i < notes.length; i++) {
@@ -7196,7 +7377,7 @@ var DocumentBuilder = class {
7196
7377
  }
7197
7378
  let note = notes[i];
7198
7379
  this.addNote(0, note, ts.beatLength);
7199
- this.addLabel(0 /* Note */, note.formatOmitOctave(SymbolSet2.Unicode));
7380
+ this.addLabel("note" /* Note */, note.formatOmitOctave(SymbolSet2.Unicode));
7200
7381
  }
7201
7382
  return this;
7202
7383
  }
@@ -7236,7 +7417,7 @@ var ScoreObjectEvent = class extends ScoreEvent {
7236
7417
 
7237
7418
  // src/score/pub/interface.ts
7238
7419
  import * as Audio2 from "@tspro/web-music-score/audio";
7239
- import { Utils as Utils12 } from "@tspro/ts-utils-lib";
7420
+ import { Utils as Utils14 } from "@tspro/ts-utils-lib";
7240
7421
  import { MusicError as MusicError19, MusicErrorType as MusicErrorType19 } from "@tspro/web-music-score/core";
7241
7422
  function assertArg2(condition, argName, argValue) {
7242
7423
  if (!condition) {
@@ -7251,7 +7432,7 @@ function require_t(t, message) {
7251
7432
  }
7252
7433
  }
7253
7434
  function isVoiceId2(value) {
7254
- return Utils12.Is.isNumber(value) && getVoiceIds().indexOf(value) >= 0;
7435
+ return Utils14.Is.isNumber(value) && getVoiceIds().indexOf(value) >= 0;
7255
7436
  }
7256
7437
  function getNotationLine(line) {
7257
7438
  if (line instanceof ObjStaff || line instanceof ObjTab) {
@@ -7373,7 +7554,7 @@ var _MDocument = class _MDocument extends MusicInterface6 {
7373
7554
  return this.obj.getMeasures().map((m) => m.getMusicInterface());
7374
7555
  }
7375
7556
  play(fn) {
7376
- assertArg2(Utils12.Is.isFunctionOrUndefined(fn), "playStateChangeListener", fn);
7557
+ assertArg2(Utils14.Is.isFunctionOrUndefined(fn), "playStateChangeListener", fn);
7377
7558
  return new MPlayer(this, fn).play();
7378
7559
  }
7379
7560
  };
@@ -7393,7 +7574,7 @@ var _MEnding = class _MEnding extends MusicInterface6 {
7393
7574
  return this.obj.passages;
7394
7575
  }
7395
7576
  hasPassage(passage) {
7396
- assertArg2(Utils12.Is.isIntegerGte(passage, 1), "passage", passage);
7577
+ assertArg2(Utils14.Is.isIntegerGte(passage, 1), "passage", passage);
7397
7578
  return this.obj.hasPassage(passage);
7398
7579
  }
7399
7580
  };
@@ -7797,7 +7978,7 @@ var _MPlayer = class _MPlayer {
7797
7978
  constructor(doc, fn) {
7798
7979
  __publicField(this, "player");
7799
7980
  assertArg2(doc instanceof MDocument2, "doc", doc);
7800
- assertArg2(Utils12.Is.isFunctionOrUndefined(fn), "playStateChangeListener", fn);
7981
+ assertArg2(Utils14.Is.isFunctionOrUndefined(fn), "playStateChangeListener", fn);
7801
7982
  this.player = new Player();
7802
7983
  this.player.setDocument(doc.getMusicObject());
7803
7984
  this.player.setCursorPositionChangeListener((cursorRect) => doc.getMusicObject().updateCursorRect(cursorRect));
@@ -7832,17 +8013,17 @@ var MRenderer2 = class {
7832
8013
  this.renderer = new Renderer(this);
7833
8014
  }
7834
8015
  setDocument(doc) {
7835
- assertArg2(Utils12.Is.isUndefined(doc) || doc instanceof MDocument2, "doc", doc);
8016
+ assertArg2(Utils14.Is.isUndefined(doc) || doc instanceof MDocument2, "doc", doc);
7836
8017
  this.renderer.setDocument(doc);
7837
8018
  return this;
7838
8019
  }
7839
8020
  setCanvas(canvas) {
7840
- canvas = require_t(Utils12.Dom.getCanvas(canvas), typeof canvas === "string" ? "Cannot set renderer canvas because invalid canvas id: " + canvas : "Cannot set renderer canvas because given canvas is undefined.");
8021
+ canvas = require_t(Utils14.Dom.getCanvas(canvas), typeof canvas === "string" ? "Cannot set renderer canvas because invalid canvas id: " + canvas : "Cannot set renderer canvas because given canvas is undefined.");
7841
8022
  this.renderer.setCanvas(canvas);
7842
8023
  return this;
7843
8024
  }
7844
8025
  setScoreEventListener(fn) {
7845
- assertArg2(Utils12.Is.isFunctionOrUndefined(fn), "scoreEventListener", fn);
8026
+ assertArg2(Utils14.Is.isFunctionOrUndefined(fn), "scoreEventListener", fn);
7846
8027
  this.renderer.setScoreEventListener(fn);
7847
8028
  }
7848
8029
  hilightObject(obj) {
@@ -7897,7 +8078,7 @@ var _MPlaybackButtons = class _MPlaybackButtons {
7897
8078
  this.updateButtons();
7898
8079
  }
7899
8080
  setDocument(doc) {
7900
- assertArg2(Utils12.Is.isUndefined(doc) || doc instanceof MDocument2, "doc", doc);
8081
+ assertArg2(Utils14.Is.isUndefined(doc) || doc instanceof MDocument2, "doc", doc);
7901
8082
  this.onStop();
7902
8083
  if (doc) {
7903
8084
  this.player = new MPlayer(doc, (playState) => {
@@ -7932,9 +8113,9 @@ var _MPlaybackButtons = class _MPlaybackButtons {
7932
8113
  }
7933
8114
  }
7934
8115
  setPlayButton(btn, btnLabel) {
7935
- assertArg2(Utils12.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
8116
+ assertArg2(Utils14.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
7936
8117
  _MPlaybackButtons.removeOnClickListeners(this.playButton, this.onPlay);
7937
- this.playButton = require_t(Utils12.Dom.getButton(btn), "Play button required!");
8118
+ this.playButton = require_t(Utils14.Dom.getButton(btn), "Play button required!");
7938
8119
  this.playLabel = btnLabel != null ? btnLabel : "Play";
7939
8120
  _MPlaybackButtons.removeOnClickListeners(this.playButton, "all");
7940
8121
  _MPlaybackButtons.addOnClickListener(this.playButton, this.onPlay);
@@ -7942,9 +8123,9 @@ var _MPlaybackButtons = class _MPlaybackButtons {
7942
8123
  return this;
7943
8124
  }
7944
8125
  setStopButton(btn, btnLabel) {
7945
- assertArg2(Utils12.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
8126
+ assertArg2(Utils14.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
7946
8127
  _MPlaybackButtons.removeOnClickListeners(this.stopButton, this.onStop);
7947
- this.stopButton = require_t(Utils12.Dom.getButton(btn), "Stop button required!");
8128
+ this.stopButton = require_t(Utils14.Dom.getButton(btn), "Stop button required!");
7948
8129
  this.stopLabel = btnLabel != null ? btnLabel : "Stop";
7949
8130
  _MPlaybackButtons.removeOnClickListeners(this.stopButton, "all");
7950
8131
  _MPlaybackButtons.addOnClickListener(this.stopButton, this.onStop);
@@ -7952,10 +8133,10 @@ var _MPlaybackButtons = class _MPlaybackButtons {
7952
8133
  return this;
7953
8134
  }
7954
8135
  setPlayStopButton(btn, playLabel, stopLabel) {
7955
- assertArg2(Utils12.Is.isStringOrUndefined(playLabel), "playLabel", playLabel);
7956
- assertArg2(Utils12.Is.isStringOrUndefined(stopLabel), "stopLabel", stopLabel);
8136
+ assertArg2(Utils14.Is.isStringOrUndefined(playLabel), "playLabel", playLabel);
8137
+ assertArg2(Utils14.Is.isStringOrUndefined(stopLabel), "stopLabel", stopLabel);
7957
8138
  _MPlaybackButtons.removeOnClickListeners(this.playStopButton, this.onPlayStop);
7958
- this.playStopButton = require_t(Utils12.Dom.getButton(btn), "Play/stop button required!");
8139
+ this.playStopButton = require_t(Utils14.Dom.getButton(btn), "Play/stop button required!");
7959
8140
  this.playLabel = playLabel != null ? playLabel : "Play";
7960
8141
  this.stopLabel = stopLabel != null ? stopLabel : "Stop";
7961
8142
  _MPlaybackButtons.removeOnClickListeners(this.playStopButton, "all");
@@ -7964,9 +8145,9 @@ var _MPlaybackButtons = class _MPlaybackButtons {
7964
8145
  return this;
7965
8146
  }
7966
8147
  setPauseButton(btn, btnLabel) {
7967
- assertArg2(Utils12.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
8148
+ assertArg2(Utils14.Is.isStringOrUndefined(btnLabel), "btnLabel", btnLabel);
7968
8149
  _MPlaybackButtons.removeOnClickListeners(this.pauseButton, this.onPause);
7969
- this.pauseButton = require_t(Utils12.Dom.getButton(btn), "Pause button required!");
8150
+ this.pauseButton = require_t(Utils14.Dom.getButton(btn), "Pause button required!");
7970
8151
  this.pauseLabel = btnLabel != null ? btnLabel : "Pause";
7971
8152
  _MPlaybackButtons.removeOnClickListeners(this.pauseButton, "all");
7972
8153
  _MPlaybackButtons.addOnClickListener(this.pauseButton, this.onPause);
@@ -7988,7 +8169,7 @@ var _MPlaybackButtons = class _MPlaybackButtons {
7988
8169
  }
7989
8170
  }
7990
8171
  static addOnClickListener(btn, onClick) {
7991
- assertArg2(Utils12.Is.isFunction(onClick), "onClick", onClick);
8172
+ assertArg2(Utils14.Is.isFunction(onClick), "onClick", onClick);
7992
8173
  btn.addEventListener("click", onClick);
7993
8174
  let clickListeners = this.savedOnClickListeners.get(btn) || [];
7994
8175
  this.savedOnClickListeners.set(btn, [...clickListeners, onClick]);