vector-score 1.1.0 → 1.2.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 I = {
1
+ const R = {
2
2
  treble: {
3
3
  staffType: "treble",
4
4
  paddingTop: 13,
@@ -31,16 +31,16 @@ const I = {
31
31
  topLineYPos: 0,
32
32
  bottomLineYPos: 110
33
33
  }
34
- }, E = {
34
+ }, p = {
35
35
  w: 4,
36
36
  h: 2,
37
37
  q: 1,
38
38
  e: 0.5,
39
39
  s: 0.25
40
- }, w = 8, M = 40, X = {
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 = {
41
41
  sharp: ["F", "C", "G", "D", "A", "E", "B"],
42
42
  flat: ["B", "E", "A", "D", "G", "C", "F"]
43
- }, G = {
43
+ }, q = {
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 I = {
54
54
  Ab: { type: "flat", count: 4 },
55
55
  Db: { type: "flat", count: 5 },
56
56
  Gb: { type: "flat", count: 6 }
57
- }, L = {
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,22 @@ const I = {
75
75
  },
76
76
  grand: { sharp: [], flat: [] }
77
77
  };
78
- function Y(h) {
79
- const e = G[h];
80
- if (!e) throw new Error(`Unknown key signature "${h}". Valid keys: ${Object.keys(G).join(", ")}`);
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(", ")}`);
81
81
  return e;
82
82
  }
83
- function k(h, e, t, s) {
84
- const r = Y(t);
83
+ function At(h, e, t, s) {
84
+ const r = gt(t);
85
85
  if (r.count === 0) return 0;
86
86
  const n = r.type === "sharp" ? "ACCIDENTAL_SHARP" : "ACCIDENTAL_FLAT", o = h.getLayerByName("staff");
87
- return e.getKeySignatureYPositions(r.type, r.count).forEach((i) => {
88
- i.forEach((c, l) => {
89
- h.drawGlyph(n, o, { xOffset: s + l * w, yOffset: c });
87
+ 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 });
90
90
  });
91
- }), r.count * w;
91
+ }), r.count * V;
92
92
  }
93
- const $ = {
93
+ const pt = {
94
94
  CLEF_TREBLE: {
95
95
  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
96
  xOffset: 0,
@@ -186,9 +186,9 @@ const $ = {
186
186
  xOffset: 0,
187
187
  yOffset: 0
188
188
  }
189
- }, W = /^(?<name>[A-Ga-g])(?<accidental>##|bb|[#bn]?)(?<octave>\d)(?<duration>[whqeWHQE]?)$/, Z = /^[whqeWHQE]$/, y = ["C", "D", "E", "F", "G", "A", "B"];
190
- function O(h) {
191
- const e = h.match(W);
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);
192
192
  if (!e || !e.groups)
193
193
  throw new Error(`Invalid note string format: ${h}. Expected format: [A-Ga-g][#|b]?[0-9][w|h|q|e].`);
194
194
  let { name: t, accidental: s, octave: r, duration: n } = e.groups;
@@ -200,12 +200,12 @@ function O(h) {
200
200
  };
201
201
  return s && (o.accidental = s), o;
202
202
  }
203
- function N(h) {
204
- const e = h.match(Z);
203
+ function b(h) {
204
+ const e = h.match(_t);
205
205
  if (!e) throw new Error(`Invalid note duration '${h}'. Use w | h | q | e.`);
206
206
  return e[0].toString().toLowerCase();
207
207
  }
208
- function R(h) {
208
+ function Y(h) {
209
209
  let e;
210
210
  switch (h) {
211
211
  case "treble":
@@ -221,22 +221,22 @@ function R(h) {
221
221
  if (!e) throw new Error(`Invalid clef type: ${h}. Valid clef types are: treble, bass, alto.`);
222
222
  return e;
223
223
  }
224
- function F(h) {
225
- let e = y.indexOf(h.name);
224
+ function z(h) {
225
+ let e = X.indexOf(h.name);
226
226
  return e += h.octave * 12, e;
227
227
  }
228
- function _(h, e) {
229
- return y.indexOf(h.name) - y.indexOf(e.name) + (h.octave - e.octave) * 7;
228
+ function N(h, e) {
229
+ return X.indexOf(h.name) - X.indexOf(e.name) + (h.octave - e.octave) * 7;
230
230
  }
231
- const C = 48, v = 40 + 30 / 2, D = 20, B = 90;
232
- class x {
231
+ const G = 48, j = 40 + 30 / 2, K = 20, Q = 90;
232
+ class ot {
233
233
  params;
234
234
  rendererRef;
235
235
  width = 0;
236
236
  trebleStaffHeight = 0;
237
237
  constructor(e, t) {
238
238
  this.rendererRef = e;
239
- const s = I[t];
239
+ const s = R[t];
240
240
  if (!s) throw new Error(`Staff type ${t} is not supported`);
241
241
  this.params = s;
242
242
  }
@@ -252,17 +252,17 @@ class x {
252
252
  let s = this.drawStaffLines(0, t), r = this.drawStaffLines(s + 30, t);
253
253
  this.rendererRef.drawLine(0, 0, 0, r, t), this.rendererRef.drawLine(this.width, 0, this.width, r, t), this.trebleStaffHeight = s;
254
254
  let n = r, o = 1;
255
- const a = R("treble"), i = R("bass");
256
- this.rendererRef.drawGlyph(a, t), this.rendererRef.drawGlyph(i, t, { yOffset: s + 30 }), n += this.params.paddingBottom + 1, o += this.params.paddingTop, this.rendererRef.addTotalRootSvgHeight(n), this.rendererRef.addTotalRootSvgYOffset(o);
255
+ const i = Y("treble"), a = Y("bass");
256
+ 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
257
  };
258
258
  shouldNoteFlip(e) {
259
- const t = Math.abs(e - B), s = Math.abs(e - D);
260
- return e === v ? !1 : t <= s ? !(e >= B) : e <= D;
259
+ const t = Math.abs(e - Q), s = Math.abs(e - K);
260
+ return e === j ? !1 : t <= s ? !(e >= Q) : e <= K;
261
261
  }
262
262
  getLedgerLinesX(e, t) {
263
- const s = [], r = F(e);
263
+ const s = [], r = z(e);
264
264
  let n = e.duration === "w" ? 17 : 12.5;
265
- if (r === C)
265
+ if (r === G)
266
266
  return s.push({ x1: -2, x2: n, yPos: 0 }), s;
267
267
  if (t < this.params.topLineYPos) {
268
268
  let o = this.params.topLineYPos - 10;
@@ -284,41 +284,41 @@ class x {
284
284
  return s;
285
285
  }
286
286
  calculateNoteYPos = (e) => {
287
- let s = _(this.params.topLineNote, e) * (10 / 2);
288
- const r = F(e);
289
- return r < C ? s += 10 : r === C && (s = v), s;
287
+ let s = N(this.params.topLineNote, e) * (10 / 2);
288
+ const r = z(e);
289
+ return r < G ? s += 10 : r === G && (s = j), s;
290
290
  };
291
291
  getKeySignatureYPositions(e, t) {
292
- const s = X[e].slice(0, t), r = L.treble[e], n = L.bass[e], o = s.map(
293
- (i, c) => _(I.treble.topLineNote, { name: i, octave: r[c] }) * (10 / 2)
294
- ), a = s.map(
295
- (i, c) => _(I.bass.topLineNote, { name: i, octave: n[c] }) * (10 / 2) + this.trebleStaffHeight + 30
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)
294
+ ), i = s.map(
295
+ (a, c) => N(R.bass.topLineNote, { name: a, octave: n[c] }) * (10 / 2) + this.trebleStaffHeight + 30
296
296
  );
297
- return [o, a];
297
+ return [o, i];
298
298
  }
299
299
  }
300
- const V = 20;
301
- class A {
300
+ const Tt = 20;
301
+ class m {
302
302
  params;
303
303
  rendererRef;
304
304
  constructor(e, t) {
305
305
  this.rendererRef = e;
306
- const s = I[t];
306
+ const s = R[t];
307
307
  if (!s) throw new Error(`Staff type ${t} is not supported`);
308
308
  this.params = s;
309
309
  }
310
310
  drawStaff = (e) => {
311
311
  const t = this.rendererRef.getLayerByName("staff");
312
312
  let s = 0;
313
- for (let a = 0; a < 5; a++)
313
+ for (let i = 0; i < 5; i++)
314
314
  this.rendererRef.drawLine(0, s, e, s, t), s += 10;
315
315
  this.rendererRef.drawLine(0, 0, 0, s - 10, t), this.rendererRef.drawLine(e, 0, e, s - 10, t);
316
316
  let r = s - 10 + 1, n = 1;
317
- const o = R(this.params.staffType);
317
+ const o = Y(this.params.staffType);
318
318
  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
319
  };
320
320
  shouldNoteFlip(e) {
321
- return e <= V;
321
+ return e <= Tt;
322
322
  }
323
323
  getLedgerLinesX(e, t) {
324
324
  const s = [];
@@ -342,15 +342,15 @@ class A {
342
342
  }
343
343
  return s;
344
344
  }
345
- calculateNoteYPos = (e) => _(this.params.topLineNote, e) * (10 / 2);
345
+ calculateNoteYPos = (e) => N(this.params.topLineNote, e) * (10 / 2);
346
346
  getKeySignatureYPositions(e, t) {
347
- const s = X[e].slice(0, t), r = L[this.params.staffType][e];
347
+ const s = nt[e].slice(0, t), r = x[this.params.staffType][e];
348
348
  return [s.map(
349
- (o, a) => this.calculateNoteYPos({ name: o, octave: r[a] })
349
+ (o, i) => this.calculateNoteYPos({ name: o, octave: r[i] })
350
350
  )];
351
351
  }
352
352
  }
353
- class U {
353
+ class it {
354
354
  svgRendererInstance;
355
355
  strategyInstance;
356
356
  constructor(e, t) {
@@ -364,9 +364,9 @@ class U {
364
364
  for (let n = 0; n < e.length; n++) {
365
365
  const o = e[n];
366
366
  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 i = Array.from(o.noteGroup.getElementsByTagName("use")).find((c) => c.getAttribute("href")?.includes("ACCIDENTAL"));
368
- if (!i) continue;
369
- i.setAttribute("transform", `translate(${t + 8}, 0)`);
367
+ const a = Array.from(o.noteGroup.getElementsByTagName("use")).find((c) => c.getAttribute("href")?.includes("ACCIDENTAL"));
368
+ if (!a) continue;
369
+ a.setAttribute("transform", `translate(${t + 8}, 0)`);
370
370
  }
371
371
  }
372
372
  return -s;
@@ -375,13 +375,13 @@ class U {
375
375
  let t = e[0], s = 0;
376
376
  for (let r = 1; r < e.length; r++) {
377
377
  const n = e[r];
378
- if (-_(t.noteObj, n.noteObj) === 1) {
378
+ if (-N(t.noteObj, n.noteObj) === 1) {
379
379
  s = 28 / 2, n.noteGroup.setAttribute("transform", `translate(${s}, ${n.noteYPos})`);
380
- const i = Array.from(n.noteGroup.getElementsByTagName("use")).find((c) => c.getAttribute("href")?.includes("ACCIDENTAL"));
381
- if (i) {
382
- const c = i.getAttribute("transform")?.match(/([-]?\d+)/), l = c && c[0];
383
- let f = -s;
384
- l && (f += Number(l)), i.setAttribute("transform", `translate(${f}, 0)`);
380
+ const a = Array.from(n.noteGroup.getElementsByTagName("use")).find((c) => c.getAttribute("href")?.includes("ACCIDENTAL"));
381
+ 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)`);
385
385
  }
386
386
  r++, t = e[r];
387
387
  continue;
@@ -392,7 +392,7 @@ class U {
392
392
  }
393
393
  // Handles drawing the glyphs to internal group, applies the xPositioning to note Cursor X
394
394
  renderNote(e) {
395
- const t = this.svgRendererInstance.createGroup("note"), s = O(e), r = this.strategyInstance.calculateNoteYPos({
395
+ const t = this.svgRendererInstance.createGroup("note"), s = U(e), r = this.strategyInstance.calculateNoteYPos({
396
396
  name: s.name,
397
397
  octave: s.octave
398
398
  });
@@ -428,8 +428,8 @@ class U {
428
428
  this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_FLAT", t), o -= -14;
429
429
  break;
430
430
  }
431
- return this.strategyInstance.getLedgerLinesX(s, r).forEach((i) => {
432
- this.svgRendererInstance.drawLine(i.x1, i.yPos, i.x2, i.yPos, t);
431
+ return this.strategyInstance.getLedgerLinesX(s, r).forEach((a) => {
432
+ this.svgRendererInstance.drawLine(a.x1, a.yPos, a.x2, a.yPos, t);
433
433
  }), {
434
434
  noteGroup: t,
435
435
  noteObj: s,
@@ -441,11 +441,11 @@ class U {
441
441
  renderChord(e) {
442
442
  const t = this.svgRendererInstance.createGroup("chord"), s = [];
443
443
  for (const o of e) {
444
- const a = this.renderNote(o);
445
- a.noteGroup.setAttribute("transform", `translate(0, ${a.noteYPos})`), t.appendChild(a.noteGroup), s.push({
446
- noteGroup: a.noteGroup,
447
- noteObj: a.noteObj,
448
- noteYPos: a.noteYPos,
444
+ const i = this.renderNote(o);
445
+ i.noteGroup.setAttribute("transform", `translate(0, ${i.noteYPos})`), t.appendChild(i.noteGroup), s.push({
446
+ noteGroup: i.noteGroup,
447
+ noteObj: i.noteObj,
448
+ noteYPos: i.noteYPos,
449
449
  cursorOffset: 0,
450
450
  accidentalOffset: 0
451
451
  });
@@ -460,8 +460,8 @@ class U {
460
460
  };
461
461
  }
462
462
  }
463
- const u = "http://www.w3.org/2000/svg", q = 0.1, S = 1200;
464
- class b {
463
+ const A = "http://www.w3.org/2000/svg", mt = 0.1, v = 1200;
464
+ class w {
465
465
  rootElementRef;
466
466
  svgElementRef;
467
467
  // Layers
@@ -479,18 +479,21 @@ class b {
479
479
  // from get rootSvgElement().
480
480
  // HEIGHT and YOfsset should be set externally, values are calculated internally.
481
481
  constructor(e, t) {
482
- this.rootElementRef = e, this.width = t.width, this.scale = t.scale, this.width > S && (this.width = S, console.warn(`Width provided for the staff ${this.width} exceeds the limit ${S}. Please use this value to fix positioning issues.`)), this.svgElementRef = document.createElementNS(u, "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);
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);
483
483
  }
484
484
  // Creates SVG defs for all glyphs in GLYPH_ENTRIES, applies global scale and offsets, appends to root SVG
485
485
  makeGlyphDefs(e) {
486
- const t = document.createElementNS(u, "defs");
487
- Object.entries($).filter(([r]) => e.includes(r)).forEach(([r, n]) => {
488
- const o = document.createElementNS(u, "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(${q})`), t.appendChild(o);
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);
490
490
  }), this.rootSvgElement.appendChild(t);
491
491
  }
492
+ addNamespacedClassesToElement(e, t) {
493
+ [e].flat().forEach((r) => t.classList.add(`vs-${r}`));
494
+ }
492
495
  createGroup(e) {
493
- const t = document.createElementNS(u, "g");
496
+ const t = document.createElementNS(A, "g");
494
497
  return e && t.classList.add(`vs-${e}`), t;
495
498
  }
496
499
  commitElementsToDOM(e, t = this.rootElementRef) {
@@ -514,6 +517,9 @@ class b {
514
517
  addTotalRootSvgHeight(e) {
515
518
  this.totalHeight += e;
516
519
  }
520
+ setTotalRootSvgHeight(e) {
521
+ this.totalHeight = e;
522
+ }
517
523
  addTotalRootSvgYOffset(e) {
518
524
  this.totalYOffset += e;
519
525
  }
@@ -531,12 +537,12 @@ class b {
531
537
  }
532
538
  // Drawing Methods
533
539
  drawLine(e, t, s, r, n) {
534
- const o = document.createElementNS(u, "line");
540
+ const o = document.createElementNS(A, "line");
535
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);
536
542
  }
537
543
  drawRect(e, t, s, r) {
538
- const n = document.createElementNS(u, "rect");
539
- 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"), s.appendChild(n), n;
544
+ const n = document.createElementNS(A, "rect");
545
+ 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;
540
546
  }
541
547
  drawGlyph(e, t, s) {
542
548
  s = {
@@ -544,14 +550,22 @@ class b {
544
550
  yOffset: 0,
545
551
  ...s
546
552
  };
547
- const r = document.createElementNS(u, "use");
553
+ const r = document.createElementNS(A, "use");
548
554
  r.setAttribute("href", `#glyph-${e}`), (s.xOffset || s.yOffset) && r.setAttribute("transform", `translate(${s.xOffset}, ${s.yOffset})`), t.appendChild(r);
549
555
  }
556
+ drawCircle(e, t, s, r, n) {
557
+ const o = document.createElementNS(A, "circle");
558
+ 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
+ }
560
+ 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
+ }
550
564
  destroy() {
551
565
  this.rootElementRef && this.svgElementRef && this.rootElementRef.contains(this.svgElementRef) && this.rootElementRef.removeChild(this.svgElementRef);
552
566
  }
553
567
  }
554
- const j = [
568
+ const Ct = [
555
569
  "CLEF_TREBLE",
556
570
  "CLEF_BASS",
557
571
  "CLEF_ALTO",
@@ -566,7 +580,7 @@ const j = [
566
580
  "ACCIDENTAL_DOUBLE_SHARP",
567
581
  "ACCIDENTAL_DOUBLE_FLAT"
568
582
  ];
569
- class et {
583
+ class bt {
570
584
  svgRendererInstance;
571
585
  strategyInstance;
572
586
  noteRendererInstance;
@@ -591,32 +605,32 @@ class et {
591
605
  staffColor: "black",
592
606
  staffBackgroundColor: "transparent",
593
607
  ...t
594
- }, this.svgRendererInstance = new b(e, {
608
+ }, this.svgRendererInstance = new w(e, {
595
609
  width: this.options.width,
596
610
  height: 100,
597
611
  scale: this.options.scale,
598
612
  staffColor: this.options.staffColor,
599
613
  staffBackgroundColor: this.options.staffBackgroundColor,
600
- useGlyphs: j
614
+ useGlyphs: Ct
601
615
  });
602
616
  const s = this.svgRendererInstance.rootSvgElement;
603
617
  switch (this.options.staffType) {
604
618
  case "grand":
605
- this.strategyInstance = new x(this.svgRendererInstance, "grand");
619
+ this.strategyInstance = new ot(this.svgRendererInstance, "grand");
606
620
  break;
607
621
  case "bass":
608
- this.strategyInstance = new A(this.svgRendererInstance, "bass");
622
+ this.strategyInstance = new m(this.svgRendererInstance, "bass");
609
623
  break;
610
624
  case "treble":
611
- this.strategyInstance = new A(this.svgRendererInstance, "treble");
625
+ this.strategyInstance = new m(this.svgRendererInstance, "treble");
612
626
  break;
613
627
  case "alto":
614
- this.strategyInstance = new A(this.svgRendererInstance, "alto");
628
+ this.strategyInstance = new m(this.svgRendererInstance, "alto");
615
629
  break;
616
630
  default:
617
631
  throw new Error(`The staff type ${this.options.staffType} is not supported. Please use "treble", "bass", "alto", or "grand".`);
618
632
  }
619
- if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new U(this.svgRendererInstance, this.strategyInstance), this.options.spaceAbove) {
633
+ if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new it(this.svgRendererInstance, this.strategyInstance), this.options.spaceAbove) {
620
634
  const n = this.options.spaceAbove * 10;
621
635
  this.svgRendererInstance.addTotalRootSvgYOffset(n);
622
636
  }
@@ -628,7 +642,7 @@ class et {
628
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);
629
643
  }
630
644
  createKeySignature(e) {
631
- return k(this.svgRendererInstance, this.strategyInstance, e, M);
645
+ return At(this.svgRendererInstance, this.strategyInstance, e, Et);
632
646
  }
633
647
  /**
634
648
  * Draws a note on the staff.
@@ -656,8 +670,8 @@ class et {
656
670
  let o;
657
671
  try {
658
672
  o = this.noteRendererInstance.renderNote(n);
659
- } catch (a) {
660
- throw r.length > 0 && this.svgRendererInstance.commitElementsToDOM(r, s), a;
673
+ } catch (i) {
674
+ throw r.length > 0 && this.svgRendererInstance.commitElementsToDOM(r, s), i;
661
675
  }
662
676
  o.noteGroup.setAttribute("transform", `translate(${this.noteCursorX + o.accidentalOffset}, ${o.noteYPos})`), this.noteEntries.push({
663
677
  gElement: o.noteGroup,
@@ -689,7 +703,7 @@ class et {
689
703
  const t = this.svgRendererInstance.getLayerByName("notes"), s = this.noteRendererInstance.renderChord(e);
690
704
  s.noteGroup.setAttribute("transform", `translate(${this.noteCursorX + s.accidentalOffset}, 0)`), this.noteEntries.push({
691
705
  gElement: s.noteGroup,
692
- note: O(e[0]),
706
+ note: U(e[0]),
693
707
  xPos: this.noteCursorX + s.accidentalOffset,
694
708
  yPos: 0,
695
709
  accidentalXOffset: s.accidentalOffset
@@ -704,15 +718,15 @@ class et {
704
718
  if (t <= 0 || e <= 0) return;
705
719
  const s = Math.round(e / t);
706
720
  this.noteEntries.map((n, o) => {
707
- const a = (o + 0.5) * s, i = n.gElement.getBBox(), c = a - i.width / 2 - i.x, l = Math.round(c * 10) / 10;
721
+ const i = (o + 0.5) * s, a = n.gElement.getBBox(), c = i - a.width / 2 - a.x, l = Math.round(c * 10) / 10;
708
722
  return {
709
723
  entry: n,
710
724
  newX: l,
711
725
  isChord: n.gElement.classList.contains("chord")
712
726
  };
713
727
  }).forEach((n) => {
714
- const { entry: o, newX: a, isChord: i } = n;
715
- i ? o.gElement.setAttribute("transform", `translate(${a}, 0)`) : o.gElement.setAttribute("transform", `translate(${a}, ${o.yPos})`), o.xPos = a;
728
+ const { entry: o, newX: i, isChord: a } = n;
729
+ a ? o.gElement.setAttribute("transform", `translate(${i}, 0)`) : o.gElement.setAttribute("transform", `translate(${i}, ${o.yPos})`), o.xPos = i;
716
730
  });
717
731
  }
718
732
  /**
@@ -771,7 +785,7 @@ class et {
771
785
  const s = this.noteEntries[t], r = this.noteRendererInstance.renderChord(e), o = s.xPos - s.accidentalXOffset + r.accidentalOffset;
772
786
  r.noteGroup.setAttribute("transform", `translate(${o}, 0)`), this.svgRendererInstance.getLayerByName("notes").replaceChild(r.noteGroup, s.gElement), this.noteEntries[t] = {
773
787
  gElement: r.noteGroup,
774
- note: O(e[0]),
788
+ note: U(e[0]),
775
789
  xPos: o,
776
790
  yPos: 0,
777
791
  accidentalXOffset: r.accidentalOffset
@@ -807,7 +821,7 @@ class et {
807
821
  this.noteEntries = [], this.svgRendererInstance.destroy();
808
822
  }
809
823
  }
810
- const d = 30, H = 19, g = 12, K = 4, Q = 6, P = 1, m = 38, z = [
824
+ const I = 30, J = 19, F = 12, St = 4, Nt = 6, tt = 1, D = 38, Lt = [
811
825
  "TIME_4",
812
826
  "TIME_3",
813
827
  "NOTE_HEAD_WHOLE",
@@ -819,7 +833,7 @@ const d = 30, H = 19, g = 12, K = 4, Q = 6, P = 1, m = 38, z = [
819
833
  "REST_QUARTER",
820
834
  "REST_EIGHTH"
821
835
  ];
822
- class st {
836
+ class Gt {
823
837
  rendererInstance;
824
838
  options;
825
839
  barSpacing;
@@ -830,7 +844,7 @@ class st {
830
844
  currentBeatCount = 0;
831
845
  currentBeatUICount = 0;
832
846
  currentBeatUIElement = null;
833
- currentBeatUIXPos = m;
847
+ currentBeatUIXPos = D;
834
848
  /**
835
849
  * Creates an instance of a RhythmStaff, A single staff that will automatically apply positioning of elements based on the duration of a note.
836
850
  *
@@ -850,13 +864,13 @@ class st {
850
864
  staffBackgroundColor: "white",
851
865
  currentBeatUIColor: "#24ff7450",
852
866
  ...t
853
- }, this.rendererInstance = new b(e, {
867
+ }, this.rendererInstance = new w(e, {
854
868
  width: this.options.width,
855
869
  height: 100,
856
870
  scale: this.options.scale,
857
871
  staffColor: this.options.staffColor,
858
872
  staffBackgroundColor: this.options.staffBackgroundColor,
859
- useGlyphs: z
873
+ useGlyphs: Lt
860
874
  });
861
875
  const s = this.rendererInstance.rootSvgElement;
862
876
  let r = "TIME_4";
@@ -872,41 +886,41 @@ class st {
872
886
  }
873
887
  if (this.options.barsCount < 1 || this.options.barsCount > 3) throw new Error(`Bars count ${this.options.barsCount} not supported. Please use 1 - 3`);
874
888
  if (this.options.spaceAbove) {
875
- const p = this.options.spaceAbove * 10;
876
- this.rendererInstance.addTotalRootSvgYOffset(p);
889
+ const f = this.options.spaceAbove * 10;
890
+ this.rendererInstance.addTotalRootSvgYOffset(f);
877
891
  }
878
892
  if (this.options.spaceBelow) {
879
- let p = this.options.spaceBelow * 10;
880
- this.rendererInstance.addTotalRootSvgHeight(p);
893
+ let f = this.options.spaceBelow * 10;
894
+ this.rendererInstance.addTotalRootSvgHeight(f);
881
895
  }
882
896
  const n = this.rendererInstance.getLayerByName("staff");
883
- this.rendererInstance.addTotalRootSvgHeight(d * 2);
897
+ this.rendererInstance.addTotalRootSvgHeight(I * 2);
884
898
  const o = this.rendererInstance.createGroup("time-signature");
885
899
  n.appendChild(o);
886
- const a = d - H;
887
- this.rendererInstance.drawGlyph(r, o), this.rendererInstance.drawGlyph("TIME_4", o, { yOffset: H }), o.setAttribute("transform", `translate(0, ${a})`);
888
- let i = this.options.width - 38;
889
- this.options.barsCount > 1 && (i -= (this.options.barsCount - 1) * g), i -= P, this.rendererInstance.drawLine(0, d, this.options.width - P, d, n), this.barSpacing = i / this.options.barsCount, this.quarterNoteSpacing = Math.round(this.barSpacing / this.options.topNumber), this.maxBeatCount = this.options.barsCount * this.options.topNumber;
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;
890
904
  let c = this.barSpacing + 38;
891
- const l = d / 2, f = d + l;
892
- for (let p = 0; p < this.options.barsCount - 1; p++)
893
- this.rendererInstance.drawLine(c, l, c, f, n), c += this.barSpacing;
894
- this.rendererInstance.getLayerByName("notes").setAttribute("transform", `translate(38, ${d})`), this.rendererInstance.applySizingToRootSvg(), this.rendererInstance.commitElementsToDOM(s);
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);
895
909
  }
896
910
  createBeatUIElement() {
897
911
  const e = this.rendererInstance.getLayerByName("ui");
898
912
  this.currentBeatUIElement = this.rendererInstance.drawRect(
899
913
  this.quarterNoteSpacing / 2,
900
- d * 2,
914
+ I * 2,
901
915
  e,
902
916
  {
903
- x: m,
917
+ x: D,
904
918
  fill: this.options.currentBeatUIColor
905
919
  }
906
920
  );
907
921
  }
908
922
  handleNewBar() {
909
- this.noteCursorX += g;
923
+ this.noteCursorX += F;
910
924
  }
911
925
  // Translates group, returns cursor increment amount
912
926
  translateGroupByDuration(e, t) {
@@ -966,14 +980,14 @@ class st {
966
980
  for (; s > 0; ) {
967
981
  const r = this.rendererInstance.createGroup("rest");
968
982
  let n = 0;
969
- s - E.h >= 0 ? (this.rendererInstance.drawGlyph("REST_HALF", r), n = E.h) : s - E.q >= 0 ? (this.rendererInstance.drawGlyph("REST_QUARTER", r), n = E.q) : (this.rendererInstance.drawGlyph("REST_EIGHTH", r), n = E.e), s -= n, this.currentBeatCount += n, r.setAttribute("transform", `translate(${this.noteCursorX}, 0)`), this.noteCursorX += n * this.quarterNoteSpacing, t.push(r);
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);
970
984
  }
971
985
  return t;
972
986
  }
973
987
  renderBeamRect(e, t, s, r) {
974
988
  this.rendererInstance.drawRect(
975
989
  e - t,
976
- K,
990
+ St,
977
991
  s,
978
992
  {
979
993
  x: 10,
@@ -1005,20 +1019,20 @@ class st {
1005
1019
  for (const n of t) {
1006
1020
  let o = "w";
1007
1021
  try {
1008
- o = N(n);
1009
- } catch (f) {
1010
- throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), f;
1022
+ o = b(n);
1023
+ } catch (d) {
1024
+ throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), d;
1011
1025
  }
1012
- const a = E[o];
1026
+ const i = p[o];
1013
1027
  if (this.currentBeatCount >= this.maxBeatCount)
1014
1028
  throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), new Error("Max beat count reached. Can't add additional notes.");
1015
1029
  this.checkAndCreateNewBar();
1016
- const i = this.checkAndFillBarWithRests(a);
1017
- i && i.forEach((f) => {
1018
- r.push(f), this.noteEntries.push(f);
1030
+ const a = this.checkAndFillBarWithRests(i);
1031
+ a && a.forEach((d) => {
1032
+ r.push(d), this.noteEntries.push(d);
1019
1033
  });
1020
- const c = this.rendererInstance.createGroup("note"), l = this.translateGroupByDuration(a, c);
1021
- this.noteCursorX += l, this.currentBeatCount += a, this.renderNote(o, c), r.push(c), this.noteEntries.push(c);
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);
1022
1036
  }
1023
1037
  this.rendererInstance.commitElementsToDOM(r, s);
1024
1038
  }
@@ -1045,18 +1059,18 @@ class st {
1045
1059
  for (const n of t) {
1046
1060
  let o = "w";
1047
1061
  try {
1048
- o = N(n);
1049
- } catch (f) {
1050
- throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), f;
1062
+ o = b(n);
1063
+ } catch (d) {
1064
+ throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), d;
1051
1065
  }
1052
- const a = this.rendererInstance.createGroup("rest"), i = E[o], c = i * this.quarterNoteSpacing;
1066
+ const i = this.rendererInstance.createGroup("rest"), a = p[o], c = a * this.quarterNoteSpacing;
1053
1067
  if (this.currentBeatCount >= this.maxBeatCount)
1054
1068
  throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), new Error("Max beat count reached. Can't add additional notes.");
1055
1069
  this.checkAndCreateNewBar();
1056
- const l = this.checkAndFillBarWithRests(i);
1057
- l && l.forEach((f) => {
1058
- r.push(f), this.noteEntries.push(f);
1059
- }), this.renderRest(o, a), a.setAttribute("transform", `translate(${this.noteCursorX}, 0)`), this.noteCursorX += c, this.currentBeatCount += i, r.push(a), this.noteEntries.push(a);
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);
1060
1074
  }
1061
1075
  this.rendererInstance.commitElementsToDOM(r, s);
1062
1076
  }
@@ -1083,13 +1097,13 @@ class st {
1083
1097
  if (this.currentBeatCount >= this.maxBeatCount)
1084
1098
  throw new Error("Max beat count reached. Can't add additional beamed note.");
1085
1099
  let s = "s";
1086
- e === "s" ? s = "s" : s = N(e), this.checkAndCreateNewBar();
1087
- const r = this.rendererInstance.getLayerByName("notes"), n = E[s], o = n * this.quarterNoteSpacing, a = this.options.topNumber - this.currentBeatCount % this.options.topNumber, i = Math.min(t, a / n), c = this.rendererInstance.createGroup("beamed-note");
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");
1088
1102
  c.setAttribute("transform", `translate(${this.noteCursorX}, 0)`);
1089
1103
  let l = 0;
1090
- for (let f = 0; f < i; f++)
1104
+ for (let d = 0; d < a; d++)
1091
1105
  this.rendererInstance.drawGlyph("NOTE_HEAD_QUARTER", c, { xOffset: l }), this.drawStem(c, l), l += o, this.currentBeatCount += n;
1092
- this.renderBeamRect(l, o, c), e === "s" && this.renderBeamRect(l, o, c, Q), this.noteCursorX += l, this.noteEntries.push(c), this.rendererInstance.commitElementsToDOM(c, r);
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);
1093
1107
  }
1094
1108
  /**
1095
1109
  * Will increment the UI showing the current beat in quarters. Once exceeded, must be reset with `resetCurrentBeatUI()`
@@ -1100,14 +1114,14 @@ class st {
1100
1114
  this.currentBeatUIElement.setAttribute("display", "none");
1101
1115
  return;
1102
1116
  }
1103
- this.currentBeatUIElement?.getAttribute("display") === "none" && this.currentBeatUIElement.removeAttribute("display"), this.currentBeatUICount++, this.currentBeatUICount > this.options.topNumber && this.currentBeatUICount % this.options.topNumber === 1 && (this.currentBeatUIXPos += g), this.currentBeatUICount > 1 && (this.currentBeatUIXPos += this.quarterNoteSpacing), this.currentBeatUIElement.setAttribute("x", this.currentBeatUIXPos.toString());
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());
1104
1118
  }
1105
1119
  /**
1106
1120
  * Resets the ui showing the current beat value.
1107
1121
  * @returns void
1108
1122
  */
1109
1123
  resetCurrentBeatUI() {
1110
- this.currentBeatUICount = 0, this.currentBeatUIXPos = m, this.currentBeatUIElement && (this.currentBeatUIElement.setAttribute("display", "none"), this.currentBeatUIElement.setAttribute("x", this.currentBeatUIXPos.toString()));
1124
+ this.currentBeatUICount = 0, this.currentBeatUIXPos = D, this.currentBeatUIElement && (this.currentBeatUIElement.setAttribute("display", "none"), this.currentBeatUIElement.setAttribute("x", this.currentBeatUIXPos.toString()));
1111
1125
  }
1112
1126
  /**
1113
1127
  * Clears staff of notes and resets internal positioning.
@@ -1124,7 +1138,7 @@ class st {
1124
1138
  this.noteEntries = [], this.rendererInstance.destroy();
1125
1139
  }
1126
1140
  }
1127
- const J = [
1141
+ const Rt = [
1128
1142
  "CLEF_TREBLE",
1129
1143
  "CLEF_BASS",
1130
1144
  "CLEF_ALTO",
@@ -1138,8 +1152,8 @@ const J = [
1138
1152
  "ACCIDENTAL_NATURAL",
1139
1153
  "ACCIDENTAL_DOUBLE_SHARP",
1140
1154
  "ACCIDENTAL_DOUBLE_FLAT"
1141
- ], T = 60, tt = T;
1142
- class rt {
1155
+ ], y = 60, yt = y;
1156
+ class vt {
1143
1157
  svgRendererInstance;
1144
1158
  strategyInstance;
1145
1159
  noteRendererInstance;
@@ -1166,32 +1180,32 @@ class rt {
1166
1180
  staffColor: "black",
1167
1181
  staffBackgroundColor: "transparent",
1168
1182
  ...t
1169
- }, this.svgRendererInstance = new b(e, {
1183
+ }, this.svgRendererInstance = new w(e, {
1170
1184
  width: this.options.width,
1171
1185
  height: 100,
1172
1186
  scale: this.options.scale,
1173
1187
  staffColor: this.options.staffColor,
1174
1188
  staffBackgroundColor: this.options.staffBackgroundColor,
1175
- useGlyphs: J
1189
+ useGlyphs: Rt
1176
1190
  });
1177
1191
  const s = this.svgRendererInstance.rootSvgElement;
1178
1192
  switch (this.options.staffType) {
1179
1193
  case "grand":
1180
- this.strategyInstance = new x(this.svgRendererInstance, "grand");
1194
+ this.strategyInstance = new ot(this.svgRendererInstance, "grand");
1181
1195
  break;
1182
1196
  case "bass":
1183
- this.strategyInstance = new A(this.svgRendererInstance, "bass");
1197
+ this.strategyInstance = new m(this.svgRendererInstance, "bass");
1184
1198
  break;
1185
1199
  case "treble":
1186
- this.strategyInstance = new A(this.svgRendererInstance, "treble");
1200
+ this.strategyInstance = new m(this.svgRendererInstance, "treble");
1187
1201
  break;
1188
1202
  case "alto":
1189
- this.strategyInstance = new A(this.svgRendererInstance, "alto");
1203
+ this.strategyInstance = new m(this.svgRendererInstance, "alto");
1190
1204
  break;
1191
1205
  default:
1192
1206
  throw new Error(`The staff type ${this.options.staffType} is not supported. Please use "treble", "bass", "alto", or "grand".`);
1193
1207
  }
1194
- if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new U(this.svgRendererInstance, this.strategyInstance), this.options.spaceAbove) {
1208
+ if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new it(this.svgRendererInstance, this.strategyInstance), this.options.spaceAbove) {
1195
1209
  const r = this.options.spaceAbove * 10;
1196
1210
  this.svgRendererInstance.addTotalRootSvgYOffset(r);
1197
1211
  }
@@ -1202,10 +1216,10 @@ class rt {
1202
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);
1203
1217
  }
1204
1218
  renderFirstNoteGroups() {
1205
- const e = this.options.width - this.options.noteStartX + tt;
1219
+ const e = this.options.width - this.options.noteStartX + yt;
1206
1220
  for (; this.noteBuffer.length > 0 && this.noteCursorX < e; )
1207
- this.renderNextNote(), this.noteCursorX += T;
1208
- this.activeEntries.length > 1 && (this.noteCursorX -= T);
1221
+ this.renderNextNote(), this.noteCursorX += y;
1222
+ this.activeEntries.length > 1 && (this.noteCursorX -= y);
1209
1223
  }
1210
1224
  renderNextNote() {
1211
1225
  if (this.noteBuffer.length < 1) return;
@@ -1264,7 +1278,7 @@ class rt {
1264
1278
  return;
1265
1279
  }
1266
1280
  this.activeEntries.forEach((t) => {
1267
- t.xPos -= T, t.noteWrapper.style.transform = `translate(${t.xPos}px, 0px)`;
1281
+ t.xPos -= y, t.noteWrapper.style.transform = `translate(${t.xPos}px, 0px)`;
1268
1282
  });
1269
1283
  const e = this.activeEntries[0];
1270
1284
  e.xPos <= 0 && (this.notesLayer.removeChild(e.noteWrapper), this.activeEntries.shift()), this.renderNextNote();
@@ -1284,8 +1298,321 @@ class rt {
1284
1298
  this.svgRendererInstance.destroy(), this.activeEntries = [], this.noteBuffer = [];
1285
1299
  }
1286
1300
  }
1301
+ const wt = /^[xX\da-zA-Z]+$/, Ot = /^[\d]+$/;
1302
+ function et(h, e) {
1303
+ const t = [];
1304
+ for (let s = 0; s < h.length; s++)
1305
+ t.push({
1306
+ fret: h[s],
1307
+ finger: e[s]
1308
+ });
1309
+ return t;
1310
+ }
1311
+ function st(h, e) {
1312
+ const t = h.filter((n) => n.toLowerCase() !== "x" && n !== "0").map((n) => parseInt(n, 36));
1313
+ if (t.length === 0) return 1;
1314
+ const s = Math.min(...t);
1315
+ return Math.max(...t) <= e ? 1 : s;
1316
+ }
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("");
1320
+ }
1321
+ function B(h) {
1322
+ if (!Ot.test(h)) throw new Error("Invalid fingers string. Only digits are allowed.");
1323
+ return h.split("");
1324
+ }
1325
+ class Ft {
1326
+ svgRendererInstance;
1327
+ options;
1328
+ chordEntries = [];
1329
+ cursorX = 0;
1330
+ cursorY = 0;
1331
+ diagramWidth;
1332
+ diagramHeight;
1333
+ gridTopY;
1334
+ rowHeight;
1335
+ /**
1336
+ * Creates an instance of a GuitarChord diagram renderer.
1337
+ *
1338
+ * @param rootElementCtx - The element (div) reference that the chord diagram(s) will be appended to.
1339
+ * @param options - Optional configuration. Can adjust total width, scale, string/fret count, and coloring.
1340
+ * All config options are in the type GuitarChordOptions.
1341
+ */
1342
+ constructor(e, t) {
1343
+ if (this.options = {
1344
+ stringCount: at,
1345
+ fretCount: ct,
1346
+ stringLabels: [],
1347
+ inlineChordsAmount: 2,
1348
+ scale: 1,
1349
+ color: "black",
1350
+ backgroundColor: "transparent",
1351
+ ...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)
1353
+ 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, {
1355
+ width: this.options.width,
1356
+ height: 100,
1357
+ scale: this.options.scale,
1358
+ staffColor: this.options.color,
1359
+ staffBackgroundColor: this.options.backgroundColor,
1360
+ useGlyphs: []
1361
+ });
1362
+ const s = this.svgRendererInstance.rootSvgElement;
1363
+ this.svgRendererInstance.setTotalRootSvgHeight(this.rowHeight), this.svgRendererInstance.applySizingToRootSvg(), this.svgRendererInstance.commitElementsToDOM(s);
1364
+ }
1365
+ getDotsToHide(e) {
1366
+ const t = /* @__PURE__ */ new Set();
1367
+ return e && e.forEach((s) => {
1368
+ const r = s.fromString - 1, n = s.toString - 1;
1369
+ for (let o = r; o <= n; o++)
1370
+ t.add(`${o}-${s.fret}`);
1371
+ }), t;
1372
+ }
1373
+ drawFretDots(e, t, s, r, n) {
1374
+ const o = this.gridTopY - W / 2;
1375
+ 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 });
1381
+ else {
1382
+ const d = parseInt(c, 36);
1383
+ if (r.has(`${i}-${d}`))
1384
+ 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
+ }
1399
+ }
1400
+ }
1401
+ }
1402
+ drawStringLabels(e, t) {
1403
+ if (!t || t.length === 0) return;
1404
+ const s = u, r = this.rowHeight - s - $;
1405
+ for (let n = 0; n < this.options.stringCount; n++) {
1406
+ const o = t[n];
1407
+ 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"
1412
+ });
1413
+ }
1414
+ }
1415
+ // Passed in 'from' and 'to' index values are zero-based
1416
+ drawBarre(e, t) {
1417
+ const s = t.fret;
1418
+ if (t.fromIndex < 0 || t.toIndex >= this.options.stringCount || t.fromIndex >= t.toIndex)
1419
+ throw new Error(`Barre fret error: Invalid string range ${t.fromIndex + 1}:${t.toIndex + 1}.`);
1420
+ if (s < t.startingFret || s > t.startingFret + (this.options.fretCount - 1))
1421
+ 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,
1426
+ rx: u,
1427
+ 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
+ }
1436
+ }
1437
+ // Builds a single chord diagram's group element: grid, nut/fret-position label, and per-string markers.
1438
+ renderChordDiagram(e, t, s) {
1439
+ 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,
1442
+ 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, {
1453
+ anchor: "start",
1454
+ fontSize: S,
1455
+ fontWeight: "bold",
1456
+ classes: "guitar-text-small"
1457
+ });
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);
1461
+ }
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,
1469
+ startingFret: n
1470
+ });
1471
+ }), r;
1472
+ }
1473
+ // 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.
1475
+ 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;
1482
+ });
1483
+ const e = this.cursorY + this.rowHeight;
1484
+ this.svgRendererInstance.setTotalRootSvgHeight(e), this.svgRendererInstance.applySizingToRootSvg();
1485
+ }
1486
+ /**
1487
+ * Adds a new chord diagram. Diagrams are placed left-to-right in the order added, wrapping to a
1488
+ * new row automatically once the configured width is exceeded.
1489
+ *
1490
+ * @param frets - A string, with each value being ordered low-to-high (e.g. first position in string 0 is the low E string)
1491
+ * * `x` - muted string
1492
+ * * `0` - open string
1493
+ * * `1...n` - fretted at the given absolute fret number (e.g. `3`)
1494
+ * @param fingers - A string, with each value being ordered low-to-high (e.g. first position in string 0 is the low E string)
1495
+ * * `0` - No finger labeled
1496
+ * * `1...n` - Finger labeled as number provided
1497
+ *
1498
+ * @param options - Optional per-chord settings: `startFret` (default `1`, for diagrams higher up the neck)
1499
+ * and `label` (a chord name drawn above the diagram).
1500
+ *
1501
+ * @returns The index of the newly added chord, for later use with the CRUD-by-index methods.
1502
+ *
1503
+ * @throws {Error} If fret or finger's string length doesn't match the configured string count.
1504
+ *
1505
+ * @example
1506
+ * // Draw an open C major chord
1507
+ * guitarChord.addChord("x32010", "032010", { label: "C" });
1508
+ */
1509
+ addChord(e, t, s) {
1510
+ const r = H(e), n = B(t);
1511
+ 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
+ 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,
1518
+ xPos: 0,
1519
+ yPos: 0
1520
+ }), this.relayoutChords(), this.chordEntries.length - 1;
1521
+ }
1522
+ /**
1523
+ * Replaces the chord diagram at the specified index with a new one, in place.
1524
+ *
1525
+ * @param frets - A string, with each value being ordered low-to-high (e.g. first position in string 0 is the low E string)
1526
+ * * `x` - muted string
1527
+ * * `0` - open string
1528
+ * * `1...n` - fretted at the given absolute fret number (e.g. `3`)
1529
+ * @param fingers - A string, with each value being ordered low-to-high (e.g. first position in string 0 is the low E string)
1530
+ * * `0` - No finger labeled
1531
+ * * `1...n` - Finger labeled as number provided
1532
+ *
1533
+ * @param chordIndex - The index of the chord to replace (as returned by addChord).
1534
+ *
1535
+ * @param options - Optional per-chord settings, see addChord.
1536
+ *
1537
+ * @returns void
1538
+ *
1539
+ * @throws {Error} If the index is out of bounds, or if chordDef is invalid (see addChord).
1540
+ *
1541
+ * @example
1542
+ * // Change chord at index 0 to a D major chord
1543
+ * guitarChord.modifyChordByIndex("xx0232", "000132", 0, { label: "D" });
1544
+ *
1545
+ */
1546
+ modifyChordByIndex(e, t, s, r) {
1547
+ if (s >= this.chordEntries.length || s < 0) throw new Error("Chord index was out of bounds.");
1548
+ const n = H(e), o = B(t);
1549
+ 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
+ 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,
1556
+ xPos: i.xPos,
1557
+ yPos: i.yPos
1558
+ }, this.relayoutChords();
1559
+ }
1560
+ /**
1561
+ * Removes the chord diagram at the specified index. Remaining chords are re-flowed to close the gap.
1562
+ * @param chordIndex - The index of the chord to remove.
1563
+ * @returns void
1564
+ * @throws {Error} If the index is out of bounds.
1565
+ */
1566
+ removeChordByIndex(e) {
1567
+ if (e >= this.chordEntries.length || e < 0) throw new Error("Chord index was out of bounds.");
1568
+ this.chordEntries[e].gElement.remove(), this.chordEntries.splice(e, 1), this.relayoutChords();
1569
+ }
1570
+ /**
1571
+ * Removes all chord diagrams and resets internal positioning.
1572
+ * @returns void
1573
+ */
1574
+ clearAllChords() {
1575
+ this.svgRendererInstance.getLayerByName("notes").replaceChildren(), this.chordEntries = [], this.cursorX = 0, this.cursorY = 0, this.svgRendererInstance.setTotalRootSvgHeight(this.rowHeight), this.svgRendererInstance.applySizingToRootSvg();
1576
+ }
1577
+ /**
1578
+ * * Used to automatically determine options for creating barre lines.
1579
+ * * The returned value then can be used in addChord and modifyChord methods.
1580
+ * @returns GuitarBarreDef[]
1581
+ */
1582
+ determineBarreOptions(e, t, s) {
1583
+ const r = H(e), n = B(t), o = [];
1584
+ return s.forEach((i) => {
1585
+ 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));
1591
+ }
1592
+ 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({
1598
+ fret: i,
1599
+ fromString: f,
1600
+ toString: C,
1601
+ finger: l
1602
+ });
1603
+ }), o;
1604
+ }
1605
+ /**
1606
+ * Removes the root svg element and cleans up arrays.
1607
+ * @returns void
1608
+ */
1609
+ destroy() {
1610
+ this.chordEntries = [], this.svgRendererInstance.destroy();
1611
+ }
1612
+ }
1287
1613
  export {
1288
- et as MusicStaff,
1289
- st as RhythmStaff,
1290
- rt as ScrollingStaff
1614
+ Ft as GuitarChord,
1615
+ bt as MusicStaff,
1616
+ Gt as RhythmStaff,
1617
+ vt as ScrollingStaff
1291
1618
  };