vector-score 1.2.1 → 1.3.1

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.
@@ -1,4 +1,4 @@
1
- const R = {
1
+ const w = {
2
2
  treble: {
3
3
  staffType: "treble",
4
4
  paddingTop: 13,
@@ -31,16 +31,16 @@ const R = {
31
31
  topLineYPos: 0,
32
32
  bottomLineYPos: 110
33
33
  }
34
- }, p = {
34
+ }, I = {
35
35
  w: 4,
36
36
  h: 2,
37
37
  q: 1,
38
38
  e: 0.5,
39
39
  s: 0.25
40
- }, at = 6, ct = 5, _ = 22, T = 30, u = 10, g = 6, ht = 4, lt = u * 2, M = 51, dt = 12, ft = 4, $ = 1, P = 4, k = 1, W = g * 2 + P + 4, rt = 16, S = 12, Z = rt, ut = 2, V = 8, Et = 40, nt = {
40
+ }, it = 6, at = 5, T = 22, m = 30, u = 10, A = 6, ct = 4, ht = u * 2, L = 51, lt = 12, dt = 4, $ = 1, x = 4, ft = 1, W = A * 2 + x + 8, st = 16, R = 12, k = st, Et = 2, Z = 8, ut = 40, rt = {
41
41
  sharp: ["F", "C", "G", "D", "A", "E", "B"],
42
42
  flat: ["B", "E", "A", "D", "G", "C", "F"]
43
- }, q = {
43
+ }, V = {
44
44
  C: { type: "sharp", count: 0 },
45
45
  G: { type: "sharp", count: 1 },
46
46
  D: { type: "sharp", count: 2 },
@@ -54,7 +54,7 @@ const R = {
54
54
  Ab: { type: "flat", count: 4 },
55
55
  Db: { type: "flat", count: 5 },
56
56
  Gb: { type: "flat", count: 6 }
57
- }, x = {
57
+ }, X = {
58
58
  treble: {
59
59
  sharp: [5, 5, 5, 5, 4, 5, 4],
60
60
  // F5 C5 G5 D5 A4 E5 B4
@@ -75,22 +75,23 @@ const R = {
75
75
  },
76
76
  grand: { sharp: [], flat: [] }
77
77
  };
78
- function gt(h) {
79
- const e = q[h];
80
- if (!e) throw new Error(`Unknown key signature "${h}". Valid keys: ${Object.keys(q).join(", ")}`);
78
+ function gt(l) {
79
+ const e = V[l];
80
+ if (!e) throw new Error(`Unknown key signature "${l}". Valid keys: ${Object.keys(V).join(", ")}`);
81
81
  return e;
82
82
  }
83
- function At(h, e, t, s) {
83
+ function pt(l, e, t, s) {
84
84
  const r = gt(t);
85
85
  if (r.count === 0) return 0;
86
- const n = r.type === "sharp" ? "ACCIDENTAL_SHARP" : "ACCIDENTAL_FLAT", o = h.getLayerByName("staff");
86
+ const n = r.type === "sharp" ? "ACCIDENTAL_SHARP" : "ACCIDENTAL_FLAT", o = l.getLayer("staff");
87
+ if (!o) throw new Error("Staff Init Error: Failed to retrieve staff layer for key signature renderering.");
87
88
  return e.getKeySignatureYPositions(r.type, r.count).forEach((a) => {
88
- a.forEach((c, l) => {
89
- h.drawGlyph(n, o, { xOffset: s + l * V, yOffset: c });
89
+ a.forEach((h, d) => {
90
+ l.drawGlyph(n, o, { xOffset: s + d * Z, yOffset: h });
90
91
  });
91
- }), r.count * V;
92
+ }), r.count * Z;
92
93
  }
93
- const pt = {
94
+ const At = {
94
95
  CLEF_TREBLE: {
95
96
  path: "m150 273 10 58c2 7 2 7 12 7 59 0 96 46 96 97 0 45-26 79-67 95-5 2-6 2-5 7 4 25 12 63 12 85 0 68-52 80-79 80-61 0-76-39-76-65 0-25 16-46 43-46 24 0 38 19 38 41 0 23-14 34-27 38-9 2-13 4-13 6 0 6 11 12 32 12 24 0 64-7 64-66 0-19-6-54-11-81-1-5-1-4-6-3l-27 2C48 540 0 474 0 404c0-80 61-138 119-185 5-4 4-5 3-10-2-16-5-42-5-65 0-42 9-92 39-125 8-9 20-19 26-19 4 0 15 11 21 20 16 24 26 58 26 93 0 61-33 112-76 153-3 2-3 2-3 7Zm38-211c-24 0-53 38-53 101l2 37c1 5 3 5 5 3 32-28 70-64 70-108 0-22-11-33-24-33Zm-44 272-8-51c-1-4-2-5-6-1-18 15-37 30-61 56-33 38-37 70-37 93 0 56 45 95 115 95l23-2c6-2 6-2 5-6l-20-119c-1-5-1-5-8-3-24 6-40 24-40 46 0 19 12 36 29 43 3 1 6 3 6 5 0 3-2 5-5 5l-11-3c-27-9-46-34-46-70 0-34 23-66 58-78 8-2 8-2 6-10Zm28 64 20 114c0 5 1 5 6 2 22-11 38-31 38-56 0-36-27-63-60-66-4 0-5 1-4 6Z",
96
97
  xOffset: 0,
@@ -186,11 +187,11 @@ const pt = {
186
187
  xOffset: 0,
187
188
  yOffset: 0
188
189
  }
189
- }, It = /^(?<name>[A-Ga-g])(?<accidental>##|bb|[#bn]?)(?<octave>\d)(?<duration>[whqeWHQE]?)$/, _t = /^[whqeWHQE]$/, X = ["C", "D", "E", "F", "G", "A", "B"];
190
- function U(h) {
191
- const e = h.match(It);
190
+ }, It = /^(?<name>[A-Ga-g])(?<accidental>##|bb|[#bn]?)(?<octave>\d)(?<duration>[whqeWHQE]?)$/, _t = /^[whqeWHQE]$/, U = ["C", "D", "E", "F", "G", "A", "B"];
191
+ function Y(l) {
192
+ const e = l.match(It);
192
193
  if (!e || !e.groups)
193
- throw new Error(`Invalid note string format: ${h}. Expected format: [A-Ga-g][#|b]?[0-9][w|h|q|e].`);
194
+ throw new Error(`Invalid note string format: ${l}. Expected format: [A-Ga-g][#|b]?[0-9][w|h|q|e].`);
194
195
  let { name: t, accidental: s, octave: r, duration: n } = e.groups;
195
196
  t = t.toUpperCase(), n = n.toLowerCase(), n || (n = "w");
196
197
  const o = {
@@ -200,14 +201,14 @@ function U(h) {
200
201
  };
201
202
  return s && (o.accidental = s), o;
202
203
  }
203
- function b(h) {
204
- const e = h.match(_t);
205
- if (!e) throw new Error(`Invalid note duration '${h}'. Use w | h | q | e.`);
204
+ function v(l) {
205
+ const e = l.match(_t);
206
+ if (!e) throw new Error(`Invalid note duration '${l}'. Use w | h | q | e.`);
206
207
  return e[0].toString().toLowerCase();
207
208
  }
208
- function Y(h) {
209
+ function M(l) {
209
210
  let e;
210
- switch (h) {
211
+ switch (l) {
211
212
  case "treble":
212
213
  e = "CLEF_TREBLE";
213
214
  break;
@@ -218,25 +219,25 @@ function Y(h) {
218
219
  e = "CLEF_ALTO";
219
220
  break;
220
221
  }
221
- if (!e) throw new Error(`Invalid clef type: ${h}. Valid clef types are: treble, bass, alto.`);
222
+ if (!e) throw new Error(`Invalid clef type: ${l}. Valid clef types are: treble, bass, alto.`);
222
223
  return e;
223
224
  }
224
- function z(h) {
225
- let e = X.indexOf(h.name);
226
- return e += h.octave * 12, e;
225
+ function z(l) {
226
+ let e = U.indexOf(l.name);
227
+ return e += l.octave * 12, e;
227
228
  }
228
- function N(h, e) {
229
- return X.indexOf(h.name) - X.indexOf(e.name) + (h.octave - e.octave) * 7;
229
+ function C(l, e) {
230
+ return U.indexOf(l.name) - U.indexOf(e.name) + (l.octave - e.octave) * 7;
230
231
  }
231
- const G = 48, j = 40 + 30 / 2, K = 20, Q = 90;
232
- class ot {
232
+ const G = 48, q = 40 + 30 / 2, j = 20, K = 90;
233
+ class nt {
233
234
  params;
234
235
  rendererRef;
235
236
  width = 0;
236
237
  trebleStaffHeight = 0;
237
238
  constructor(e, t) {
238
239
  this.rendererRef = e;
239
- const s = R[t];
240
+ const s = w[t];
240
241
  if (!s) throw new Error(`Staff type ${t} is not supported`);
241
242
  this.params = s;
242
243
  }
@@ -248,16 +249,16 @@ class ot {
248
249
  };
249
250
  drawStaff = (e) => {
250
251
  this.width = e;
251
- const t = this.rendererRef.getLayerByName("staff");
252
+ const t = this.rendererRef.createLayer("staff");
252
253
  let s = this.drawStaffLines(0, t), r = this.drawStaffLines(s + 30, t);
253
254
  this.rendererRef.drawLine(0, 0, 0, r, t), this.rendererRef.drawLine(this.width, 0, this.width, r, t), this.trebleStaffHeight = s;
254
255
  let n = r, o = 1;
255
- const i = Y("treble"), a = Y("bass");
256
+ const i = M("treble"), a = M("bass");
256
257
  this.rendererRef.drawGlyph(i, t), this.rendererRef.drawGlyph(a, t, { yOffset: s + 30 }), n += this.params.paddingBottom + 1, o += this.params.paddingTop, this.rendererRef.addTotalRootSvgHeight(n), this.rendererRef.addTotalRootSvgYOffset(o);
257
258
  };
258
259
  shouldNoteFlip(e) {
259
- const t = Math.abs(e - Q), s = Math.abs(e - K);
260
- return e === j ? !1 : t <= s ? !(e >= Q) : e <= K;
260
+ const t = Math.abs(e - K), s = Math.abs(e - j);
261
+ return e === q ? !1 : t <= s ? !(e >= K) : e <= j;
261
262
  }
262
263
  getLedgerLinesX(e, t) {
263
264
  const s = [], r = z(e);
@@ -284,37 +285,37 @@ class ot {
284
285
  return s;
285
286
  }
286
287
  calculateNoteYPos = (e) => {
287
- let s = N(this.params.topLineNote, e) * (10 / 2);
288
+ let s = C(this.params.topLineNote, e) * (10 / 2);
288
289
  const r = z(e);
289
- return r < G ? s += 10 : r === G && (s = j), s;
290
+ return r < G ? s += 10 : r === G && (s = q), s;
290
291
  };
291
292
  getKeySignatureYPositions(e, t) {
292
- const s = nt[e].slice(0, t), r = x.treble[e], n = x.bass[e], o = s.map(
293
- (a, c) => N(R.treble.topLineNote, { name: a, octave: r[c] }) * (10 / 2)
293
+ const s = rt[e].slice(0, t), r = X.treble[e], n = X.bass[e], o = s.map(
294
+ (a, h) => C(w.treble.topLineNote, { name: a, octave: r[h] }) * (10 / 2)
294
295
  ), i = s.map(
295
- (a, c) => N(R.bass.topLineNote, { name: a, octave: n[c] }) * (10 / 2) + this.trebleStaffHeight + 30
296
+ (a, h) => C(w.bass.topLineNote, { name: a, octave: n[h] }) * (10 / 2) + this.trebleStaffHeight + 30
296
297
  );
297
298
  return [o, i];
298
299
  }
299
300
  }
300
301
  const Tt = 20;
301
- class m {
302
+ class S {
302
303
  params;
303
304
  rendererRef;
304
305
  constructor(e, t) {
305
306
  this.rendererRef = e;
306
- const s = R[t];
307
+ const s = w[t];
307
308
  if (!s) throw new Error(`Staff type ${t} is not supported`);
308
309
  this.params = s;
309
310
  }
310
311
  drawStaff = (e) => {
311
- const t = this.rendererRef.getLayerByName("staff");
312
+ const t = this.rendererRef.createLayer("staff");
312
313
  let s = 0;
313
314
  for (let i = 0; i < 5; i++)
314
315
  this.rendererRef.drawLine(0, s, e, s, t), s += 10;
315
316
  this.rendererRef.drawLine(0, 0, 0, s - 10, t), this.rendererRef.drawLine(e, 0, e, s - 10, t);
316
317
  let r = s - 10 + 1, n = 1;
317
- const o = Y(this.params.staffType);
318
+ const o = M(this.params.staffType);
318
319
  this.rendererRef.drawGlyph(o, t), r += this.params.paddingTop + this.params.paddingBottom, n += this.params.paddingTop, this.rendererRef.addTotalRootSvgHeight(r), this.rendererRef.addTotalRootSvgYOffset(n);
319
320
  };
320
321
  shouldNoteFlip(e) {
@@ -342,15 +343,15 @@ class m {
342
343
  }
343
344
  return s;
344
345
  }
345
- calculateNoteYPos = (e) => N(this.params.topLineNote, e) * (10 / 2);
346
+ calculateNoteYPos = (e) => C(this.params.topLineNote, e) * (10 / 2);
346
347
  getKeySignatureYPositions(e, t) {
347
- const s = nt[e].slice(0, t), r = x[this.params.staffType][e];
348
+ const s = rt[e].slice(0, t), r = X[this.params.staffType][e];
348
349
  return [s.map(
349
350
  (o, i) => this.calculateNoteYPos({ name: o, octave: r[i] })
350
351
  )];
351
352
  }
352
353
  }
353
- class it {
354
+ class ot {
354
355
  svgRendererInstance;
355
356
  strategyInstance;
356
357
  constructor(e, t) {
@@ -364,7 +365,7 @@ class it {
364
365
  for (let n = 0; n < e.length; n++) {
365
366
  const o = e[n];
366
367
  if (o.noteObj.accidental && r < 3 ? (t += -8, s = Math.min(s, t), r++) : o.noteObj.accidental && r <= 3 ? (t = -8, r = 1) : (t = 0, r = 0), t !== 0) {
367
- const a = Array.from(o.noteGroup.getElementsByTagName("use")).find((c) => c.getAttribute("href")?.includes("ACCIDENTAL"));
368
+ const a = Array.from(o.noteGroup.getElementsByTagName("use")).find((h) => h.getAttribute("href")?.includes("ACCIDENTAL"));
368
369
  if (!a) continue;
369
370
  a.setAttribute("transform", `translate(${t + 8}, 0)`);
370
371
  }
@@ -375,13 +376,13 @@ class it {
375
376
  let t = e[0], s = 0;
376
377
  for (let r = 1; r < e.length; r++) {
377
378
  const n = e[r];
378
- if (-N(t.noteObj, n.noteObj) === 1) {
379
+ if (-C(t.noteObj, n.noteObj) === 1) {
379
380
  s = 28 / 2, n.noteGroup.setAttribute("transform", `translate(${s}, ${n.noteYPos})`);
380
- const a = Array.from(n.noteGroup.getElementsByTagName("use")).find((c) => c.getAttribute("href")?.includes("ACCIDENTAL"));
381
+ const a = Array.from(n.noteGroup.getElementsByTagName("use")).find((h) => h.getAttribute("href")?.includes("ACCIDENTAL"));
381
382
  if (a) {
382
- const c = a.getAttribute("transform")?.match(/([-]?\d+)/), l = c && c[0];
383
- let d = -s;
384
- l && (d += Number(l)), a.setAttribute("transform", `translate(${d}, 0)`);
383
+ const h = a.getAttribute("transform")?.match(/([-]?\d+)/), d = h && h[0];
384
+ let c = -s;
385
+ d && (c += Number(d)), a.setAttribute("transform", `translate(${c}, 0)`);
385
386
  }
386
387
  r++, t = e[r];
387
388
  continue;
@@ -392,7 +393,7 @@ class it {
392
393
  }
393
394
  // Handles drawing the glyphs to internal group, applies the xPositioning to note Cursor X
394
395
  renderNote(e) {
395
- const t = this.svgRendererInstance.createGroup("note"), s = U(e), r = this.strategyInstance.calculateNoteYPos({
396
+ const t = this.svgRendererInstance.createGroup("note"), s = Y(e), r = this.strategyInstance.calculateNoteYPos({
396
397
  name: s.name,
397
398
  octave: s.octave
398
399
  });
@@ -460,15 +461,13 @@ class it {
460
461
  };
461
462
  }
462
463
  }
463
- const A = "http://www.w3.org/2000/svg", mt = 0.1, v = 1200;
464
- class w {
464
+ const p = "http://www.w3.org/2000/svg", St = 0.1, F = 2;
465
+ class O {
465
466
  rootElementRef;
466
467
  svgElementRef;
467
468
  // Layers
468
469
  parentGroupContainer;
469
- musicStaffLayer;
470
- musicNotesLayer;
471
- musicUILayer;
470
+ layers = {};
472
471
  // Positioning variables
473
472
  width;
474
473
  scale;
@@ -479,21 +478,36 @@ class w {
479
478
  // from get rootSvgElement().
480
479
  // HEIGHT and YOfsset should be set externally, values are calculated internally.
481
480
  constructor(e, t) {
482
- this.rootElementRef = e, this.width = t.width, this.scale = t.scale, this.width > v && (this.width = v, console.warn(`Width provided for the staff ${this.width} exceeds the limit ${v}. Please use this value to fix positioning issues.`)), this.svgElementRef = document.createElementNS(A, "svg"), this.svgElementRef.classList.add("vs-svg-renderer-root"), this.svgElementRef.style.maxWidth = "100%", this.svgElementRef.style.height = "auto", this.svgElementRef.style.display = "block", this.svgElementRef.setAttribute("color", t.staffColor), this.svgElementRef.style.backgroundColor = t.staffBackgroundColor, this.makeGlyphDefs(t.useGlyphs), this.parentGroupContainer = this.createGroup("svg-renderer-parent"), this.svgElementRef.appendChild(this.parentGroupContainer), this.musicStaffLayer = this.createGroup("music-staff-layer"), this.musicNotesLayer = this.createGroup("music-notes-layer"), this.musicUILayer = this.createGroup("music-ui-layer"), this.parentGroupContainer.appendChild(this.musicStaffLayer), this.parentGroupContainer.appendChild(this.musicNotesLayer), this.parentGroupContainer.appendChild(this.musicUILayer);
481
+ this.rootElementRef = e, this.width = t.width, this.scale = t.scale, this.svgElementRef = document.createElementNS(p, "svg"), this.svgElementRef.classList.add("vs-svg-renderer-root"), t.svgAutoFill && (this.svgElementRef.style.maxWidth = "100%", this.svgElementRef.style.height = "auto"), this.makeGlyphDefs(t.useGlyphs), this.parentGroupContainer = this.createGroup("svg-renderer-parent"), this.svgElementRef.appendChild(this.parentGroupContainer);
483
482
  }
484
483
  // Creates SVG defs for all glyphs in GLYPH_ENTRIES, applies global scale and offsets, appends to root SVG
485
484
  makeGlyphDefs(e) {
486
- const t = document.createElementNS(A, "defs");
487
- Object.entries(pt).filter(([r]) => e.includes(r)).forEach(([r, n]) => {
488
- const o = document.createElementNS(A, "path");
489
- o.setAttribute("id", `glyph-${r}`), o.setAttribute("d", n.path), o.setAttribute("fill", "currentColor"), o.setAttribute("transform", `translate(${n.xOffset}, ${n.yOffset}) scale(${mt})`), t.appendChild(o);
485
+ const t = document.createElementNS(p, "defs");
486
+ Object.entries(At).filter(([r]) => e.includes(r)).forEach(([r, n]) => {
487
+ const o = document.createElementNS(p, "path");
488
+ o.setAttribute("id", `glyph-${r}`), o.setAttribute("d", n.path), o.setAttribute("fill", "currentColor"), o.setAttribute("transform", `translate(${n.xOffset}, ${n.yOffset}) scale(${St})`), t.appendChild(o);
490
489
  }), this.rootSvgElement.appendChild(t);
491
490
  }
492
491
  addNamespacedClassesToElement(e, t) {
493
492
  [e].flat().forEach((r) => t.classList.add(`vs-${r}`));
494
493
  }
494
+ /**
495
+ * Creates a layer that is appended to parent element.
496
+ * layerName arg is the key that is appended to the internal list of layers, which
497
+ * can be used in method getLayer() arg. Best to call on construction.
498
+ *
499
+ * @param {string} layerName
500
+ * @returns {SVGGElement}
501
+ */
502
+ createLayer(e) {
503
+ const t = document.createElementNS(p, "g");
504
+ return t.classList.add(`vs-${e}-layer`), this.layers[e] = t, this.parentGroupContainer.appendChild(this.layers[e]), t;
505
+ }
506
+ getLayer(e) {
507
+ return this.layers[e] ?? null;
508
+ }
495
509
  createGroup(e) {
496
- const t = document.createElementNS(A, "g");
510
+ const t = document.createElementNS(p, "g");
497
511
  return e && t.classList.add(`vs-${e}`), t;
498
512
  }
499
513
  commitElementsToDOM(e, t = this.rootElementRef) {
@@ -502,18 +516,6 @@ class w {
502
516
  s.appendChild(r);
503
517
  }) : s.appendChild(e), t.appendChild(s);
504
518
  }
505
- getLayerByName(e) {
506
- switch (e) {
507
- case "staff":
508
- return this.musicStaffLayer;
509
- case "notes":
510
- return this.musicNotesLayer;
511
- case "ui":
512
- return this.musicUILayer;
513
- default:
514
- throw new Error(`Layer with name '${e}' does not exist.`);
515
- }
516
- }
517
519
  addTotalRootSvgHeight(e) {
518
520
  this.totalHeight += e;
519
521
  }
@@ -524,10 +526,10 @@ class w {
524
526
  this.totalYOffset += e;
525
527
  }
526
528
  applySizingToRootSvg() {
527
- this.parentGroupContainer.setAttribute("transform", `translate(0, ${this.totalYOffset})`);
528
- let e = this.width * this.scale;
529
+ this.parentGroupContainer.setAttribute("transform", `translate(${F / 2}, ${this.totalYOffset})`);
530
+ let e = Math.round(this.width * this.scale);
529
531
  const t = (this.totalHeight + this.totalYOffset) * this.scale;
530
- e += 2, this.svgElementRef.setAttribute("width", e.toString()), this.svgElementRef.setAttribute("height", t.toString()), this.svgElementRef.setAttribute("viewBox", `0 0 ${this.width} ${this.totalHeight + this.totalYOffset}`);
532
+ e += F, this.svgElementRef.setAttribute("width", e.toString()), this.svgElementRef.setAttribute("height", t.toString()), this.svgElementRef.setAttribute("viewBox", `0 0 ${this.width + F} ${this.totalHeight + this.totalYOffset}`);
531
533
  }
532
534
  get rootSvgElement() {
533
535
  return this.svgElementRef;
@@ -536,12 +538,12 @@ class w {
536
538
  return this.parentGroupContainer;
537
539
  }
538
540
  // Drawing Methods
539
- drawLine(e, t, s, r, n) {
540
- const o = document.createElementNS(A, "line");
541
- o.setAttribute("x1", e.toString()), o.setAttribute("y1", t.toString()), o.setAttribute("x2", s.toString()), o.setAttribute("y2", r.toString()), o.setAttribute("stroke", "currentColor"), o.setAttribute("stroke-width", "1"), n.appendChild(o);
541
+ drawLine(e, t, s, r, n, o) {
542
+ const i = o?.strokeWidth ?? 1, a = document.createElementNS(p, "line");
543
+ a.setAttribute("x1", e.toString()), a.setAttribute("y1", t.toString()), a.setAttribute("x2", s.toString()), a.setAttribute("y2", r.toString()), a.setAttribute("stroke", "currentColor"), a.setAttribute("stroke-width", i.toString()), o?.classes && this.addNamespacedClassesToElement(o.classes, n), n.appendChild(a);
542
544
  }
543
545
  drawRect(e, t, s, r) {
544
- const n = document.createElementNS(A, "rect");
546
+ const n = document.createElementNS(p, "rect");
545
547
  return n.setAttribute("width", e.toString()), n.setAttribute("height", t.toString()), n.setAttribute("x", (r?.x ?? 0).toString()), n.setAttribute("y", (r?.y ?? 0).toString()), r?.fill ? n.setAttribute("fill", r.fill) : n.setAttribute("fill", "currentColor"), r?.rx && n.setAttribute("rx", r.rx.toString()), r?.classes && this.addNamespacedClassesToElement(r.classes, n), s.appendChild(n), n;
546
548
  }
547
549
  drawGlyph(e, t, s) {
@@ -550,22 +552,22 @@ class w {
550
552
  yOffset: 0,
551
553
  ...s
552
554
  };
553
- const r = document.createElementNS(A, "use");
555
+ const r = document.createElementNS(p, "use");
554
556
  r.setAttribute("href", `#glyph-${e}`), (s.xOffset || s.yOffset) && r.setAttribute("transform", `translate(${s.xOffset}, ${s.yOffset})`), t.appendChild(r);
555
557
  }
556
558
  drawCircle(e, t, s, r, n) {
557
- const o = document.createElementNS(A, "circle");
559
+ const o = document.createElementNS(p, "circle");
558
560
  return o.setAttribute("cx", e.toString()), o.setAttribute("cy", t.toString()), o.setAttribute("r", s.toString()), n?.filled === !1 ? (o.setAttribute("fill", "none"), o.setAttribute("stroke", "currentColor"), o.setAttribute("stroke-width", (n?.strokeWidth ?? 1.5).toString())) : o.setAttribute("fill", n?.fill ?? "currentColor"), n?.classes && this.addNamespacedClassesToElement(n.classes, o), r.appendChild(o), o;
559
561
  }
560
562
  drawText(e, t, s, r, n) {
561
- const o = document.createElementNS(A, "text");
562
- return o.setAttribute("x", t.toString()), o.setAttribute("y", s.toString()), o.setAttribute("text-anchor", n?.anchor ?? "middle"), o.setAttribute("fill", n?.fill ?? "currentColor"), n?.fontSize && o.setAttribute("font-size", n.fontSize + "px"), n?.fontWeight && o.setAttribute("font-weight", n.fontWeight), n?.classes && this.addNamespacedClassesToElement(n.classes, o), o.textContent = e, r.appendChild(o), o;
563
+ const o = document.createElementNS(p, "text");
564
+ return o.setAttribute("x", t.toString()), o.setAttribute("y", s.toString()), o.setAttribute("text-anchor", n?.anchor ?? "middle"), o.setAttribute("fill", n?.fill ?? "currentColor"), n?.fontSize && o.setAttribute("font-size", n.fontSize + "px"), n?.fontWeight && o.setAttribute("font-weight", n.fontWeight), n?.baseline && o.setAttribute("dominant-baseline", n.baseline), n?.classes && this.addNamespacedClassesToElement(n.classes, o), o.textContent = e, r.appendChild(o), o;
563
565
  }
564
566
  destroy() {
565
567
  this.rootElementRef && this.svgElementRef && this.rootElementRef.contains(this.svgElementRef) && this.rootElementRef.removeChild(this.svgElementRef);
566
568
  }
567
569
  }
568
- const Ct = [
570
+ const mt = [
569
571
  "CLEF_TREBLE",
570
572
  "CLEF_BASS",
571
573
  "CLEF_ALTO",
@@ -602,47 +604,47 @@ class bt {
602
604
  staffType: "treble",
603
605
  spaceAbove: 0,
604
606
  spaceBelow: 0,
605
- staffColor: "black",
606
- staffBackgroundColor: "transparent",
607
+ svgAutoFill: !0,
607
608
  ...t
608
- }, this.svgRendererInstance = new w(e, {
609
+ }, this.svgRendererInstance = new O(e, {
609
610
  width: this.options.width,
610
611
  height: 100,
611
612
  scale: this.options.scale,
612
- staffColor: this.options.staffColor,
613
- staffBackgroundColor: this.options.staffBackgroundColor,
614
- useGlyphs: Ct
613
+ useGlyphs: mt,
614
+ svgAutoFill: this.options.svgAutoFill
615
615
  });
616
616
  const s = this.svgRendererInstance.rootSvgElement;
617
617
  switch (this.options.staffType) {
618
618
  case "grand":
619
- this.strategyInstance = new ot(this.svgRendererInstance, "grand");
619
+ this.strategyInstance = new nt(this.svgRendererInstance, "grand");
620
620
  break;
621
621
  case "bass":
622
- this.strategyInstance = new m(this.svgRendererInstance, "bass");
622
+ this.strategyInstance = new S(this.svgRendererInstance, "bass");
623
623
  break;
624
624
  case "treble":
625
- this.strategyInstance = new m(this.svgRendererInstance, "treble");
625
+ this.strategyInstance = new S(this.svgRendererInstance, "treble");
626
626
  break;
627
627
  case "alto":
628
- this.strategyInstance = new m(this.svgRendererInstance, "alto");
628
+ this.strategyInstance = new S(this.svgRendererInstance, "alto");
629
629
  break;
630
630
  default:
631
631
  throw new Error(`The staff type ${this.options.staffType} is not supported. Please use "treble", "bass", "alto", or "grand".`);
632
632
  }
633
- if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new it(this.svgRendererInstance, this.strategyInstance), this.options.spaceAbove) {
634
- const n = this.options.spaceAbove * 10;
635
- this.svgRendererInstance.addTotalRootSvgYOffset(n);
633
+ this.strategyInstance.drawStaff(this.options.width);
634
+ const r = this.svgRendererInstance.createLayer("notes");
635
+ if (this.noteRendererInstance = new ot(this.svgRendererInstance, this.strategyInstance), this.options.spaceAbove) {
636
+ const o = this.options.spaceAbove * 10;
637
+ this.svgRendererInstance.addTotalRootSvgYOffset(o);
636
638
  }
637
639
  if (this.options.spaceBelow) {
638
- let n = this.options.spaceBelow * 10;
639
- this.options.staffType === "grand" && (n -= 10 / 2), this.svgRendererInstance.addTotalRootSvgHeight(n);
640
+ let o = this.options.spaceBelow * 10;
641
+ this.options.staffType === "grand" && (o -= 10 / 2), this.svgRendererInstance.addTotalRootSvgHeight(o);
640
642
  }
641
- let r = 0;
642
- this.options.keySignature && (r = this.createKeySignature(this.options.keySignature)), this.noteStartX = 38 + this.options.noteStartX + r, this.svgRendererInstance.getLayerByName("notes").setAttribute("transform", `translate(${this.noteStartX}, 0)`), this.svgRendererInstance.applySizingToRootSvg(), this.svgRendererInstance.commitElementsToDOM(s);
643
+ let n = 0;
644
+ this.options.keySignature && (n = this.createKeySignature(this.options.keySignature)), this.noteStartX = 38 + this.options.noteStartX + n, r.setAttribute("transform", `translate(${this.noteStartX}, 0)`), this.svgRendererInstance.applySizingToRootSvg(), this.svgRendererInstance.commitElementsToDOM(s);
643
645
  }
644
646
  createKeySignature(e) {
645
- return At(this.svgRendererInstance, this.strategyInstance, e, Et);
647
+ return pt(this.svgRendererInstance, this.strategyInstance, e, ut);
646
648
  }
647
649
  /**
648
650
  * Draws a note on the staff.
@@ -665,7 +667,9 @@ class bt {
665
667
  * drawNote("D4w");
666
668
  */
667
669
  drawNote(e) {
668
- const t = Array.isArray(e) ? e : [e], s = this.svgRendererInstance.getLayerByName("notes"), r = [];
670
+ const t = Array.isArray(e) ? e : [e], s = this.svgRendererInstance.getLayer("notes");
671
+ if (!s) throw new Error("DrawNote Error: Failed to retrieve notesLayer to append notes.");
672
+ const r = [];
669
673
  for (const n of t) {
670
674
  let o;
671
675
  try {
@@ -700,10 +704,12 @@ class bt {
700
704
  */
701
705
  drawChord(e) {
702
706
  if (e.length < 2) throw new Error("Provide more than one note for a chord.");
703
- const t = this.svgRendererInstance.getLayerByName("notes"), s = this.noteRendererInstance.renderChord(e);
707
+ const t = this.svgRendererInstance.getLayer("notes");
708
+ if (!t) throw new Error("DrawChord Error: Failed to retrieve notesLayer to append chord.");
709
+ const s = this.noteRendererInstance.renderChord(e);
704
710
  s.noteGroup.setAttribute("transform", `translate(${this.noteCursorX + s.accidentalOffset}, 0)`), this.noteEntries.push({
705
711
  gElement: s.noteGroup,
706
- note: U(e[0]),
712
+ note: Y(e[0]),
707
713
  xPos: this.noteCursorX + s.accidentalOffset,
708
714
  yPos: 0,
709
715
  accidentalXOffset: s.accidentalOffset
@@ -718,10 +724,10 @@ class bt {
718
724
  if (t <= 0 || e <= 0) return;
719
725
  const s = Math.round(e / t);
720
726
  this.noteEntries.map((n, o) => {
721
- const i = (o + 0.5) * s, a = n.gElement.getBBox(), c = i - a.width / 2 - a.x, l = Math.round(c * 10) / 10;
727
+ const i = (o + 0.5) * s, a = n.gElement.getBBox(), h = i - a.width / 2 - a.x, d = Math.round(h * 10) / 10;
722
728
  return {
723
729
  entry: n,
724
- newX: l,
730
+ newX: d,
725
731
  isChord: n.gElement.classList.contains("chord")
726
732
  };
727
733
  }).forEach((n) => {
@@ -734,7 +740,7 @@ class bt {
734
740
  * @returns void
735
741
  */
736
742
  clearAllNotes() {
737
- this.noteCursorX = 0, this.svgRendererInstance.getLayerByName("notes").replaceChildren(), this.noteEntries = [];
743
+ this.noteCursorX = 0, this.svgRendererInstance.getLayer("notes")?.replaceChildren(), this.noteEntries = [];
738
744
  }
739
745
  /**
740
746
  * Changes the note by index to the specified note.
@@ -755,7 +761,10 @@ class bt {
755
761
  changeNoteByIndex(e, t) {
756
762
  if (t >= this.noteEntries.length) throw new Error("Note index was out of bounds.");
757
763
  const s = this.noteEntries[t], r = this.noteRendererInstance.renderNote(e), o = s.xPos - s.accidentalXOffset + r.accidentalOffset;
758
- r.noteGroup.setAttribute("transform", `translate(${o}, ${r.noteYPos})`), this.svgRendererInstance.getLayerByName("notes").replaceChild(r.noteGroup, s.gElement), this.noteEntries[t] = {
764
+ r.noteGroup.setAttribute("transform", `translate(${o}, ${r.noteYPos})`);
765
+ const i = this.svgRendererInstance.getLayer("notes");
766
+ if (!i) throw new Error("ChangeNoteByIndex Error: Failed to retrieve notesLayer to append notes.");
767
+ i.replaceChild(r.noteGroup, s.gElement), this.noteEntries[t] = {
759
768
  gElement: r.noteGroup,
760
769
  note: r.noteObj,
761
770
  xPos: o,
@@ -783,9 +792,12 @@ class bt {
783
792
  if (t >= this.noteEntries.length) throw new Error("Chord index was out of bounds.");
784
793
  if (e.length < 2) throw new Error("Notes provided need to be more than one to be considered a chord.");
785
794
  const s = this.noteEntries[t], r = this.noteRendererInstance.renderChord(e), o = s.xPos - s.accidentalXOffset + r.accidentalOffset;
786
- r.noteGroup.setAttribute("transform", `translate(${o}, 0)`), this.svgRendererInstance.getLayerByName("notes").replaceChild(r.noteGroup, s.gElement), this.noteEntries[t] = {
795
+ r.noteGroup.setAttribute("transform", `translate(${o}, 0)`);
796
+ const i = this.svgRendererInstance.getLayer("notes");
797
+ if (!i) throw new Error("DrawNote Error: Failed to retrieve notesLayer to append notes.");
798
+ i.replaceChild(r.noteGroup, s.gElement), this.noteEntries[t] = {
787
799
  gElement: r.noteGroup,
788
- note: U(e[0]),
800
+ note: Y(e[0]),
789
801
  xPos: o,
790
802
  yPos: 0,
791
803
  accidentalXOffset: r.accidentalOffset
@@ -821,7 +833,7 @@ class bt {
821
833
  this.noteEntries = [], this.svgRendererInstance.destroy();
822
834
  }
823
835
  }
824
- const I = 30, J = 19, F = 12, St = 4, Nt = 6, tt = 1, D = 38, Lt = [
836
+ const _ = 30, Q = 19, D = 12, Ct = 4, Nt = 6, J = 1, H = 38, Lt = [
825
837
  "TIME_4",
826
838
  "TIME_3",
827
839
  "NOTE_HEAD_WHOLE",
@@ -833,7 +845,7 @@ const I = 30, J = 19, F = 12, St = 4, Nt = 6, tt = 1, D = 38, Lt = [
833
845
  "REST_QUARTER",
834
846
  "REST_EIGHTH"
835
847
  ];
836
- class Gt {
848
+ class vt {
837
849
  rendererInstance;
838
850
  options;
839
851
  barSpacing;
@@ -844,7 +856,7 @@ class Gt {
844
856
  currentBeatCount = 0;
845
857
  currentBeatUICount = 0;
846
858
  currentBeatUIElement = null;
847
- currentBeatUIXPos = D;
859
+ currentBeatUIXPos = H;
848
860
  /**
849
861
  * Creates an instance of a RhythmStaff, A single staff that will automatically apply positioning of elements based on the duration of a note.
850
862
  *
@@ -860,67 +872,66 @@ class Gt {
860
872
  barsCount: 2,
861
873
  spaceAbove: 0,
862
874
  spaceBelow: 0,
863
- staffColor: "black",
864
- staffBackgroundColor: "white",
865
- currentBeatUIColor: "#24ff7450",
875
+ svgAutoFill: !0,
866
876
  ...t
867
- }, this.rendererInstance = new w(e, {
877
+ }, this.rendererInstance = new O(e, {
868
878
  width: this.options.width,
869
879
  height: 100,
870
880
  scale: this.options.scale,
871
- staffColor: this.options.staffColor,
872
- staffBackgroundColor: this.options.staffBackgroundColor,
873
- useGlyphs: Lt
881
+ useGlyphs: Lt,
882
+ svgAutoFill: this.options.svgAutoFill
874
883
  });
875
- const s = this.rendererInstance.rootSvgElement;
876
- let r = "TIME_4";
884
+ const s = this.rendererInstance.rootSvgElement, r = this.rendererInstance.createLayer("staff"), n = this.rendererInstance.createLayer("notes");
885
+ this.rendererInstance.createLayer("ui");
886
+ let o = "TIME_4";
877
887
  switch (this.options.topNumber) {
878
888
  case 3:
879
- r = "TIME_3";
889
+ o = "TIME_3";
880
890
  break;
881
891
  case 4:
882
- r = "TIME_4";
892
+ o = "TIME_4";
883
893
  break;
884
894
  default:
885
895
  throw new Error(`Time signature ${this.options.topNumber} not supported. Please use either 3 or 4.`);
886
896
  }
887
897
  if (this.options.barsCount < 1 || this.options.barsCount > 3) throw new Error(`Bars count ${this.options.barsCount} not supported. Please use 1 - 3`);
888
898
  if (this.options.spaceAbove) {
889
- const f = this.options.spaceAbove * 10;
890
- this.rendererInstance.addTotalRootSvgYOffset(f);
899
+ const E = this.options.spaceAbove * 10;
900
+ this.rendererInstance.addTotalRootSvgYOffset(E);
891
901
  }
892
902
  if (this.options.spaceBelow) {
893
- let f = this.options.spaceBelow * 10;
894
- this.rendererInstance.addTotalRootSvgHeight(f);
903
+ let E = this.options.spaceBelow * 10;
904
+ this.rendererInstance.addTotalRootSvgHeight(E);
895
905
  }
896
- const n = this.rendererInstance.getLayerByName("staff");
897
- this.rendererInstance.addTotalRootSvgHeight(I * 2);
898
- const o = this.rendererInstance.createGroup("time-signature");
899
- n.appendChild(o);
900
- const i = I - J;
901
- this.rendererInstance.drawGlyph(r, o), this.rendererInstance.drawGlyph("TIME_4", o, { yOffset: J }), o.setAttribute("transform", `translate(0, ${i})`);
902
- let a = this.options.width - 38;
903
- this.options.barsCount > 1 && (a -= (this.options.barsCount - 1) * F), a -= tt, this.rendererInstance.drawLine(0, I, this.options.width - tt, I, n), this.barSpacing = a / this.options.barsCount, this.quarterNoteSpacing = Math.round(this.barSpacing / this.options.topNumber), this.maxBeatCount = this.options.barsCount * this.options.topNumber;
904
- let c = this.barSpacing + 38;
905
- const l = I / 2, d = I + l;
906
- for (let f = 0; f < this.options.barsCount - 1; f++)
907
- this.rendererInstance.drawLine(c, l, c, d, n), c += this.barSpacing;
908
- this.rendererInstance.getLayerByName("notes").setAttribute("transform", `translate(38, ${I})`), this.rendererInstance.applySizingToRootSvg(), this.rendererInstance.commitElementsToDOM(s);
906
+ this.rendererInstance.addTotalRootSvgHeight(_ * 2);
907
+ const i = this.rendererInstance.createGroup("time-signature");
908
+ r.appendChild(i);
909
+ const a = _ - Q;
910
+ this.rendererInstance.drawGlyph(o, i), this.rendererInstance.drawGlyph("TIME_4", i, { yOffset: Q }), i.setAttribute("transform", `translate(0, ${a})`);
911
+ let h = this.options.width - 38;
912
+ this.options.barsCount > 1 && (h -= (this.options.barsCount - 1) * D), h -= J, this.rendererInstance.drawLine(0, _, this.options.width - J, _, r), this.barSpacing = h / this.options.barsCount, this.quarterNoteSpacing = Math.round(this.barSpacing / this.options.topNumber), this.maxBeatCount = this.options.barsCount * this.options.topNumber;
913
+ let d = this.barSpacing + 38;
914
+ const c = _ / 2, f = _ + c;
915
+ for (let E = 0; E < this.options.barsCount - 1; E++)
916
+ this.rendererInstance.drawLine(d, c, d, f, r), d += this.barSpacing;
917
+ n.setAttribute("transform", `translate(38, ${_})`), this.rendererInstance.applySizingToRootSvg(), this.rendererInstance.commitElementsToDOM(s);
909
918
  }
910
919
  createBeatUIElement() {
911
- const e = this.rendererInstance.getLayerByName("ui");
920
+ const e = this.rendererInstance.getLayer("ui");
921
+ if (!e) throw new Error("BeatUI Error: Failed to retrieve ui layer");
912
922
  this.currentBeatUIElement = this.rendererInstance.drawRect(
913
923
  this.quarterNoteSpacing / 2,
914
- I * 2,
924
+ _ * 2,
915
925
  e,
916
926
  {
917
- x: D,
918
- fill: this.options.currentBeatUIColor
927
+ x: H,
928
+ fill: "rgba(0,255,40,0.4)",
929
+ classes: "rhythm-current-beat"
919
930
  }
920
931
  );
921
932
  }
922
933
  handleNewBar() {
923
- this.noteCursorX += F;
934
+ this.noteCursorX += D;
924
935
  }
925
936
  // Translates group, returns cursor increment amount
926
937
  translateGroupByDuration(e, t) {
@@ -980,19 +991,18 @@ class Gt {
980
991
  for (; s > 0; ) {
981
992
  const r = this.rendererInstance.createGroup("rest");
982
993
  let n = 0;
983
- s - p.h >= 0 ? (this.rendererInstance.drawGlyph("REST_HALF", r), n = p.h) : s - p.q >= 0 ? (this.rendererInstance.drawGlyph("REST_QUARTER", r), n = p.q) : (this.rendererInstance.drawGlyph("REST_EIGHTH", r), n = p.e), s -= n, this.currentBeatCount += n, r.setAttribute("transform", `translate(${this.noteCursorX}, 0)`), this.noteCursorX += n * this.quarterNoteSpacing, t.push(r);
994
+ s - I.h >= 0 ? (this.rendererInstance.drawGlyph("REST_HALF", r), n = I.h) : s - I.q >= 0 ? (this.rendererInstance.drawGlyph("REST_QUARTER", r), n = I.q) : (this.rendererInstance.drawGlyph("REST_EIGHTH", r), n = I.e), s -= n, this.currentBeatCount += n, r.setAttribute("transform", `translate(${this.noteCursorX}, 0)`), this.noteCursorX += n * this.quarterNoteSpacing, t.push(r);
984
995
  }
985
996
  return t;
986
997
  }
987
998
  renderBeamRect(e, t, s, r) {
988
999
  this.rendererInstance.drawRect(
989
1000
  e - t,
990
- St,
1001
+ Ct,
991
1002
  s,
992
1003
  {
993
1004
  x: 10,
994
- y: -28 + (r ?? 0),
995
- fill: this.options.staffColor
1005
+ y: -28 + (r ?? 0)
996
1006
  }
997
1007
  );
998
1008
  }
@@ -1015,24 +1025,26 @@ class Gt {
1015
1025
  * drawNote("w");
1016
1026
  */
1017
1027
  drawNote(e) {
1018
- const t = Array.isArray(e) ? e : [e], s = this.rendererInstance.getLayerByName("notes"), r = [];
1028
+ const t = Array.isArray(e) ? e : [e], s = this.rendererInstance.getLayer("notes");
1029
+ if (!s) throw new Error("DrawNote Error: Failed to retrieve notes layer");
1030
+ const r = [];
1019
1031
  for (const n of t) {
1020
1032
  let o = "w";
1021
1033
  try {
1022
- o = b(n);
1023
- } catch (d) {
1024
- throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), d;
1034
+ o = v(n);
1035
+ } catch (c) {
1036
+ throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), c;
1025
1037
  }
1026
- const i = p[o];
1038
+ const i = I[o];
1027
1039
  if (this.currentBeatCount >= this.maxBeatCount)
1028
1040
  throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), new Error("Max beat count reached. Can't add additional notes.");
1029
1041
  this.checkAndCreateNewBar();
1030
1042
  const a = this.checkAndFillBarWithRests(i);
1031
- a && a.forEach((d) => {
1032
- r.push(d), this.noteEntries.push(d);
1043
+ a && a.forEach((c) => {
1044
+ r.push(c), this.noteEntries.push(c);
1033
1045
  });
1034
- const c = this.rendererInstance.createGroup("note"), l = this.translateGroupByDuration(i, c);
1035
- this.noteCursorX += l, this.currentBeatCount += i, this.renderNote(o, c), r.push(c), this.noteEntries.push(c);
1046
+ const h = this.rendererInstance.createGroup("note"), d = this.translateGroupByDuration(i, h);
1047
+ this.noteCursorX += d, this.currentBeatCount += i, this.renderNote(o, h), r.push(h), this.noteEntries.push(h);
1036
1048
  }
1037
1049
  this.rendererInstance.commitElementsToDOM(r, s);
1038
1050
  }
@@ -1055,22 +1067,24 @@ class Gt {
1055
1067
  * drawRest("w");
1056
1068
  */
1057
1069
  drawRest(e) {
1058
- const t = Array.isArray(e) ? e : [e], s = this.rendererInstance.getLayerByName("notes"), r = [];
1070
+ const t = Array.isArray(e) ? e : [e], s = this.rendererInstance.getLayer("notes");
1071
+ if (!s) throw new Error("DrawRest Error: Failed to retrieve notes layer");
1072
+ const r = [];
1059
1073
  for (const n of t) {
1060
1074
  let o = "w";
1061
1075
  try {
1062
- o = b(n);
1063
- } catch (d) {
1064
- throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), d;
1076
+ o = v(n);
1077
+ } catch (c) {
1078
+ throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), c;
1065
1079
  }
1066
- const i = this.rendererInstance.createGroup("rest"), a = p[o], c = a * this.quarterNoteSpacing;
1080
+ const i = this.rendererInstance.createGroup("rest"), a = I[o], h = a * this.quarterNoteSpacing;
1067
1081
  if (this.currentBeatCount >= this.maxBeatCount)
1068
1082
  throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), new Error("Max beat count reached. Can't add additional notes.");
1069
1083
  this.checkAndCreateNewBar();
1070
- const l = this.checkAndFillBarWithRests(a);
1071
- l && l.forEach((d) => {
1072
- r.push(d), this.noteEntries.push(d);
1073
- }), this.renderRest(o, i), i.setAttribute("transform", `translate(${this.noteCursorX}, 0)`), this.noteCursorX += c, this.currentBeatCount += a, r.push(i), this.noteEntries.push(i);
1084
+ const d = this.checkAndFillBarWithRests(a);
1085
+ d && d.forEach((c) => {
1086
+ r.push(c), this.noteEntries.push(c);
1087
+ }), this.renderRest(o, i), i.setAttribute("transform", `translate(${this.noteCursorX}, 0)`), this.noteCursorX += h, this.currentBeatCount += a, r.push(i), this.noteEntries.push(i);
1074
1088
  }
1075
1089
  this.rendererInstance.commitElementsToDOM(r, s);
1076
1090
  }
@@ -1097,13 +1111,15 @@ class Gt {
1097
1111
  if (this.currentBeatCount >= this.maxBeatCount)
1098
1112
  throw new Error("Max beat count reached. Can't add additional beamed note.");
1099
1113
  let s = "s";
1100
- e === "s" ? s = "s" : s = b(e), this.checkAndCreateNewBar();
1101
- const r = this.rendererInstance.getLayerByName("notes"), n = p[s], o = n * this.quarterNoteSpacing, i = this.options.topNumber - this.currentBeatCount % this.options.topNumber, a = Math.min(t, i / n), c = this.rendererInstance.createGroup("beamed-note");
1102
- c.setAttribute("transform", `translate(${this.noteCursorX}, 0)`);
1103
- let l = 0;
1104
- for (let d = 0; d < a; d++)
1105
- this.rendererInstance.drawGlyph("NOTE_HEAD_QUARTER", c, { xOffset: l }), this.drawStem(c, l), l += o, this.currentBeatCount += n;
1106
- this.renderBeamRect(l, o, c), e === "s" && this.renderBeamRect(l, o, c, Nt), this.noteCursorX += l, this.noteEntries.push(c), this.rendererInstance.commitElementsToDOM(c, r);
1114
+ e === "s" ? s = "s" : s = v(e), this.checkAndCreateNewBar();
1115
+ const r = this.rendererInstance.getLayer("notes");
1116
+ if (!r) throw new Error("drawBeamedNotes Error: Failed to retrieve notes layer");
1117
+ const n = I[s], o = n * this.quarterNoteSpacing, i = this.options.topNumber - this.currentBeatCount % this.options.topNumber, a = Math.min(t, i / n), h = this.rendererInstance.createGroup("beamed-note");
1118
+ h.setAttribute("transform", `translate(${this.noteCursorX}, 0)`);
1119
+ let d = 0;
1120
+ for (let c = 0; c < a; c++)
1121
+ this.rendererInstance.drawGlyph("NOTE_HEAD_QUARTER", h, { xOffset: d }), this.drawStem(h, d), d += o, this.currentBeatCount += n;
1122
+ this.renderBeamRect(d, o, h), e === "s" && this.renderBeamRect(d, o, h, Nt), this.noteCursorX += d, this.noteEntries.push(h), this.rendererInstance.commitElementsToDOM(h, r);
1107
1123
  }
1108
1124
  /**
1109
1125
  * Will increment the UI showing the current beat in quarters. Once exceeded, must be reset with `resetCurrentBeatUI()`
@@ -1114,21 +1130,21 @@ class Gt {
1114
1130
  this.currentBeatUIElement.setAttribute("display", "none");
1115
1131
  return;
1116
1132
  }
1117
- this.currentBeatUIElement?.getAttribute("display") === "none" && this.currentBeatUIElement.removeAttribute("display"), this.currentBeatUICount++, this.currentBeatUICount > this.options.topNumber && this.currentBeatUICount % this.options.topNumber === 1 && (this.currentBeatUIXPos += F), this.currentBeatUICount > 1 && (this.currentBeatUIXPos += this.quarterNoteSpacing), this.currentBeatUIElement.setAttribute("x", this.currentBeatUIXPos.toString());
1133
+ this.currentBeatUIElement?.getAttribute("display") === "none" && this.currentBeatUIElement.removeAttribute("display"), this.currentBeatUICount++, this.currentBeatUICount > this.options.topNumber && this.currentBeatUICount % this.options.topNumber === 1 && (this.currentBeatUIXPos += D), this.currentBeatUICount > 1 && (this.currentBeatUIXPos += this.quarterNoteSpacing), this.currentBeatUIElement.setAttribute("x", this.currentBeatUIXPos.toString());
1118
1134
  }
1119
1135
  /**
1120
1136
  * Resets the ui showing the current beat value.
1121
1137
  * @returns void
1122
1138
  */
1123
1139
  resetCurrentBeatUI() {
1124
- this.currentBeatUICount = 0, this.currentBeatUIXPos = D, this.currentBeatUIElement && (this.currentBeatUIElement.setAttribute("display", "none"), this.currentBeatUIElement.setAttribute("x", this.currentBeatUIXPos.toString()));
1140
+ this.currentBeatUICount = 0, this.currentBeatUIXPos = H, this.currentBeatUIElement && (this.currentBeatUIElement.setAttribute("display", "none"), this.currentBeatUIElement.setAttribute("x", this.currentBeatUIXPos.toString()));
1125
1141
  }
1126
1142
  /**
1127
1143
  * Clears staff of notes and resets internal positioning.
1128
1144
  * @returns void
1129
1145
  */
1130
1146
  clearAllNotes() {
1131
- this.noteCursorX = 0, this.currentBeatCount = 0, this.rendererInstance.getLayerByName("notes").replaceChildren(), this.noteEntries = [];
1147
+ this.noteCursorX = 0, this.currentBeatCount = 0, this.rendererInstance.getLayer("notes")?.replaceChildren(), this.noteEntries = [];
1132
1148
  }
1133
1149
  /**
1134
1150
  * Removes the root svg element and cleans up arrays.
@@ -1152,8 +1168,8 @@ const Rt = [
1152
1168
  "ACCIDENTAL_NATURAL",
1153
1169
  "ACCIDENTAL_DOUBLE_SHARP",
1154
1170
  "ACCIDENTAL_DOUBLE_FLAT"
1155
- ], y = 60, yt = y;
1156
- class vt {
1171
+ ], y = 60, wt = y;
1172
+ class Gt {
1157
1173
  svgRendererInstance;
1158
1174
  strategyInstance;
1159
1175
  noteRendererInstance;
@@ -1177,46 +1193,45 @@ class vt {
1177
1193
  staffType: "treble",
1178
1194
  spaceAbove: 0,
1179
1195
  spaceBelow: 0,
1180
- staffColor: "black",
1181
- staffBackgroundColor: "transparent",
1196
+ svgAutoFill: !0,
1182
1197
  ...t
1183
- }, this.svgRendererInstance = new w(e, {
1198
+ }, this.svgRendererInstance = new O(e, {
1184
1199
  width: this.options.width,
1185
1200
  height: 100,
1186
1201
  scale: this.options.scale,
1187
- staffColor: this.options.staffColor,
1188
- staffBackgroundColor: this.options.staffBackgroundColor,
1189
- useGlyphs: Rt
1202
+ useGlyphs: Rt,
1203
+ svgAutoFill: this.options.svgAutoFill
1190
1204
  });
1191
1205
  const s = this.svgRendererInstance.rootSvgElement;
1192
1206
  switch (this.options.staffType) {
1193
1207
  case "grand":
1194
- this.strategyInstance = new ot(this.svgRendererInstance, "grand");
1208
+ this.strategyInstance = new nt(this.svgRendererInstance, "grand");
1195
1209
  break;
1196
1210
  case "bass":
1197
- this.strategyInstance = new m(this.svgRendererInstance, "bass");
1211
+ this.strategyInstance = new S(this.svgRendererInstance, "bass");
1198
1212
  break;
1199
1213
  case "treble":
1200
- this.strategyInstance = new m(this.svgRendererInstance, "treble");
1214
+ this.strategyInstance = new S(this.svgRendererInstance, "treble");
1201
1215
  break;
1202
1216
  case "alto":
1203
- this.strategyInstance = new m(this.svgRendererInstance, "alto");
1217
+ this.strategyInstance = new S(this.svgRendererInstance, "alto");
1204
1218
  break;
1205
1219
  default:
1206
1220
  throw new Error(`The staff type ${this.options.staffType} is not supported. Please use "treble", "bass", "alto", or "grand".`);
1207
1221
  }
1208
- if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new it(this.svgRendererInstance, this.strategyInstance), this.options.spaceAbove) {
1209
- const r = this.options.spaceAbove * 10;
1210
- this.svgRendererInstance.addTotalRootSvgYOffset(r);
1222
+ if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new ot(this.svgRendererInstance, this.strategyInstance), this.options.spaceAbove) {
1223
+ const n = this.options.spaceAbove * 10;
1224
+ this.svgRendererInstance.addTotalRootSvgYOffset(n);
1211
1225
  }
1212
1226
  if (this.options.spaceBelow) {
1213
- let r = this.options.spaceBelow * 10;
1214
- this.options.staffType === "grand" && (r -= 10 / 2), this.svgRendererInstance.addTotalRootSvgHeight(r);
1227
+ let n = this.options.spaceBelow * 10;
1228
+ this.options.staffType === "grand" && (n -= 10 / 2), this.svgRendererInstance.addTotalRootSvgHeight(n);
1215
1229
  }
1216
- this.notesLayer = this.svgRendererInstance.getLayerByName("notes"), this.notesLayer.classList.add("vs-scrolling-notes-layer"), this.noteStartX = 38 + this.options.noteStartX, this.svgRendererInstance.getLayerByName("notes").setAttribute("transform", `translate(${this.noteStartX}, 0)`), this.svgRendererInstance.applySizingToRootSvg(), this.svgRendererInstance.commitElementsToDOM(s);
1230
+ const r = this.svgRendererInstance.createLayer("notes");
1231
+ this.notesLayer = r, r.classList.add("vs-scrolling-notes-layer"), this.noteStartX = 38 + this.options.noteStartX, r.setAttribute("transform", `translate(${this.noteStartX}, 0)`), this.svgRendererInstance.applySizingToRootSvg(), this.svgRendererInstance.commitElementsToDOM(s);
1217
1232
  }
1218
1233
  renderFirstNoteGroups() {
1219
- const e = this.options.width - this.options.noteStartX + yt;
1234
+ const e = this.options.width - this.options.noteStartX + wt;
1220
1235
  for (; this.noteBuffer.length > 0 && this.noteCursorX < e; )
1221
1236
  this.renderNextNote(), this.noteCursorX += y;
1222
1237
  this.activeEntries.length > 1 && (this.noteCursorX -= y);
@@ -1298,29 +1313,29 @@ class vt {
1298
1313
  this.svgRendererInstance.destroy(), this.activeEntries = [], this.noteBuffer = [];
1299
1314
  }
1300
1315
  }
1301
- const wt = /^[xX\da-zA-Z]+$/, Ot = /^[\d]+$/;
1302
- function et(h, e) {
1316
+ const yt = /^[xX\da-zA-Z]+$/, Ot = /^[\d]+$/;
1317
+ function tt(l, e) {
1303
1318
  const t = [];
1304
- for (let s = 0; s < h.length; s++)
1319
+ for (let s = 0; s < l.length; s++)
1305
1320
  t.push({
1306
- fret: h[s],
1321
+ fret: l[s],
1307
1322
  finger: e[s]
1308
1323
  });
1309
1324
  return t;
1310
1325
  }
1311
- function st(h, e) {
1312
- const t = h.filter((n) => n.toLowerCase() !== "x" && n !== "0").map((n) => parseInt(n, 36));
1326
+ function et(l, e) {
1327
+ const t = l.filter((n) => n.toLowerCase() !== "x" && n !== "0").map((n) => parseInt(n, 36));
1313
1328
  if (t.length === 0) return 1;
1314
1329
  const s = Math.min(...t);
1315
1330
  return Math.max(...t) <= e ? 1 : s;
1316
1331
  }
1317
- function H(h) {
1318
- if (!wt.test(h)) throw new Error("Invalid frets string. Only 'x', 'X', and digits are allowed.");
1319
- return h.split("");
1332
+ function P(l) {
1333
+ if (!yt.test(l)) throw new Error("Invalid frets string. Only 'x', 'X', and digits are allowed.");
1334
+ return l.split("");
1320
1335
  }
1321
- function B(h) {
1322
- if (!Ot.test(h)) throw new Error("Invalid fingers string. Only digits are allowed.");
1323
- return h.split("");
1336
+ function B(l) {
1337
+ if (!Ot.test(l)) throw new Error("Invalid fingers string. Only digits are allowed.");
1338
+ return l.split("");
1324
1339
  }
1325
1340
  class Ft {
1326
1341
  svgRendererInstance;
@@ -1341,23 +1356,22 @@ class Ft {
1341
1356
  */
1342
1357
  constructor(e, t) {
1343
1358
  if (this.options = {
1344
- stringCount: at,
1345
- fretCount: ct,
1359
+ stringCount: it,
1360
+ fretCount: at,
1346
1361
  stringLabels: [],
1347
1362
  inlineChordsAmount: 2,
1363
+ centerChords: !0,
1348
1364
  scale: 1,
1349
- color: "black",
1350
- backgroundColor: "transparent",
1365
+ svgAutoFill: !0,
1351
1366
  ...t
1352
- }, this.diagramWidth = (this.options.stringCount - 1) * _, this.diagramHeight = this.options.fretCount * T, this.gridTopY = Z + W, this.rowHeight = this.gridTopY + this.diagramHeight + $, t?.width ? this.options.width = t.width : this.options.width = (this.diagramWidth + M) * this.options.inlineChordsAmount, this.options.stringLabels.length >= 1 && (this.rowHeight += lt + ht), this.diagramWidth > this.options.width)
1367
+ }, this.diagramWidth = (this.options.stringCount - 1) * T, this.diagramHeight = this.options.fretCount * m, this.gridTopY = k + W, this.rowHeight = this.gridTopY + this.diagramHeight + $, t?.width ? this.options.width = t.width : this.options.width = (this.diagramWidth + L) * this.options.inlineChordsAmount, this.options.stringLabels.length >= 1 && (this.rowHeight += ht + ct), this.diagramWidth > this.options.width)
1353
1368
  throw new Error(`The configured width (${this.options.width}) is too small to fit a single ${this.options.stringCount}-string diagram (needs at least ${this.diagramWidth}). Increase 'width'.`);
1354
- this.svgRendererInstance = new w(e, {
1369
+ this.svgRendererInstance = new O(e, {
1355
1370
  width: this.options.width,
1356
1371
  height: 100,
1357
1372
  scale: this.options.scale,
1358
- staffColor: this.options.color,
1359
- staffBackgroundColor: this.options.backgroundColor,
1360
- useGlyphs: []
1373
+ useGlyphs: [],
1374
+ svgAutoFill: this.options.svgAutoFill
1361
1375
  });
1362
1376
  const s = this.svgRendererInstance.rootSvgElement;
1363
1377
  this.svgRendererInstance.setTotalRootSvgHeight(this.rowHeight), this.svgRendererInstance.applySizingToRootSvg(), this.svgRendererInstance.commitElementsToDOM(s);
@@ -1373,30 +1387,33 @@ class Ft {
1373
1387
  drawFretDots(e, t, s, r, n) {
1374
1388
  const o = this.gridTopY - W / 2;
1375
1389
  for (let i = 0; i < this.options.stringCount; i++) {
1376
- const a = i * _, c = e[i].toLowerCase(), l = t[i];
1377
- if (c === "x")
1378
- this.svgRendererInstance.drawLine(a - g, o - g, a + g, o + g, n), this.svgRendererInstance.drawLine(a - g, o + g, a + g, o - g, n);
1379
- else if (c === "0")
1380
- this.svgRendererInstance.drawCircle(a, o, g, n, { filled: !1 });
1390
+ const a = i * T, h = e[i].toLowerCase(), d = t[i], c = this.svgRendererInstance.createGroup("");
1391
+ if (h === "x")
1392
+ c.classList.add("vs-guitar-fret-muted"), c.setAttribute("transform", `translate(${a}, ${o})`), this.svgRendererInstance.drawLine(-A, -A, A, A, c, {
1393
+ strokeWidth: 1.5
1394
+ }), this.svgRendererInstance.drawLine(-A, A, A, -A, c, {
1395
+ strokeWidth: 1.5
1396
+ });
1397
+ else if (h === "0")
1398
+ c.classList.add("vs-guitar-fret-open"), c.setAttribute("transform", `translate(${a}, ${o})`), this.svgRendererInstance.drawCircle(0, 0, A, c, { filled: !1 });
1381
1399
  else {
1382
- const d = parseInt(c, 36);
1383
- if (r.has(`${i}-${d}`))
1400
+ const f = parseInt(h, 36);
1401
+ if (r.has(`${i}-${f}`))
1384
1402
  continue;
1385
- const f = d - s + 1;
1386
- if (f < 1 || f > this.options.fretCount)
1387
- throw new Error(`Fret ${c} on string ${i + 1} is outside the visible range (${s}-${s + this.options.fretCount - 1}). Adjust 'startFret' or 'fretCount'.`);
1388
- const C = this.gridTopY + (f - 0.5) * T;
1389
- if (this.svgRendererInstance.drawCircle(a, C, u, n, {
1390
- classes: "guitar-fret-dot"
1391
- }), l !== "0") {
1392
- const E = this.options.backgroundColor === "transparent" ? "white" : this.options.backgroundColor;
1393
- this.svgRendererInstance.drawText(l, a, C + S / 3, n, {
1394
- fontSize: S,
1395
- fill: E,
1396
- classes: "guitar-text-small"
1397
- });
1398
- }
1403
+ c.classList.add("vs-guitar-fret-dot");
1404
+ const E = f - s + 1;
1405
+ if (E < 1 || E > this.options.fretCount)
1406
+ throw new Error(`Fret ${h} on string ${i + 1} is outside the visible range (${s}-${s + this.options.fretCount - 1}). Adjust 'startFret' or 'fretCount'.`);
1407
+ const g = this.gridTopY + (E - 0.5) * m;
1408
+ c.setAttribute("transform", `translate(${a}, ${g})`), this.svgRendererInstance.drawCircle(0, 0, u, c, {
1409
+ classes: "guitar-fret-circle"
1410
+ }), d !== "0" && this.svgRendererInstance.drawText(d, 0, -1, c, {
1411
+ fontSize: R,
1412
+ baseline: "central",
1413
+ classes: ["guitar-text", "guitar-fret-text"]
1414
+ });
1399
1415
  }
1416
+ n.appendChild(c);
1400
1417
  }
1401
1418
  }
1402
1419
  drawStringLabels(e, t) {
@@ -1405,10 +1422,11 @@ class Ft {
1405
1422
  for (let n = 0; n < this.options.stringCount; n++) {
1406
1423
  const o = t[n];
1407
1424
  if (!o) continue;
1408
- const i = n * _, a = r + s / 2;
1409
- this.svgRendererInstance.drawText(o, i, a, e, {
1410
- fontSize: S,
1411
- classes: "guitar-text-small"
1425
+ const i = n * T;
1426
+ this.svgRendererInstance.drawText(o, i, r, e, {
1427
+ fontSize: R,
1428
+ baseline: "central",
1429
+ classes: "guitar-text"
1412
1430
  });
1413
1431
  }
1414
1432
  }
@@ -1419,69 +1437,82 @@ class Ft {
1419
1437
  throw new Error(`Barre fret error: Invalid string range ${t.fromIndex + 1}:${t.toIndex + 1}.`);
1420
1438
  if (s < t.startingFret || s > t.startingFret + (this.options.fretCount - 1))
1421
1439
  throw new Error(`Barre fret error: ${t.fret} is outside the visible range.`);
1422
- const r = s - t.startingFret, n = t.fromIndex * _, o = t.toIndex * _, i = u * 2, a = o - n + i, c = this.gridTopY + u / 2 + T * r, l = this.gridTopY + T * r + u * 2;
1423
- if (this.svgRendererInstance.drawRect(a, i, e, {
1424
- x: n - u,
1425
- y: c,
1440
+ const r = this.svgRendererInstance.createGroup("guitar-group-barre"), n = s - t.startingFret, o = t.fromIndex * T, i = t.toIndex * T, a = u * 2, h = i - o + a, d = this.gridTopY + m * n;
1441
+ r.setAttribute("transform", `translate(0, ${d})`), this.svgRendererInstance.drawRect(h, a, r, {
1442
+ x: o - u,
1443
+ y: u / 2,
1426
1444
  rx: u,
1427
1445
  classes: "guitar-barre"
1428
- }), t.finger) {
1429
- const d = this.options.backgroundColor === "transparent" ? "white" : this.options.backgroundColor;
1430
- this.svgRendererInstance.drawText(t.finger.toString(), (n + o) / 2, l, e, {
1431
- fontSize: S,
1432
- fill: d,
1433
- classes: "guitar-text-small"
1434
- });
1435
- }
1446
+ }), t.finger && this.svgRendererInstance.drawText(t.finger.toString(), (o + i) / 2, u * 1.5 - 1, r, {
1447
+ fontSize: R,
1448
+ baseline: "central",
1449
+ classes: ["guitar-text", "guitar-fret-text"]
1450
+ }), e.appendChild(r);
1436
1451
  }
1437
1452
  // Builds a single chord diagram's group element: grid, nut/fret-position label, and per-string markers.
1438
1453
  renderChordDiagram(e, t, s) {
1439
1454
  const r = this.svgRendererInstance.createGroup("chord"), n = s?.startFret ?? 1;
1440
- s?.label && this.svgRendererInstance.drawText(s.label, this.diagramWidth / 2, Z - 5, r, {
1441
- fontSize: rt,
1455
+ s?.label && this.svgRendererInstance.drawText(s.label, this.diagramWidth / 2, k - 5, r, {
1456
+ fontSize: st,
1442
1457
  fontWeight: "bold",
1443
- classes: "guitar-text-base"
1444
- });
1445
- for (let i = 0; i <= this.options.fretCount; i++) {
1446
- const a = this.gridTopY + i * T;
1447
- i === 0 && n === 1 ? this.svgRendererInstance.drawRect(this.diagramWidth + k * 2, P, r, {
1448
- x: -k,
1449
- y: a - P / 2
1450
- }) : this.svgRendererInstance.drawLine(0, a, this.diagramWidth, a, r);
1451
- }
1452
- n > 1 && this.svgRendererInstance.drawText(`${n}fr`, this.diagramWidth + u + ut, this.gridTopY + T / 2 + 4, r, {
1458
+ classes: ["guitar-text", "guitar-diagram-label"]
1459
+ }), n > 1 && this.svgRendererInstance.drawText(`${n}fr`, this.diagramWidth + u + Et, this.gridTopY + m / 2 + 4, r, {
1453
1460
  anchor: "start",
1454
- fontSize: S,
1461
+ fontSize: R,
1455
1462
  fontWeight: "bold",
1456
- classes: "guitar-text-small"
1463
+ classes: ["guitar-text", "guitar-fret-label"]
1457
1464
  });
1458
- for (let i = 0; i < this.options.stringCount; i++) {
1459
- const a = i * _;
1460
- this.svgRendererInstance.drawLine(a, this.gridTopY, a, this.gridTopY + this.diagramHeight, r);
1465
+ const o = this.svgRendererInstance.createGroup("guitar-group-fret-lines");
1466
+ for (let c = 0; c <= this.options.fretCount; c++) {
1467
+ const f = this.gridTopY + c * m;
1468
+ c === 0 && n === 1 ? this.svgRendererInstance.drawRect(this.diagramWidth + ft, x, o, {
1469
+ x: -0.5,
1470
+ y: f - x / 2
1471
+ }) : this.svgRendererInstance.drawLine(0, f, this.diagramWidth, f, o);
1461
1472
  }
1462
- const o = this.getDotsToHide(s?.barres);
1463
- return this.drawFretDots(e, t, n, o, r), this.options.stringLabels.length >= 1 && this.drawStringLabels(r, this.options.stringLabels), s?.barres?.forEach((i) => {
1464
- this.drawBarre(r, {
1465
- fromIndex: i.fromString - 1,
1466
- toIndex: i.toString - 1,
1467
- fret: i.fret,
1468
- finger: i.finger,
1473
+ r.appendChild(o);
1474
+ const i = this.svgRendererInstance.createGroup("guitar-group-string-lines");
1475
+ for (let c = 0; c < this.options.stringCount; c++) {
1476
+ const f = c * T;
1477
+ this.svgRendererInstance.drawLine(f, this.gridTopY, f, this.gridTopY + this.diagramHeight, i);
1478
+ }
1479
+ r.appendChild(i);
1480
+ const a = this.svgRendererInstance.createGroup("guitar-group-fret-dots"), h = this.getDotsToHide(s?.barres);
1481
+ this.drawFretDots(e, t, n, h, a), s?.barres?.forEach((c) => {
1482
+ this.drawBarre(a, {
1483
+ fromIndex: c.fromString - 1,
1484
+ toIndex: c.toString - 1,
1485
+ fret: c.fret,
1486
+ finger: c.finger,
1469
1487
  startingFret: n
1470
1488
  });
1471
- }), r;
1489
+ }), r.appendChild(a);
1490
+ const d = this.svgRendererInstance.createGroup("guitar-group-string-labels");
1491
+ return this.options.stringLabels.length >= 1 && this.drawStringLabels(d, this.options.stringLabels), r.appendChild(d), r;
1472
1492
  }
1473
1493
  // Repositions every existing chord diagram from scratch, in order, wrapping rows as needed.
1474
- // Called after any add/remove/change so the layout never has to track incremental deltas.
1494
+ // Called after any add/remove/change so the layout never has to track pos.
1475
1495
  relayoutChords() {
1476
- if (this.cursorX = u, this.cursorY = ft, this.chordEntries.length === 1) {
1477
- const t = this.chordEntries[0];
1478
- this.cursorX = this.options.width / 2 - this.diagramWidth / 2, t.xPos = this.cursorX, t.yPos = this.cursorY, t.gElement.setAttribute("transform", `translate(${this.cursorX}, ${this.cursorY})`);
1479
- } else
1480
- this.chordEntries.forEach((t, s) => {
1481
- s > 0 && this.cursorX + this.diagramWidth > this.options.width && (this.cursorX = u, this.cursorY += this.rowHeight + dt), t.xPos = this.cursorX, t.yPos = this.cursorY, t.gElement.setAttribute("transform", `translate(${this.cursorX}, ${this.cursorY})`), this.cursorX += this.diagramWidth + M;
1496
+ if (this.chordEntries.length === 0) {
1497
+ this.svgRendererInstance.setTotalRootSvgHeight(0), this.svgRendererInstance.applySizingToRootSvg();
1498
+ return;
1499
+ }
1500
+ const e = [];
1501
+ let t = [], s = u;
1502
+ this.chordEntries.forEach((n, o) => {
1503
+ o > 0 && s + this.diagramWidth > this.options.width && (e.push(t), t = [], s = u), t.push(n), s += this.diagramWidth + L;
1504
+ }), t.length > 0 && e.push(t), this.cursorY = dt, e.forEach((n, o) => {
1505
+ if (o > 0 && (this.cursorY += this.rowHeight + lt), this.options.centerChords) {
1506
+ const i = n.length * this.diagramWidth + (n.length - 1) * L, a = this.options.width / 2 - i / 2 - 16;
1507
+ this.cursorX = a;
1508
+ } else
1509
+ this.cursorX = u;
1510
+ n.forEach((i) => {
1511
+ i.xPos = this.cursorX, i.yPos = this.cursorY, i.gElement.setAttribute("transform", `translate(${this.cursorX}, ${this.cursorY})`), this.cursorX += this.diagramWidth + L;
1482
1512
  });
1483
- const e = this.cursorY + this.rowHeight;
1484
- this.svgRendererInstance.setTotalRootSvgHeight(e), this.svgRendererInstance.applySizingToRootSvg();
1513
+ });
1514
+ const r = this.cursorY + this.rowHeight;
1515
+ this.svgRendererInstance.setTotalRootSvgHeight(r), this.svgRendererInstance.applySizingToRootSvg();
1485
1516
  }
1486
1517
  /**
1487
1518
  * Adds a new chord diagram. Diagrams are placed left-to-right in the order added, wrapping to a
@@ -1507,14 +1538,14 @@ class Ft {
1507
1538
  * guitarChord.addChord("x32010", "032010", { label: "C" });
1508
1539
  */
1509
1540
  addChord(e, t, s) {
1510
- const r = H(e), n = B(t);
1541
+ const r = P(e), n = B(t);
1511
1542
  if (r.length !== this.options.stringCount) throw new Error("Invalid number of frets provided, entries should be equal to number of strings in diagram.");
1512
1543
  if (n.length !== this.options.stringCount) throw new Error("Invalid number of fingers provided, entries should be equal to number of strings in diagram.");
1513
- const o = s?.startFret ?? st(r, this.options.fretCount), i = s?.label, a = s?.barres, c = { startFret: o, label: i, barres: a }, l = this.renderChordDiagram(r, n, c), d = this.svgRendererInstance.getLayerByName("notes");
1514
- return this.svgRendererInstance.commitElementsToDOM(l, d), this.chordEntries.push({
1515
- gElement: l,
1516
- strings: et(r, n),
1517
- ...c,
1544
+ const o = s?.startFret ?? et(r, this.options.fretCount), i = s?.label, a = s?.barres, h = { startFret: o, label: i, barres: a }, d = this.renderChordDiagram(r, n, h), c = this.svgRendererInstance.parentGroupElement;
1545
+ return this.svgRendererInstance.commitElementsToDOM(d, c), this.chordEntries.push({
1546
+ gElement: d,
1547
+ strings: tt(r, n),
1548
+ ...h,
1518
1549
  xPos: 0,
1519
1550
  yPos: 0
1520
1551
  }), this.relayoutChords(), this.chordEntries.length - 1;
@@ -1545,14 +1576,14 @@ class Ft {
1545
1576
  */
1546
1577
  modifyChordByIndex(e, t, s, r) {
1547
1578
  if (s >= this.chordEntries.length || s < 0) throw new Error("Chord index was out of bounds.");
1548
- const n = H(e), o = B(t);
1579
+ const n = P(e), o = B(t);
1549
1580
  if (n.length !== this.options.stringCount) throw new Error("Invalid number of frets provided, entries should be equal to number of strings in diagram.");
1550
1581
  if (o.length !== this.options.stringCount) throw new Error("Invalid number of fingers provided, entries should be equal to number of strings in diagram.");
1551
- const i = this.chordEntries[s], a = r && "label" in r ? r.label === "" ? void 0 : r.label : i.label, c = r?.startFret ?? st(n, this.options.fretCount), l = { ...r, label: a, startFret: c }, d = this.renderChordDiagram(n, o, l);
1552
- this.svgRendererInstance.getLayerByName("notes").replaceChild(d, i.gElement), this.chordEntries[s] = {
1553
- gElement: d,
1554
- strings: et(n, o),
1555
- ...l,
1582
+ const i = this.chordEntries[s], a = r && "label" in r ? r.label === "" ? void 0 : r.label : i.label, h = r?.startFret ?? et(n, this.options.fretCount), d = { ...r, label: a, startFret: h }, c = this.renderChordDiagram(n, o, d);
1583
+ this.svgRendererInstance.parentGroupElement.replaceChild(c, i.gElement), this.chordEntries[s] = {
1584
+ gElement: c,
1585
+ strings: tt(n, o),
1586
+ ...d,
1556
1587
  xPos: i.xPos,
1557
1588
  yPos: i.yPos
1558
1589
  }, this.relayoutChords();
@@ -1572,7 +1603,7 @@ class Ft {
1572
1603
  * @returns void
1573
1604
  */
1574
1605
  clearAllChords() {
1575
- this.svgRendererInstance.getLayerByName("notes").replaceChildren(), this.chordEntries = [], this.cursorX = 0, this.cursorY = 0, this.svgRendererInstance.setTotalRootSvgHeight(this.rowHeight), this.svgRendererInstance.applySizingToRootSvg();
1606
+ this.svgRendererInstance.parentGroupElement.replaceChildren(), this.chordEntries = [], this.cursorX = 0, this.cursorY = 0, this.svgRendererInstance.setTotalRootSvgHeight(this.rowHeight), this.svgRendererInstance.applySizingToRootSvg();
1576
1607
  }
1577
1608
  /**
1578
1609
  * * Used to automatically determine options for creating barre lines.
@@ -1580,25 +1611,25 @@ class Ft {
1580
1611
  * @returns GuitarBarreDef[]
1581
1612
  */
1582
1613
  determineBarreOptions(e, t, s) {
1583
- const r = H(e), n = B(t), o = [];
1614
+ const r = P(e), n = B(t), o = [];
1584
1615
  return s.forEach((i) => {
1585
1616
  if (i === 0) return;
1586
- const a = [], c = {};
1587
- for (let E = 0; E < r.length; E++) {
1588
- if (r[E].toLowerCase() === "x") continue;
1589
- const L = parseInt(r[E], 36), O = Number(n[E]);
1590
- L === i && (c[O] ? c[O] += 1 : c[O] = 1, a.push(E + 1));
1617
+ const a = [], h = {};
1618
+ for (let g = 0; g < r.length; g++) {
1619
+ if (r[g].toLowerCase() === "x") continue;
1620
+ const N = parseInt(r[g], 36), b = Number(n[g]);
1621
+ N === i && (h[b] ? h[b] += 1 : h[b] = 1, a.push(g + 1));
1591
1622
  }
1592
1623
  a.sort();
1593
- let l = 0, d = 0;
1594
- for (const [E, L] of Object.entries(c))
1595
- L > d && (d = L, l = Number(E));
1596
- const f = a[0], C = a.at(-1);
1597
- a.length > 1 && C && o.push({
1624
+ let d = 0, c = 0;
1625
+ for (const [g, N] of Object.entries(h))
1626
+ N > c && (c = N, d = Number(g));
1627
+ const f = a[0], E = a.at(-1);
1628
+ a.length > 1 && E && o.push({
1598
1629
  fret: i,
1599
1630
  fromString: f,
1600
- toString: C,
1601
- finger: l
1631
+ toString: E,
1632
+ finger: d
1602
1633
  });
1603
1634
  }), o;
1604
1635
  }
@@ -1613,6 +1644,6 @@ class Ft {
1613
1644
  export {
1614
1645
  Ft as GuitarChord,
1615
1646
  bt as MusicStaff,
1616
- Gt as RhythmStaff,
1617
- vt as ScrollingStaff
1647
+ vt as RhythmStaff,
1648
+ Gt as ScrollingStaff
1618
1649
  };