vector-score 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- const S = {
1
+ const w = {
2
2
  treble: {
3
3
  staffType: "treble",
4
4
  paddingTop: 13,
@@ -31,16 +31,16 @@ const S = {
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
- }, st = 6, rt = 5, I = 22, T = 30, E = 10, f = 6, nt = 4, ot = E * 2, it = 40, at = 16, X = 1, F = 4, U = 1, Y = f * 2 + F + 4, D = 16, C = 14, ct = 14, M = D, ht = E + 2, $ = 8, lt = 40, J = {
40
+ }, it = 6, at = 5, T = 22, m = 30, u = 10, p = 6, ct = 4, ht = u * 2, L = 51, lt = 12, dt = 4, $ = 1, x = 4, ft = 1, W = p * 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
- }, k = {
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 S = {
54
54
  Ab: { type: "flat", count: 4 },
55
55
  Db: { type: "flat", count: 5 },
56
56
  Gb: { type: "flat", count: 6 }
57
- }, B = {
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 S = {
75
75
  },
76
76
  grand: { sharp: [], flat: [] }
77
77
  };
78
- function dt(h) {
79
- const e = k[h];
80
- if (!e) throw new Error(`Unknown key signature "${h}". Valid keys: ${Object.keys(k).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 ft(h, e, t, s) {
84
- const r = dt(t);
83
+ function At(l, e, t, s) {
84
+ const r = gt(t);
85
85
  if (r.count === 0) return 0;
86
- const o = r.type === "sharp" ? "ACCIDENTAL_SHARP" : "ACCIDENTAL_FLAT", n = 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(o, n, { xOffset: s + l * $, yOffset: c });
89
+ a.forEach((h, d) => {
90
+ l.drawGlyph(n, o, { xOffset: s + d * Z, yOffset: h });
90
91
  });
91
- }), r.count * $;
92
+ }), r.count * Z;
92
93
  }
93
- const Et = {
94
+ const pt = {
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,28 +187,28 @@ const Et = {
186
187
  xOffset: 0,
187
188
  yOffset: 0
188
189
  }
189
- }, ut = /^(?<name>[A-Ga-g])(?<accidental>##|bb|[#bn]?)(?<octave>\d)(?<duration>[whqeWHQE]?)$/, gt = /^[whqeWHQE]$/, H = ["C", "D", "E", "F", "G", "A", "B"];
190
- function P(h) {
191
- const e = h.match(ut);
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
- let { name: t, accidental: s, octave: r, duration: o } = e.groups;
195
- t = t.toUpperCase(), o = o.toLowerCase(), o || (o = "w");
196
- const n = {
194
+ throw new Error(`Invalid note string format: ${l}. Expected format: [A-Ga-g][#|b]?[0-9][w|h|q|e].`);
195
+ let { name: t, accidental: s, octave: r, duration: n } = e.groups;
196
+ t = t.toUpperCase(), n = n.toLowerCase(), n || (n = "w");
197
+ const o = {
197
198
  name: t,
198
199
  octave: parseInt(r),
199
- duration: o
200
+ duration: n
200
201
  };
201
- return s && (n.accidental = s), n;
202
+ return s && (o.accidental = s), o;
202
203
  }
203
- function R(h) {
204
- const e = h.match(gt);
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 x(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 x(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 W(h) {
225
- let e = H.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 m(h, e) {
229
- return H.indexOf(h.name) - H.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 y = 48, Z = 40 + 30 / 2, V = 20, q = 90;
232
- class tt {
232
+ const F = 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 = S[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,109 +249,109 @@ class tt {
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
- let o = r, n = 1;
255
- const i = x("treble"), a = x("bass");
256
- this.rendererRef.drawGlyph(i, t), this.rendererRef.drawGlyph(a, t, { yOffset: s + 30 }), o += this.params.paddingBottom + 1, n += this.params.paddingTop, this.rendererRef.addTotalRootSvgHeight(o), this.rendererRef.addTotalRootSvgYOffset(n);
255
+ let n = r, o = 1;
256
+ const i = M("treble"), a = M("bass");
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 - V);
260
- return e === Z ? !1 : t <= s ? !(e >= q) : e <= V;
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
- const s = [], r = W(e);
264
- let o = e.duration === "w" ? 17 : 12.5;
265
- if (r === y)
266
- return s.push({ x1: -2, x2: o, yPos: 0 }), s;
264
+ const s = [], r = z(e);
265
+ let n = e.duration === "w" ? 17 : 12.5;
266
+ if (r === F)
267
+ return s.push({ x1: -2, x2: n, yPos: 0 }), s;
267
268
  if (t < this.params.topLineYPos) {
268
- let n = this.params.topLineYPos - 10;
269
- for (; n >= t; )
269
+ let o = this.params.topLineYPos - 10;
270
+ for (; o >= t; )
270
271
  s.push({
271
272
  x1: -2,
272
- x2: o,
273
- yPos: n - t
274
- }), n -= 10;
273
+ x2: n,
274
+ yPos: o - t
275
+ }), o -= 10;
275
276
  } else if (t > this.params.bottomLineYPos) {
276
- let n = this.params.bottomLineYPos + 10;
277
- for (; n <= t; )
277
+ let o = this.params.bottomLineYPos + 10;
278
+ for (; o <= t; )
278
279
  s.push({
279
280
  x1: -2,
280
- x2: o,
281
- yPos: n - t
282
- }), n += 10;
281
+ x2: n,
282
+ yPos: o - t
283
+ }), o += 10;
283
284
  }
284
285
  return s;
285
286
  }
286
287
  calculateNoteYPos = (e) => {
287
- let s = m(this.params.topLineNote, e) * (10 / 2);
288
- const r = W(e);
289
- return r < y ? s += 10 : r === y && (s = Z), s;
288
+ let s = C(this.params.topLineNote, e) * (10 / 2);
289
+ const r = z(e);
290
+ return r < F ? s += 10 : r === F && (s = q), s;
290
291
  };
291
292
  getKeySignatureYPositions(e, t) {
292
- const s = J[e].slice(0, t), r = B.treble[e], o = B.bass[e], n = s.map(
293
- (a, c) => m(S.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) => m(S.bass.topLineNote, { name: a, octave: o[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
- return [n, i];
298
+ return [o, i];
298
299
  }
299
300
  }
300
- const pt = 20;
301
- class _ {
301
+ const Tt = 20;
302
+ class S {
302
303
  params;
303
304
  rendererRef;
304
305
  constructor(e, t) {
305
306
  this.rendererRef = e;
306
- const s = S[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
- let r = s - 10 + 1, o = 1;
317
- const n = x(this.params.staffType);
318
- this.rendererRef.drawGlyph(n, t), r += this.params.paddingTop + this.params.paddingBottom, o += this.params.paddingTop, this.rendererRef.addTotalRootSvgHeight(r), this.rendererRef.addTotalRootSvgYOffset(o);
317
+ let r = s - 10 + 1, n = 1;
318
+ const o = M(this.params.staffType);
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) {
321
- return e <= pt;
322
+ return e <= Tt;
322
323
  }
323
324
  getLedgerLinesX(e, t) {
324
325
  const s = [];
325
326
  let r = e.duration === "w" ? 17 : 12.5;
326
327
  if (t < this.params.topLineYPos) {
327
- let o = this.params.topLineYPos - 10;
328
- for (; o >= t; )
328
+ let n = this.params.topLineYPos - 10;
329
+ for (; n >= t; )
329
330
  s.push({
330
331
  x1: -2,
331
332
  x2: r,
332
- yPos: o - t
333
- }), o -= 10;
333
+ yPos: n - t
334
+ }), n -= 10;
334
335
  } else if (t > this.params.bottomLineYPos) {
335
- let o = this.params.bottomLineYPos + 10;
336
- for (; o <= t; )
336
+ let n = this.params.bottomLineYPos + 10;
337
+ for (; n <= t; )
337
338
  s.push({
338
339
  x1: -2,
339
340
  x2: r,
340
- yPos: o - t
341
- }), o += 10;
341
+ yPos: n - t
342
+ }), n += 10;
342
343
  }
343
344
  return s;
344
345
  }
345
- calculateNoteYPos = (e) => m(this.params.topLineNote, e) * (10 / 2);
346
+ calculateNoteYPos = (e) => C(this.params.topLineNote, e) * (10 / 2);
346
347
  getKeySignatureYPositions(e, t) {
347
- const s = J[e].slice(0, t), r = B[this.params.staffType][e];
348
+ const s = rt[e].slice(0, t), r = X[this.params.staffType][e];
348
349
  return [s.map(
349
- (n, i) => this.calculateNoteYPos({ name: n, octave: r[i] })
350
+ (o, i) => this.calculateNoteYPos({ name: o, octave: r[i] })
350
351
  )];
351
352
  }
352
353
  }
353
- class et {
354
+ class ot {
354
355
  svgRendererInstance;
355
356
  strategyInstance;
356
357
  constructor(e, t) {
@@ -361,10 +362,10 @@ class et {
361
362
  }
362
363
  chordOffsetConsecutiveAccidentals(e) {
363
364
  let t = 0, s = 0, r = 0;
364
- for (let o = 0; o < e.length; o++) {
365
- const n = e[o];
366
- if (n.noteObj.accidental && r < 3 ? (t += -8, s = Math.min(s, t), r++) : n.noteObj.accidental && r <= 3 ? (t = -8, r = 1) : (t = 0, r = 0), t !== 0) {
367
- const a = Array.from(n.noteGroup.getElementsByTagName("use")).find((c) => c.getAttribute("href")?.includes("ACCIDENTAL"));
365
+ for (let n = 0; n < e.length; n++) {
366
+ const o = e[n];
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) {
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
  }
@@ -374,58 +375,58 @@ class et {
374
375
  chordOffsetCloseNotes(e) {
375
376
  let t = e[0], s = 0;
376
377
  for (let r = 1; r < e.length; r++) {
377
- const o = e[r];
378
- if (-m(t.noteObj, o.noteObj) === 1) {
379
- s = 28 / 2, o.noteGroup.setAttribute("transform", `translate(${s}, ${o.noteYPos})`);
380
- const a = Array.from(o.noteGroup.getElementsByTagName("use")).find((c) => c.getAttribute("href")?.includes("ACCIDENTAL"));
378
+ const n = e[r];
379
+ if (-C(t.noteObj, n.noteObj) === 1) {
380
+ s = 28 / 2, n.noteGroup.setAttribute("transform", `translate(${s}, ${n.noteYPos})`);
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;
388
389
  }
389
- t = o;
390
+ t = n;
390
391
  }
391
392
  return s;
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 = P(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
  });
399
- let o = this.strategyInstance.shouldNoteFlip(r);
400
+ let n = this.strategyInstance.shouldNoteFlip(r);
400
401
  switch (s.duration) {
401
402
  case "h":
402
- this.svgRendererInstance.drawGlyph("NOTE_HEAD_HALF", t), this.drawStem(t, o);
403
+ this.svgRendererInstance.drawGlyph("NOTE_HEAD_HALF", t), this.drawStem(t, n);
403
404
  break;
404
405
  case "q":
405
- this.svgRendererInstance.drawGlyph("NOTE_HEAD_QUARTER", t), this.drawStem(t, o);
406
+ this.svgRendererInstance.drawGlyph("NOTE_HEAD_QUARTER", t), this.drawStem(t, n);
406
407
  break;
407
408
  case "e":
408
- o ? this.svgRendererInstance.drawGlyph("EIGHTH_NOTE_FLIPPED", t) : this.svgRendererInstance.drawGlyph("EIGHTH_NOTE", t);
409
+ n ? this.svgRendererInstance.drawGlyph("EIGHTH_NOTE_FLIPPED", t) : this.svgRendererInstance.drawGlyph("EIGHTH_NOTE", t);
409
410
  break;
410
411
  default:
411
412
  this.svgRendererInstance.drawGlyph("NOTE_HEAD_WHOLE", t);
412
413
  }
413
- let n = 0;
414
+ let o = 0;
414
415
  switch (s.accidental) {
415
416
  case "#":
416
- this.svgRendererInstance.drawGlyph("ACCIDENTAL_SHARP", t), n -= -8;
417
+ this.svgRendererInstance.drawGlyph("ACCIDENTAL_SHARP", t), o -= -8;
417
418
  break;
418
419
  case "b":
419
- this.svgRendererInstance.drawGlyph("ACCIDENTAL_FLAT", t), n -= -8;
420
+ this.svgRendererInstance.drawGlyph("ACCIDENTAL_FLAT", t), o -= -8;
420
421
  break;
421
422
  case "n":
422
- this.svgRendererInstance.drawGlyph("ACCIDENTAL_NATURAL", t), n -= -8;
423
+ this.svgRendererInstance.drawGlyph("ACCIDENTAL_NATURAL", t), o -= -8;
423
424
  break;
424
425
  case "##":
425
- this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_SHARP", t), n -= -10;
426
+ this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_SHARP", t), o -= -10;
426
427
  break;
427
428
  case "bb":
428
- this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_FLAT", t), n -= -14;
429
+ this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_FLAT", t), o -= -14;
429
430
  break;
430
431
  }
431
432
  return this.strategyInstance.getLedgerLinesX(s, r).forEach((a) => {
@@ -434,14 +435,14 @@ class et {
434
435
  noteGroup: t,
435
436
  noteObj: s,
436
437
  noteYPos: r,
437
- accidentalOffset: n,
438
+ accidentalOffset: o,
438
439
  cursorOffset: 0
439
440
  };
440
441
  }
441
442
  renderChord(e) {
442
443
  const t = this.svgRendererInstance.createGroup("chord"), s = [];
443
- for (const n of e) {
444
- const i = this.renderNote(n);
444
+ for (const o of e) {
445
+ const i = this.renderNote(o);
445
446
  i.noteGroup.setAttribute("transform", `translate(0, ${i.noteYPos})`), t.appendChild(i.noteGroup), s.push({
446
447
  noteGroup: i.noteGroup,
447
448
  noteObj: i.noteObj,
@@ -450,25 +451,23 @@ class et {
450
451
  accidentalOffset: 0
451
452
  });
452
453
  }
453
- const r = this.chordOffsetConsecutiveAccidentals(s), o = this.chordOffsetCloseNotes(s);
454
+ const r = this.chordOffsetConsecutiveAccidentals(s), n = this.chordOffsetCloseNotes(s);
454
455
  return {
455
456
  noteGroup: t,
456
457
  noteObj: s[0].noteObj,
457
458
  noteYPos: 0,
458
459
  accidentalOffset: r,
459
- cursorOffset: o
460
+ cursorOffset: n
460
461
  };
461
462
  }
462
463
  }
463
- const g = "http://www.w3.org/2000/svg", At = 0.1, w = 1200;
464
- class L {
464
+ const A = "http://www.w3.org/2000/svg", St = 0.1, G = 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,18 +478,36 @@ class L {
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 > w && (this.width = w, console.warn(`Width provided for the staff ${this.width} exceeds the limit ${w}. Please use this value to fix positioning issues.`)), this.svgElementRef = document.createElementNS(g, "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(A, "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(g, "defs");
487
- Object.entries(Et).filter(([r]) => e.includes(r)).forEach(([r, o]) => {
488
- const n = document.createElementNS(g, "path");
489
- n.setAttribute("id", `glyph-${r}`), n.setAttribute("d", o.path), n.setAttribute("fill", "currentColor"), n.setAttribute("transform", `translate(${o.xOffset}, ${o.yOffset}) scale(${At})`), t.appendChild(n);
485
+ const t = document.createElementNS(A, "defs");
486
+ Object.entries(pt).filter(([r]) => e.includes(r)).forEach(([r, n]) => {
487
+ const o = document.createElementNS(A, "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
  }
491
+ addNamespacedClassesToElement(e, t) {
492
+ [e].flat().forEach((r) => t.classList.add(`vs-${r}`));
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(A, "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
+ }
492
509
  createGroup(e) {
493
- const t = document.createElementNS(g, "g");
510
+ const t = document.createElementNS(A, "g");
494
511
  return e && t.classList.add(`vs-${e}`), t;
495
512
  }
496
513
  commitElementsToDOM(e, t = this.rootElementRef) {
@@ -499,18 +516,6 @@ class L {
499
516
  s.appendChild(r);
500
517
  }) : s.appendChild(e), t.appendChild(s);
501
518
  }
502
- getLayerByName(e) {
503
- switch (e) {
504
- case "staff":
505
- return this.musicStaffLayer;
506
- case "notes":
507
- return this.musicNotesLayer;
508
- case "ui":
509
- return this.musicUILayer;
510
- default:
511
- throw new Error(`Layer with name '${e}' does not exist.`);
512
- }
513
- }
514
519
  addTotalRootSvgHeight(e) {
515
520
  this.totalHeight += e;
516
521
  }
@@ -521,10 +526,10 @@ class L {
521
526
  this.totalYOffset += e;
522
527
  }
523
528
  applySizingToRootSvg() {
524
- this.parentGroupContainer.setAttribute("transform", `translate(0, ${this.totalYOffset})`);
525
- let e = this.width * this.scale;
529
+ this.parentGroupContainer.setAttribute("transform", `translate(${G / 2}, ${this.totalYOffset})`);
530
+ let e = Math.round(this.width * this.scale);
526
531
  const t = (this.totalHeight + this.totalYOffset) * this.scale;
527
- 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 += G, this.svgElementRef.setAttribute("width", e.toString()), this.svgElementRef.setAttribute("height", t.toString()), this.svgElementRef.setAttribute("viewBox", `0 0 ${this.width + G} ${this.totalHeight + this.totalYOffset}`);
528
533
  }
529
534
  get rootSvgElement() {
530
535
  return this.svgElementRef;
@@ -533,13 +538,13 @@ class L {
533
538
  return this.parentGroupContainer;
534
539
  }
535
540
  // Drawing Methods
536
- drawLine(e, t, s, r, o) {
537
- const n = document.createElementNS(g, "line");
538
- n.setAttribute("x1", e.toString()), n.setAttribute("y1", t.toString()), n.setAttribute("x2", s.toString()), n.setAttribute("y2", r.toString()), n.setAttribute("stroke", "currentColor"), n.setAttribute("stroke-width", "1"), o.appendChild(n);
541
+ drawLine(e, t, s, r, n, o) {
542
+ const i = o?.strokeWidth ?? 1, a = document.createElementNS(A, "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);
539
544
  }
540
545
  drawRect(e, t, s, r) {
541
- const o = document.createElementNS(g, "rect");
542
- return o.setAttribute("width", e.toString()), o.setAttribute("height", t.toString()), o.setAttribute("x", (r?.x ?? 0).toString()), o.setAttribute("y", (r?.y ?? 0).toString()), r?.fill ? o.setAttribute("fill", r.fill) : o.setAttribute("fill", "currentColor"), r?.rx && o.setAttribute("rx", r.rx.toString()), s.appendChild(o), o;
546
+ const n = document.createElementNS(A, "rect");
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;
543
548
  }
544
549
  drawGlyph(e, t, s) {
545
550
  s = {
@@ -547,22 +552,22 @@ class L {
547
552
  yOffset: 0,
548
553
  ...s
549
554
  };
550
- const r = document.createElementNS(g, "use");
555
+ const r = document.createElementNS(A, "use");
551
556
  r.setAttribute("href", `#glyph-${e}`), (s.xOffset || s.yOffset) && r.setAttribute("transform", `translate(${s.xOffset}, ${s.yOffset})`), t.appendChild(r);
552
557
  }
553
- drawCircle(e, t, s, r, o) {
554
- const n = document.createElementNS(g, "circle");
555
- return n.setAttribute("cx", e.toString()), n.setAttribute("cy", t.toString()), n.setAttribute("r", s.toString()), o?.filled === !1 ? (n.setAttribute("fill", "none"), n.setAttribute("stroke", "currentColor"), n.setAttribute("stroke-width", (o?.strokeWidth ?? 1.5).toString())) : n.setAttribute("fill", o?.fill ?? "currentColor"), r.appendChild(n), n;
558
+ drawCircle(e, t, s, r, n) {
559
+ const o = document.createElementNS(A, "circle");
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;
556
561
  }
557
- drawText(e, t, s, r, o) {
558
- const n = document.createElementNS(g, "text");
559
- return n.setAttribute("x", t.toString()), n.setAttribute("y", s.toString()), n.setAttribute("text-anchor", o?.anchor ?? "middle"), n.setAttribute("font-size", (o?.fontSize ?? 10).toString()), n.setAttribute("fill", o?.fill ?? "currentColor"), o?.fontWeight && n.setAttribute("font-weight", o.fontWeight), n.textContent = e, r.appendChild(n), n;
562
+ drawText(e, t, s, r, n) {
563
+ const o = document.createElementNS(A, "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;
560
565
  }
561
566
  destroy() {
562
567
  this.rootElementRef && this.svgElementRef && this.rootElementRef.contains(this.svgElementRef) && this.rootElementRef.removeChild(this.svgElementRef);
563
568
  }
564
569
  }
565
- const It = [
570
+ const mt = [
566
571
  "CLEF_TREBLE",
567
572
  "CLEF_BASS",
568
573
  "CLEF_ALTO",
@@ -577,7 +582,7 @@ const It = [
577
582
  "ACCIDENTAL_DOUBLE_SHARP",
578
583
  "ACCIDENTAL_DOUBLE_FLAT"
579
584
  ];
580
- class Rt {
585
+ class bt {
581
586
  svgRendererInstance;
582
587
  strategyInstance;
583
588
  noteRendererInstance;
@@ -599,35 +604,35 @@ class Rt {
599
604
  staffType: "treble",
600
605
  spaceAbove: 0,
601
606
  spaceBelow: 0,
602
- staffColor: "black",
603
- staffBackgroundColor: "transparent",
607
+ svgAutoFill: !0,
604
608
  ...t
605
- }, this.svgRendererInstance = new L(e, {
609
+ }, this.svgRendererInstance = new O(e, {
606
610
  width: this.options.width,
607
611
  height: 100,
608
612
  scale: this.options.scale,
609
- staffColor: this.options.staffColor,
610
- staffBackgroundColor: this.options.staffBackgroundColor,
611
- useGlyphs: It
613
+ useGlyphs: mt,
614
+ svgAutoFill: this.options.svgAutoFill
612
615
  });
613
616
  const s = this.svgRendererInstance.rootSvgElement;
614
617
  switch (this.options.staffType) {
615
618
  case "grand":
616
- this.strategyInstance = new tt(this.svgRendererInstance, "grand");
619
+ this.strategyInstance = new nt(this.svgRendererInstance, "grand");
617
620
  break;
618
621
  case "bass":
619
- this.strategyInstance = new _(this.svgRendererInstance, "bass");
622
+ this.strategyInstance = new S(this.svgRendererInstance, "bass");
620
623
  break;
621
624
  case "treble":
622
- this.strategyInstance = new _(this.svgRendererInstance, "treble");
625
+ this.strategyInstance = new S(this.svgRendererInstance, "treble");
623
626
  break;
624
627
  case "alto":
625
- this.strategyInstance = new _(this.svgRendererInstance, "alto");
628
+ this.strategyInstance = new S(this.svgRendererInstance, "alto");
626
629
  break;
627
630
  default:
628
631
  throw new Error(`The staff type ${this.options.staffType} is not supported. Please use "treble", "bass", "alto", or "grand".`);
629
632
  }
630
- if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new et(this.svgRendererInstance, this.strategyInstance), this.options.spaceAbove) {
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) {
631
636
  const o = this.options.spaceAbove * 10;
632
637
  this.svgRendererInstance.addTotalRootSvgYOffset(o);
633
638
  }
@@ -635,11 +640,11 @@ class Rt {
635
640
  let o = this.options.spaceBelow * 10;
636
641
  this.options.staffType === "grand" && (o -= 10 / 2), this.svgRendererInstance.addTotalRootSvgHeight(o);
637
642
  }
638
- let r = 0;
639
- 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);
640
645
  }
641
646
  createKeySignature(e) {
642
- return ft(this.svgRendererInstance, this.strategyInstance, e, lt);
647
+ return At(this.svgRendererInstance, this.strategyInstance, e, ut);
643
648
  }
644
649
  /**
645
650
  * Draws a note on the staff.
@@ -662,21 +667,23 @@ class Rt {
662
667
  * drawNote("D4w");
663
668
  */
664
669
  drawNote(e) {
665
- const t = Array.isArray(e) ? e : [e], s = this.svgRendererInstance.getLayerByName("notes"), r = [];
666
- for (const o of t) {
667
- let n;
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 = [];
673
+ for (const n of t) {
674
+ let o;
668
675
  try {
669
- n = this.noteRendererInstance.renderNote(o);
676
+ o = this.noteRendererInstance.renderNote(n);
670
677
  } catch (i) {
671
678
  throw r.length > 0 && this.svgRendererInstance.commitElementsToDOM(r, s), i;
672
679
  }
673
- n.noteGroup.setAttribute("transform", `translate(${this.noteCursorX + n.accidentalOffset}, ${n.noteYPos})`), this.noteEntries.push({
674
- gElement: n.noteGroup,
675
- note: n.noteObj,
676
- xPos: this.noteCursorX + n.accidentalOffset,
677
- yPos: n.noteYPos,
678
- accidentalXOffset: n.accidentalOffset
679
- }), this.noteCursorX += 28 + n.accidentalOffset, r.push(n.noteGroup);
680
+ o.noteGroup.setAttribute("transform", `translate(${this.noteCursorX + o.accidentalOffset}, ${o.noteYPos})`), this.noteEntries.push({
681
+ gElement: o.noteGroup,
682
+ note: o.noteObj,
683
+ xPos: this.noteCursorX + o.accidentalOffset,
684
+ yPos: o.noteYPos,
685
+ accidentalXOffset: o.accidentalOffset
686
+ }), this.noteCursorX += 28 + o.accidentalOffset, r.push(o.noteGroup);
680
687
  }
681
688
  this.svgRendererInstance.commitElementsToDOM(r, s);
682
689
  }
@@ -697,10 +704,12 @@ class Rt {
697
704
  */
698
705
  drawChord(e) {
699
706
  if (e.length < 2) throw new Error("Provide more than one note for a chord.");
700
- 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);
701
710
  s.noteGroup.setAttribute("transform", `translate(${this.noteCursorX + s.accidentalOffset}, 0)`), this.noteEntries.push({
702
711
  gElement: s.noteGroup,
703
- note: P(e[0]),
712
+ note: Y(e[0]),
704
713
  xPos: this.noteCursorX + s.accidentalOffset,
705
714
  yPos: 0,
706
715
  accidentalXOffset: s.accidentalOffset
@@ -714,16 +723,16 @@ class Rt {
714
723
  const e = this.options.width - this.noteStartX, t = this.noteEntries.length;
715
724
  if (t <= 0 || e <= 0) return;
716
725
  const s = Math.round(e / t);
717
- this.noteEntries.map((o, n) => {
718
- const i = (n + 0.5) * s, a = o.gElement.getBBox(), c = i - a.width / 2 - a.x, l = Math.round(c * 10) / 10;
726
+ this.noteEntries.map((n, o) => {
727
+ const i = (o + 0.5) * s, a = n.gElement.getBBox(), h = i - a.width / 2 - a.x, d = Math.round(h * 10) / 10;
719
728
  return {
720
- entry: o,
721
- newX: l,
722
- isChord: o.gElement.classList.contains("chord")
729
+ entry: n,
730
+ newX: d,
731
+ isChord: n.gElement.classList.contains("chord")
723
732
  };
724
- }).forEach((o) => {
725
- const { entry: n, newX: i, isChord: a } = o;
726
- a ? n.gElement.setAttribute("transform", `translate(${i}, 0)`) : n.gElement.setAttribute("transform", `translate(${i}, ${n.yPos})`), n.xPos = i;
733
+ }).forEach((n) => {
734
+ const { entry: o, newX: i, isChord: a } = n;
735
+ a ? o.gElement.setAttribute("transform", `translate(${i}, 0)`) : o.gElement.setAttribute("transform", `translate(${i}, ${o.yPos})`), o.xPos = i;
727
736
  });
728
737
  }
729
738
  /**
@@ -731,7 +740,7 @@ class Rt {
731
740
  * @returns void
732
741
  */
733
742
  clearAllNotes() {
734
- this.noteCursorX = 0, this.svgRendererInstance.getLayerByName("notes").replaceChildren(), this.noteEntries = [];
743
+ this.noteCursorX = 0, this.svgRendererInstance.getLayer("notes")?.replaceChildren(), this.noteEntries = [];
735
744
  }
736
745
  /**
737
746
  * Changes the note by index to the specified note.
@@ -751,11 +760,12 @@ class Rt {
751
760
  */
752
761
  changeNoteByIndex(e, t) {
753
762
  if (t >= this.noteEntries.length) throw new Error("Note index was out of bounds.");
754
- const s = this.noteEntries[t], r = this.noteRendererInstance.renderNote(e), n = s.xPos - s.accidentalXOffset + r.accidentalOffset;
755
- r.noteGroup.setAttribute("transform", `translate(${n}, ${r.noteYPos})`), this.svgRendererInstance.getLayerByName("notes").replaceChild(r.noteGroup, s.gElement), this.noteEntries[t] = {
763
+ const s = this.noteEntries[t], r = this.noteRendererInstance.renderNote(e), o = s.xPos - s.accidentalXOffset + r.accidentalOffset;
764
+ if (r.noteGroup.setAttribute("transform", `translate(${o}, ${r.noteYPos})`), !this.svgRendererInstance.getLayer("notes")) throw new Error("ChangeNoteByIndex Error: Failed to retrieve notesLayer to append notes.");
765
+ this.noteEntries[t] = {
756
766
  gElement: r.noteGroup,
757
767
  note: r.noteObj,
758
- xPos: n,
768
+ xPos: o,
759
769
  yPos: r.noteYPos,
760
770
  accidentalXOffset: r.accidentalOffset
761
771
  };
@@ -779,11 +789,14 @@ class Rt {
779
789
  changeChordByIndex(e, t) {
780
790
  if (t >= this.noteEntries.length) throw new Error("Chord index was out of bounds.");
781
791
  if (e.length < 2) throw new Error("Notes provided need to be more than one to be considered a chord.");
782
- const s = this.noteEntries[t], r = this.noteRendererInstance.renderChord(e), n = s.xPos - s.accidentalXOffset + r.accidentalOffset;
783
- r.noteGroup.setAttribute("transform", `translate(${n}, 0)`), this.svgRendererInstance.getLayerByName("notes").replaceChild(r.noteGroup, s.gElement), this.noteEntries[t] = {
792
+ const s = this.noteEntries[t], r = this.noteRendererInstance.renderChord(e), o = s.xPos - s.accidentalXOffset + r.accidentalOffset;
793
+ r.noteGroup.setAttribute("transform", `translate(${o}, 0)`);
794
+ const i = this.svgRendererInstance.getLayer("notes");
795
+ if (!i) throw new Error("DrawNote Error: Failed to retrieve notesLayer to append notes.");
796
+ i.replaceChild(r.noteGroup, s.gElement), this.noteEntries[t] = {
784
797
  gElement: r.noteGroup,
785
- note: P(e[0]),
786
- xPos: n,
798
+ note: Y(e[0]),
799
+ xPos: o,
787
800
  yPos: 0,
788
801
  accidentalXOffset: r.accidentalOffset
789
802
  };
@@ -818,7 +831,7 @@ class Rt {
818
831
  this.noteEntries = [], this.svgRendererInstance.destroy();
819
832
  }
820
833
  }
821
- const A = 30, z = 19, O = 12, _t = 4, Tt = 6, j = 1, b = 38, mt = [
834
+ const _ = 30, Q = 19, D = 12, Ct = 4, Nt = 6, J = 1, H = 38, Lt = [
822
835
  "TIME_4",
823
836
  "TIME_3",
824
837
  "NOTE_HEAD_WHOLE",
@@ -830,7 +843,7 @@ const A = 30, z = 19, O = 12, _t = 4, Tt = 6, j = 1, b = 38, mt = [
830
843
  "REST_QUARTER",
831
844
  "REST_EIGHTH"
832
845
  ];
833
- class yt {
846
+ class vt {
834
847
  rendererInstance;
835
848
  options;
836
849
  barSpacing;
@@ -841,7 +854,7 @@ class yt {
841
854
  currentBeatCount = 0;
842
855
  currentBeatUICount = 0;
843
856
  currentBeatUIElement = null;
844
- currentBeatUIXPos = b;
857
+ currentBeatUIXPos = H;
845
858
  /**
846
859
  * Creates an instance of a RhythmStaff, A single staff that will automatically apply positioning of elements based on the duration of a note.
847
860
  *
@@ -857,67 +870,66 @@ class yt {
857
870
  barsCount: 2,
858
871
  spaceAbove: 0,
859
872
  spaceBelow: 0,
860
- staffColor: "black",
861
- staffBackgroundColor: "white",
862
- currentBeatUIColor: "#24ff7450",
873
+ svgAutoFill: !0,
863
874
  ...t
864
- }, this.rendererInstance = new L(e, {
875
+ }, this.rendererInstance = new O(e, {
865
876
  width: this.options.width,
866
877
  height: 100,
867
878
  scale: this.options.scale,
868
- staffColor: this.options.staffColor,
869
- staffBackgroundColor: this.options.staffBackgroundColor,
870
- useGlyphs: mt
879
+ useGlyphs: Lt,
880
+ svgAutoFill: this.options.svgAutoFill
871
881
  });
872
- const s = this.rendererInstance.rootSvgElement;
873
- let r = "TIME_4";
882
+ const s = this.rendererInstance.rootSvgElement, r = this.rendererInstance.createLayer("staff"), n = this.rendererInstance.createLayer("notes");
883
+ this.rendererInstance.createLayer("ui");
884
+ let o = "TIME_4";
874
885
  switch (this.options.topNumber) {
875
886
  case 3:
876
- r = "TIME_3";
887
+ o = "TIME_3";
877
888
  break;
878
889
  case 4:
879
- r = "TIME_4";
890
+ o = "TIME_4";
880
891
  break;
881
892
  default:
882
893
  throw new Error(`Time signature ${this.options.topNumber} not supported. Please use either 3 or 4.`);
883
894
  }
884
895
  if (this.options.barsCount < 1 || this.options.barsCount > 3) throw new Error(`Bars count ${this.options.barsCount} not supported. Please use 1 - 3`);
885
896
  if (this.options.spaceAbove) {
886
- const u = this.options.spaceAbove * 10;
887
- this.rendererInstance.addTotalRootSvgYOffset(u);
897
+ const E = this.options.spaceAbove * 10;
898
+ this.rendererInstance.addTotalRootSvgYOffset(E);
888
899
  }
889
900
  if (this.options.spaceBelow) {
890
- let u = this.options.spaceBelow * 10;
891
- this.rendererInstance.addTotalRootSvgHeight(u);
901
+ let E = this.options.spaceBelow * 10;
902
+ this.rendererInstance.addTotalRootSvgHeight(E);
892
903
  }
893
- const o = this.rendererInstance.getLayerByName("staff");
894
- this.rendererInstance.addTotalRootSvgHeight(A * 2);
895
- const n = this.rendererInstance.createGroup("time-signature");
896
- o.appendChild(n);
897
- const i = A - z;
898
- this.rendererInstance.drawGlyph(r, n), this.rendererInstance.drawGlyph("TIME_4", n, { yOffset: z }), n.setAttribute("transform", `translate(0, ${i})`);
899
- let a = this.options.width - 38;
900
- this.options.barsCount > 1 && (a -= (this.options.barsCount - 1) * O), a -= j, this.rendererInstance.drawLine(0, A, this.options.width - j, A, o), this.barSpacing = a / this.options.barsCount, this.quarterNoteSpacing = Math.round(this.barSpacing / this.options.topNumber), this.maxBeatCount = this.options.barsCount * this.options.topNumber;
901
- let c = this.barSpacing + 38;
902
- const l = A / 2, d = A + l;
903
- for (let u = 0; u < this.options.barsCount - 1; u++)
904
- this.rendererInstance.drawLine(c, l, c, d, o), c += this.barSpacing;
905
- this.rendererInstance.getLayerByName("notes").setAttribute("transform", `translate(38, ${A})`), this.rendererInstance.applySizingToRootSvg(), this.rendererInstance.commitElementsToDOM(s);
904
+ this.rendererInstance.addTotalRootSvgHeight(_ * 2);
905
+ const i = this.rendererInstance.createGroup("time-signature");
906
+ r.appendChild(i);
907
+ const a = _ - Q;
908
+ this.rendererInstance.drawGlyph(o, i), this.rendererInstance.drawGlyph("TIME_4", i, { yOffset: Q }), i.setAttribute("transform", `translate(0, ${a})`);
909
+ let h = this.options.width - 38;
910
+ 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;
911
+ let d = this.barSpacing + 38;
912
+ const c = _ / 2, f = _ + c;
913
+ for (let E = 0; E < this.options.barsCount - 1; E++)
914
+ this.rendererInstance.drawLine(d, c, d, f, r), d += this.barSpacing;
915
+ n.setAttribute("transform", `translate(38, ${_})`), this.rendererInstance.applySizingToRootSvg(), this.rendererInstance.commitElementsToDOM(s);
906
916
  }
907
917
  createBeatUIElement() {
908
- const e = this.rendererInstance.getLayerByName("ui");
918
+ const e = this.rendererInstance.getLayer("ui");
919
+ if (!e) throw new Error("BeatUI Error: Failed to retrieve ui layer");
909
920
  this.currentBeatUIElement = this.rendererInstance.drawRect(
910
921
  this.quarterNoteSpacing / 2,
911
- A * 2,
922
+ _ * 2,
912
923
  e,
913
924
  {
914
- x: b,
915
- fill: this.options.currentBeatUIColor
925
+ x: H,
926
+ fill: "rgba(0,255,40,0.4)",
927
+ classes: "rhythm-current-beat"
916
928
  }
917
929
  );
918
930
  }
919
931
  handleNewBar() {
920
- this.noteCursorX += O;
932
+ this.noteCursorX += D;
921
933
  }
922
934
  // Translates group, returns cursor increment amount
923
935
  translateGroupByDuration(e, t) {
@@ -976,20 +988,19 @@ class yt {
976
988
  let s = e;
977
989
  for (; s > 0; ) {
978
990
  const r = this.rendererInstance.createGroup("rest");
979
- let o = 0;
980
- s - p.h >= 0 ? (this.rendererInstance.drawGlyph("REST_HALF", r), o = p.h) : s - p.q >= 0 ? (this.rendererInstance.drawGlyph("REST_QUARTER", r), o = p.q) : (this.rendererInstance.drawGlyph("REST_EIGHTH", r), o = p.e), s -= o, this.currentBeatCount += o, r.setAttribute("transform", `translate(${this.noteCursorX}, 0)`), this.noteCursorX += o * this.quarterNoteSpacing, t.push(r);
991
+ let n = 0;
992
+ 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);
981
993
  }
982
994
  return t;
983
995
  }
984
996
  renderBeamRect(e, t, s, r) {
985
997
  this.rendererInstance.drawRect(
986
998
  e - t,
987
- _t,
999
+ Ct,
988
1000
  s,
989
1001
  {
990
1002
  x: 10,
991
- y: -28 + (r ?? 0),
992
- fill: this.options.staffColor
1003
+ y: -28 + (r ?? 0)
993
1004
  }
994
1005
  );
995
1006
  }
@@ -1012,24 +1023,26 @@ class yt {
1012
1023
  * drawNote("w");
1013
1024
  */
1014
1025
  drawNote(e) {
1015
- const t = Array.isArray(e) ? e : [e], s = this.rendererInstance.getLayerByName("notes"), r = [];
1016
- for (const o of t) {
1017
- let n = "w";
1026
+ const t = Array.isArray(e) ? e : [e], s = this.rendererInstance.getLayer("notes");
1027
+ if (!s) throw new Error("DrawNote Error: Failed to retrieve notes layer");
1028
+ const r = [];
1029
+ for (const n of t) {
1030
+ let o = "w";
1018
1031
  try {
1019
- n = R(o);
1020
- } catch (d) {
1021
- throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), d;
1032
+ o = v(n);
1033
+ } catch (c) {
1034
+ throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), c;
1022
1035
  }
1023
- const i = p[n];
1036
+ const i = I[o];
1024
1037
  if (this.currentBeatCount >= this.maxBeatCount)
1025
1038
  throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), new Error("Max beat count reached. Can't add additional notes.");
1026
1039
  this.checkAndCreateNewBar();
1027
1040
  const a = this.checkAndFillBarWithRests(i);
1028
- a && a.forEach((d) => {
1029
- r.push(d), this.noteEntries.push(d);
1041
+ a && a.forEach((c) => {
1042
+ r.push(c), this.noteEntries.push(c);
1030
1043
  });
1031
- const c = this.rendererInstance.createGroup("note"), l = this.translateGroupByDuration(i, c);
1032
- this.noteCursorX += l, this.currentBeatCount += i, this.renderNote(n, c), r.push(c), this.noteEntries.push(c);
1044
+ const h = this.rendererInstance.createGroup("note"), d = this.translateGroupByDuration(i, h);
1045
+ this.noteCursorX += d, this.currentBeatCount += i, this.renderNote(o, h), r.push(h), this.noteEntries.push(h);
1033
1046
  }
1034
1047
  this.rendererInstance.commitElementsToDOM(r, s);
1035
1048
  }
@@ -1052,22 +1065,24 @@ class yt {
1052
1065
  * drawRest("w");
1053
1066
  */
1054
1067
  drawRest(e) {
1055
- const t = Array.isArray(e) ? e : [e], s = this.rendererInstance.getLayerByName("notes"), r = [];
1056
- for (const o of t) {
1057
- let n = "w";
1068
+ const t = Array.isArray(e) ? e : [e], s = this.rendererInstance.getLayer("notes");
1069
+ if (!s) throw new Error("DrawRest Error: Failed to retrieve notes layer");
1070
+ const r = [];
1071
+ for (const n of t) {
1072
+ let o = "w";
1058
1073
  try {
1059
- n = R(o);
1060
- } catch (d) {
1061
- throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), d;
1074
+ o = v(n);
1075
+ } catch (c) {
1076
+ throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), c;
1062
1077
  }
1063
- const i = this.rendererInstance.createGroup("rest"), a = p[n], c = a * this.quarterNoteSpacing;
1078
+ const i = this.rendererInstance.createGroup("rest"), a = I[o], h = a * this.quarterNoteSpacing;
1064
1079
  if (this.currentBeatCount >= this.maxBeatCount)
1065
1080
  throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), new Error("Max beat count reached. Can't add additional notes.");
1066
1081
  this.checkAndCreateNewBar();
1067
- const l = this.checkAndFillBarWithRests(a);
1068
- l && l.forEach((d) => {
1069
- r.push(d), this.noteEntries.push(d);
1070
- }), this.renderRest(n, i), i.setAttribute("transform", `translate(${this.noteCursorX}, 0)`), this.noteCursorX += c, this.currentBeatCount += a, r.push(i), this.noteEntries.push(i);
1082
+ const d = this.checkAndFillBarWithRests(a);
1083
+ d && d.forEach((c) => {
1084
+ r.push(c), this.noteEntries.push(c);
1085
+ }), this.renderRest(o, i), i.setAttribute("transform", `translate(${this.noteCursorX}, 0)`), this.noteCursorX += h, this.currentBeatCount += a, r.push(i), this.noteEntries.push(i);
1071
1086
  }
1072
1087
  this.rendererInstance.commitElementsToDOM(r, s);
1073
1088
  }
@@ -1094,13 +1109,15 @@ class yt {
1094
1109
  if (this.currentBeatCount >= this.maxBeatCount)
1095
1110
  throw new Error("Max beat count reached. Can't add additional beamed note.");
1096
1111
  let s = "s";
1097
- e === "s" ? s = "s" : s = R(e), this.checkAndCreateNewBar();
1098
- const r = this.rendererInstance.getLayerByName("notes"), o = p[s], n = o * this.quarterNoteSpacing, i = this.options.topNumber - this.currentBeatCount % this.options.topNumber, a = Math.min(t, i / o), c = this.rendererInstance.createGroup("beamed-note");
1099
- c.setAttribute("transform", `translate(${this.noteCursorX}, 0)`);
1100
- let l = 0;
1101
- for (let d = 0; d < a; d++)
1102
- this.rendererInstance.drawGlyph("NOTE_HEAD_QUARTER", c, { xOffset: l }), this.drawStem(c, l), l += n, this.currentBeatCount += o;
1103
- this.renderBeamRect(l, n, c), e === "s" && this.renderBeamRect(l, n, c, Tt), this.noteCursorX += l, this.noteEntries.push(c), this.rendererInstance.commitElementsToDOM(c, r);
1112
+ e === "s" ? s = "s" : s = v(e), this.checkAndCreateNewBar();
1113
+ const r = this.rendererInstance.getLayer("notes");
1114
+ if (!r) throw new Error("drawBeamedNotes Error: Failed to retrieve notes layer");
1115
+ 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");
1116
+ h.setAttribute("transform", `translate(${this.noteCursorX}, 0)`);
1117
+ let d = 0;
1118
+ for (let c = 0; c < a; c++)
1119
+ this.rendererInstance.drawGlyph("NOTE_HEAD_QUARTER", h, { xOffset: d }), this.drawStem(h, d), d += o, this.currentBeatCount += n;
1120
+ 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);
1104
1121
  }
1105
1122
  /**
1106
1123
  * Will increment the UI showing the current beat in quarters. Once exceeded, must be reset with `resetCurrentBeatUI()`
@@ -1111,21 +1128,21 @@ class yt {
1111
1128
  this.currentBeatUIElement.setAttribute("display", "none");
1112
1129
  return;
1113
1130
  }
1114
- this.currentBeatUIElement?.getAttribute("display") === "none" && this.currentBeatUIElement.removeAttribute("display"), this.currentBeatUICount++, this.currentBeatUICount > this.options.topNumber && this.currentBeatUICount % this.options.topNumber === 1 && (this.currentBeatUIXPos += O), this.currentBeatUICount > 1 && (this.currentBeatUIXPos += this.quarterNoteSpacing), this.currentBeatUIElement.setAttribute("x", this.currentBeatUIXPos.toString());
1131
+ 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());
1115
1132
  }
1116
1133
  /**
1117
1134
  * Resets the ui showing the current beat value.
1118
1135
  * @returns void
1119
1136
  */
1120
1137
  resetCurrentBeatUI() {
1121
- this.currentBeatUICount = 0, this.currentBeatUIXPos = b, this.currentBeatUIElement && (this.currentBeatUIElement.setAttribute("display", "none"), this.currentBeatUIElement.setAttribute("x", this.currentBeatUIXPos.toString()));
1138
+ this.currentBeatUICount = 0, this.currentBeatUIXPos = H, this.currentBeatUIElement && (this.currentBeatUIElement.setAttribute("display", "none"), this.currentBeatUIElement.setAttribute("x", this.currentBeatUIXPos.toString()));
1122
1139
  }
1123
1140
  /**
1124
1141
  * Clears staff of notes and resets internal positioning.
1125
1142
  * @returns void
1126
1143
  */
1127
1144
  clearAllNotes() {
1128
- this.noteCursorX = 0, this.currentBeatCount = 0, this.rendererInstance.getLayerByName("notes").replaceChildren(), this.noteEntries = [];
1145
+ this.noteCursorX = 0, this.currentBeatCount = 0, this.rendererInstance.getLayer("notes")?.replaceChildren(), this.noteEntries = [];
1129
1146
  }
1130
1147
  /**
1131
1148
  * Removes the root svg element and cleans up arrays.
@@ -1135,7 +1152,7 @@ class yt {
1135
1152
  this.noteEntries = [], this.rendererInstance.destroy();
1136
1153
  }
1137
1154
  }
1138
- const Ct = [
1155
+ const Rt = [
1139
1156
  "CLEF_TREBLE",
1140
1157
  "CLEF_BASS",
1141
1158
  "CLEF_ALTO",
@@ -1149,8 +1166,8 @@ const Ct = [
1149
1166
  "ACCIDENTAL_NATURAL",
1150
1167
  "ACCIDENTAL_DOUBLE_SHARP",
1151
1168
  "ACCIDENTAL_DOUBLE_FLAT"
1152
- ], N = 60, St = N;
1153
- class wt {
1169
+ ], y = 60, wt = y;
1170
+ class Ft {
1154
1171
  svgRendererInstance;
1155
1172
  strategyInstance;
1156
1173
  noteRendererInstance;
@@ -1174,49 +1191,48 @@ class wt {
1174
1191
  staffType: "treble",
1175
1192
  spaceAbove: 0,
1176
1193
  spaceBelow: 0,
1177
- staffColor: "black",
1178
- staffBackgroundColor: "transparent",
1194
+ svgAutoFill: !0,
1179
1195
  ...t
1180
- }, this.svgRendererInstance = new L(e, {
1196
+ }, this.svgRendererInstance = new O(e, {
1181
1197
  width: this.options.width,
1182
1198
  height: 100,
1183
1199
  scale: this.options.scale,
1184
- staffColor: this.options.staffColor,
1185
- staffBackgroundColor: this.options.staffBackgroundColor,
1186
- useGlyphs: Ct
1200
+ useGlyphs: Rt,
1201
+ svgAutoFill: this.options.svgAutoFill
1187
1202
  });
1188
1203
  const s = this.svgRendererInstance.rootSvgElement;
1189
1204
  switch (this.options.staffType) {
1190
1205
  case "grand":
1191
- this.strategyInstance = new tt(this.svgRendererInstance, "grand");
1206
+ this.strategyInstance = new nt(this.svgRendererInstance, "grand");
1192
1207
  break;
1193
1208
  case "bass":
1194
- this.strategyInstance = new _(this.svgRendererInstance, "bass");
1209
+ this.strategyInstance = new S(this.svgRendererInstance, "bass");
1195
1210
  break;
1196
1211
  case "treble":
1197
- this.strategyInstance = new _(this.svgRendererInstance, "treble");
1212
+ this.strategyInstance = new S(this.svgRendererInstance, "treble");
1198
1213
  break;
1199
1214
  case "alto":
1200
- this.strategyInstance = new _(this.svgRendererInstance, "alto");
1215
+ this.strategyInstance = new S(this.svgRendererInstance, "alto");
1201
1216
  break;
1202
1217
  default:
1203
1218
  throw new Error(`The staff type ${this.options.staffType} is not supported. Please use "treble", "bass", "alto", or "grand".`);
1204
1219
  }
1205
- if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new et(this.svgRendererInstance, this.strategyInstance), this.options.spaceAbove) {
1206
- const r = this.options.spaceAbove * 10;
1207
- this.svgRendererInstance.addTotalRootSvgYOffset(r);
1220
+ if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new ot(this.svgRendererInstance, this.strategyInstance), this.options.spaceAbove) {
1221
+ const n = this.options.spaceAbove * 10;
1222
+ this.svgRendererInstance.addTotalRootSvgYOffset(n);
1208
1223
  }
1209
1224
  if (this.options.spaceBelow) {
1210
- let r = this.options.spaceBelow * 10;
1211
- this.options.staffType === "grand" && (r -= 10 / 2), this.svgRendererInstance.addTotalRootSvgHeight(r);
1225
+ let n = this.options.spaceBelow * 10;
1226
+ this.options.staffType === "grand" && (n -= 10 / 2), this.svgRendererInstance.addTotalRootSvgHeight(n);
1212
1227
  }
1213
- 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);
1228
+ const r = this.svgRendererInstance.createLayer("notes");
1229
+ 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);
1214
1230
  }
1215
1231
  renderFirstNoteGroups() {
1216
- const e = this.options.width - this.options.noteStartX + St;
1232
+ const e = this.options.width - this.options.noteStartX + wt;
1217
1233
  for (; this.noteBuffer.length > 0 && this.noteCursorX < e; )
1218
- this.renderNextNote(), this.noteCursorX += N;
1219
- this.activeEntries.length > 1 && (this.noteCursorX -= N);
1234
+ this.renderNextNote(), this.noteCursorX += y;
1235
+ this.activeEntries.length > 1 && (this.noteCursorX -= y);
1220
1236
  }
1221
1237
  renderNextNote() {
1222
1238
  if (this.noteBuffer.length < 1) return;
@@ -1275,7 +1291,7 @@ class wt {
1275
1291
  return;
1276
1292
  }
1277
1293
  this.activeEntries.forEach((t) => {
1278
- t.xPos -= N, t.noteWrapper.style.transform = `translate(${t.xPos}px, 0px)`;
1294
+ t.xPos -= y, t.noteWrapper.style.transform = `translate(${t.xPos}px, 0px)`;
1279
1295
  });
1280
1296
  const e = this.activeEntries[0];
1281
1297
  e.xPos <= 0 && (this.notesLayer.removeChild(e.noteWrapper), this.activeEntries.shift()), this.renderNextNote();
@@ -1295,37 +1311,36 @@ class wt {
1295
1311
  this.svgRendererInstance.destroy(), this.activeEntries = [], this.noteBuffer = [];
1296
1312
  }
1297
1313
  }
1298
- const Nt = /^[xX\da-zA-Z]+$/, Lt = /^[\d]+$/;
1299
- function K(h, e) {
1314
+ const yt = /^[xX\da-zA-Z]+$/, Ot = /^[\d]+$/;
1315
+ function tt(l, e) {
1300
1316
  const t = [];
1301
- for (let s = 0; s < h.length; s++)
1317
+ for (let s = 0; s < l.length; s++)
1302
1318
  t.push({
1303
- fret: h[s],
1319
+ fret: l[s],
1304
1320
  finger: e[s]
1305
1321
  });
1306
1322
  return t;
1307
1323
  }
1308
- function Q(h, e) {
1309
- const t = h.filter((o) => o.toLowerCase() !== "x" && o !== "0").map((o) => parseInt(o, 36));
1324
+ function et(l, e) {
1325
+ const t = l.filter((n) => n.toLowerCase() !== "x" && n !== "0").map((n) => parseInt(n, 36));
1310
1326
  if (t.length === 0) return 1;
1311
1327
  const s = Math.min(...t);
1312
1328
  return Math.max(...t) <= e ? 1 : s;
1313
1329
  }
1314
- function v(h) {
1315
- if (!Nt.test(h)) throw new Error("Invalid frets string. Only 'x', 'X', and digits are allowed.");
1316
- return h.split("");
1330
+ function P(l) {
1331
+ if (!yt.test(l)) throw new Error("Invalid frets string. Only 'x', 'X', and digits are allowed.");
1332
+ return l.split("");
1317
1333
  }
1318
- function G(h) {
1319
- if (!Lt.test(h)) throw new Error("Invalid fingers string. Only digits are allowed.");
1320
- return h.split("");
1334
+ function B(l) {
1335
+ if (!Ot.test(l)) throw new Error("Invalid fingers string. Only digits are allowed.");
1336
+ return l.split("");
1321
1337
  }
1322
- class Ot {
1338
+ class Gt {
1323
1339
  svgRendererInstance;
1324
1340
  options;
1325
1341
  chordEntries = [];
1326
1342
  cursorX = 0;
1327
1343
  cursorY = 0;
1328
- // Fixed per-instance sizing, derived once from options
1329
1344
  diagramWidth;
1330
1345
  diagramHeight;
1331
1346
  gridTopY;
@@ -1339,58 +1354,78 @@ class Ot {
1339
1354
  */
1340
1355
  constructor(e, t) {
1341
1356
  if (this.options = {
1342
- width: 300,
1343
- scale: 1,
1344
- stringCount: st,
1345
- fretCount: rt,
1357
+ stringCount: it,
1358
+ fretCount: at,
1346
1359
  stringLabels: [],
1347
- color: "black",
1348
- backgroundColor: "transparent",
1360
+ inlineChordsAmount: 2,
1361
+ centerChords: !0,
1362
+ scale: 1,
1363
+ svgAutoFill: !0,
1349
1364
  ...t
1350
- }, this.diagramWidth = (this.options.stringCount - 1) * I, this.diagramHeight = this.options.fretCount * T, this.gridTopY = M + Y, this.rowHeight = this.gridTopY + this.diagramHeight + X, this.options.stringLabels.length >= 1 && (this.rowHeight += ot + nt), this.diagramWidth > this.options.width)
1365
+ }, 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)
1351
1366
  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'.`);
1352
- this.svgRendererInstance = new L(e, {
1367
+ this.svgRendererInstance = new O(e, {
1353
1368
  width: this.options.width,
1354
1369
  height: 100,
1355
1370
  scale: this.options.scale,
1356
- staffColor: this.options.color,
1357
- staffBackgroundColor: this.options.backgroundColor,
1358
- useGlyphs: []
1371
+ useGlyphs: [],
1372
+ svgAutoFill: this.options.svgAutoFill
1359
1373
  });
1360
1374
  const s = this.svgRendererInstance.rootSvgElement;
1361
1375
  this.svgRendererInstance.setTotalRootSvgHeight(this.rowHeight), this.svgRendererInstance.applySizingToRootSvg(), this.svgRendererInstance.commitElementsToDOM(s);
1362
1376
  }
1363
- drawStringDots(e, t, s, r) {
1364
- const o = this.gridTopY - Y / 2;
1365
- for (let n = 0; n < this.options.stringCount; n++) {
1366
- const i = n * I, a = e[n].toLowerCase(), c = t[n];
1367
- if (a === "x")
1368
- this.svgRendererInstance.drawLine(i - f, o - f, i + f, o + f, r), this.svgRendererInstance.drawLine(i - f, o + f, i + f, o - f, r);
1369
- else if (a === "0")
1370
- this.svgRendererInstance.drawCircle(i, o, f, r, { filled: !1 });
1377
+ getDotsToHide(e) {
1378
+ const t = /* @__PURE__ */ new Set();
1379
+ return e && e.forEach((s) => {
1380
+ const r = s.fromString - 1, n = s.toString - 1;
1381
+ for (let o = r; o <= n; o++)
1382
+ t.add(`${o}-${s.fret}`);
1383
+ }), t;
1384
+ }
1385
+ drawFretDots(e, t, s, r, n) {
1386
+ const o = this.gridTopY - W / 2;
1387
+ for (let i = 0; i < this.options.stringCount; i++) {
1388
+ const a = i * T, h = e[i].toLowerCase(), d = t[i], c = this.svgRendererInstance.createGroup("");
1389
+ if (h === "x")
1390
+ c.classList.add("vs-guitar-fret-muted"), c.setAttribute("transform", `translate(${a}, ${o})`), this.svgRendererInstance.drawLine(-p, -p, p, p, c, {
1391
+ strokeWidth: 1.5
1392
+ }), this.svgRendererInstance.drawLine(-p, p, p, -p, c, {
1393
+ strokeWidth: 1.5
1394
+ });
1395
+ else if (h === "0")
1396
+ c.classList.add("vs-guitar-fret-open"), c.setAttribute("transform", `translate(${a}, ${o})`), this.svgRendererInstance.drawCircle(0, 0, p, c, { filled: !1 });
1371
1397
  else {
1372
- const l = parseInt(a, 36) - s + 1;
1373
- if (l < 1 || l > this.options.fretCount)
1374
- throw new Error(`Fret ${a} on string ${n + 1} is outside the visible range (${s}-${s + this.options.fretCount - 1}). Adjust 'startFret' or 'fretCount'.`);
1375
- const d = this.gridTopY + (l - 0.5) * T;
1376
- if (this.svgRendererInstance.drawCircle(i, d, E, r), c !== "0") {
1377
- const u = this.options.backgroundColor === "transparent" ? "white" : this.options.backgroundColor;
1378
- this.svgRendererInstance.drawText(c, i, d + C / 3, r, {
1379
- fontSize: C,
1380
- fill: u
1381
- });
1382
- }
1398
+ const f = parseInt(h, 36);
1399
+ if (r.has(`${i}-${f}`))
1400
+ continue;
1401
+ c.classList.add("vs-guitar-fret-dot");
1402
+ const E = f - s + 1;
1403
+ if (E < 1 || E > this.options.fretCount)
1404
+ throw new Error(`Fret ${h} on string ${i + 1} is outside the visible range (${s}-${s + this.options.fretCount - 1}). Adjust 'startFret' or 'fretCount'.`);
1405
+ const g = this.gridTopY + (E - 0.5) * m;
1406
+ c.setAttribute("transform", `translate(${a}, ${g})`), this.svgRendererInstance.drawCircle(0, 0, u, c, {
1407
+ classes: "guitar-fret-circle"
1408
+ }), d !== "0" && this.svgRendererInstance.drawText(d, 0, -1, c, {
1409
+ fontSize: R,
1410
+ baseline: "central",
1411
+ classes: ["guitar-text", "guitar-fret-text"]
1412
+ });
1383
1413
  }
1414
+ n.appendChild(c);
1384
1415
  }
1385
1416
  }
1386
1417
  drawStringLabels(e, t) {
1387
1418
  if (!t || t.length === 0) return;
1388
- const s = E - 1, r = this.rowHeight - s - X;
1389
- for (let o = 0; o < this.options.stringCount; o++) {
1390
- const n = t[o];
1391
- if (!n) continue;
1392
- const i = o * I, a = r + s / 2;
1393
- this.svgRendererInstance.drawCircle(i, r, s, e, { filled: !1 }), this.svgRendererInstance.drawText(n, i, a, e, { fontSize: D });
1419
+ const s = u, r = this.rowHeight - s - $;
1420
+ for (let n = 0; n < this.options.stringCount; n++) {
1421
+ const o = t[n];
1422
+ if (!o) continue;
1423
+ const i = n * T;
1424
+ this.svgRendererInstance.drawText(o, i, r, e, {
1425
+ fontSize: R,
1426
+ baseline: "central",
1427
+ classes: "guitar-text"
1428
+ });
1394
1429
  }
1395
1430
  }
1396
1431
  // Passed in 'from' and 'to' index values are zero-based
@@ -1400,64 +1435,82 @@ class Ot {
1400
1435
  throw new Error(`Barre fret error: Invalid string range ${t.fromIndex + 1}:${t.toIndex + 1}.`);
1401
1436
  if (s < t.startingFret || s > t.startingFret + (this.options.fretCount - 1))
1402
1437
  throw new Error(`Barre fret error: ${t.fret} is outside the visible range.`);
1403
- const r = s - t.startingFret, o = t.fromIndex * I, n = t.toIndex * I, i = E * 2, a = n - o + i, c = this.gridTopY + E / 2 + T * r;
1404
- if (this.svgRendererInstance.drawRect(a, i, e, {
1405
- x: o - E,
1406
- y: c,
1407
- rx: E
1408
- }), t.finger) {
1409
- const l = this.options.backgroundColor === "transparent" ? "white" : this.options.backgroundColor;
1410
- this.svgRendererInstance.drawText(t.finger.toString(), (o + n) / 2, c + C, e, {
1411
- fontSize: C,
1412
- fill: l
1413
- });
1414
- }
1438
+ 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;
1439
+ r.setAttribute("transform", `translate(0, ${d})`), this.svgRendererInstance.drawRect(h, a, r, {
1440
+ x: o - u,
1441
+ y: u / 2,
1442
+ rx: u,
1443
+ classes: "guitar-barre"
1444
+ }), t.finger && this.svgRendererInstance.drawText(t.finger.toString(), (o + i) / 2, u * 1.5 - 1, r, {
1445
+ fontSize: R,
1446
+ baseline: "central",
1447
+ classes: ["guitar-text", "guitar-fret-text"]
1448
+ }), e.appendChild(r);
1415
1449
  }
1416
1450
  // Builds a single chord diagram's group element: grid, nut/fret-position label, and per-string markers.
1417
1451
  renderChordDiagram(e, t, s) {
1418
- const r = this.svgRendererInstance.createGroup("chord"), o = s?.startFret ?? 1;
1419
- s?.label && this.svgRendererInstance.drawText(s.label, this.diagramWidth / 2, M - 5, r, {
1420
- fontSize: D,
1421
- fontWeight: "bold"
1422
- });
1423
- for (let n = 0; n <= this.options.fretCount; n++) {
1424
- const i = this.gridTopY + n * T;
1425
- n === 0 && o === 1 ? this.svgRendererInstance.drawRect(this.diagramWidth + U * 2, F, r, {
1426
- x: -U,
1427
- y: i - F / 2
1428
- }) : this.svgRendererInstance.drawLine(0, i, this.diagramWidth, i, r);
1429
- }
1430
- o > 1 && this.svgRendererInstance.drawText(`${o}fr`, this.diagramWidth + ht, this.gridTopY + T / 2 + 4, r, {
1452
+ const r = this.svgRendererInstance.createGroup("chord"), n = s?.startFret ?? 1;
1453
+ s?.label && this.svgRendererInstance.drawText(s.label, this.diagramWidth / 2, k - 5, r, {
1454
+ fontSize: st,
1455
+ fontWeight: "bold",
1456
+ classes: ["guitar-text", "guitar-diagram-label"]
1457
+ }), n > 1 && this.svgRendererInstance.drawText(`${n}fr`, this.diagramWidth + u + Et, this.gridTopY + m / 2 + 4, r, {
1431
1458
  anchor: "start",
1432
- fontSize: ct,
1433
- fontWeight: "bold"
1459
+ fontSize: R,
1460
+ fontWeight: "bold",
1461
+ classes: ["guitar-text", "guitar-fret-label"]
1434
1462
  });
1435
- for (let n = 0; n < this.options.stringCount; n++) {
1436
- const i = n * I;
1437
- this.svgRendererInstance.drawLine(i, this.gridTopY, i, this.gridTopY + this.diagramHeight, r);
1463
+ const o = this.svgRendererInstance.createGroup("guitar-group-fret-lines");
1464
+ for (let c = 0; c <= this.options.fretCount; c++) {
1465
+ const f = this.gridTopY + c * m;
1466
+ c === 0 && n === 1 ? this.svgRendererInstance.drawRect(this.diagramWidth + ft, x, o, {
1467
+ x: -0.5,
1468
+ y: f - x / 2
1469
+ }) : this.svgRendererInstance.drawLine(0, f, this.diagramWidth, f, o);
1470
+ }
1471
+ r.appendChild(o);
1472
+ const i = this.svgRendererInstance.createGroup("guitar-group-string-lines");
1473
+ for (let c = 0; c < this.options.stringCount; c++) {
1474
+ const f = c * T;
1475
+ this.svgRendererInstance.drawLine(f, this.gridTopY, f, this.gridTopY + this.diagramHeight, i);
1438
1476
  }
1439
- return this.drawStringDots(e, t, o, r), this.options.stringLabels.length >= 1 && this.drawStringLabels(r, this.options.stringLabels), s?.barres?.forEach((n) => {
1440
- this.drawBarre(r, {
1441
- fromIndex: n.fromString - 1,
1442
- toIndex: n.toString - 1,
1443
- fret: n.fret,
1444
- finger: n.finger,
1445
- startingFret: o
1477
+ r.appendChild(i);
1478
+ const a = this.svgRendererInstance.createGroup("guitar-group-fret-dots"), h = this.getDotsToHide(s?.barres);
1479
+ this.drawFretDots(e, t, n, h, a), s?.barres?.forEach((c) => {
1480
+ this.drawBarre(a, {
1481
+ fromIndex: c.fromString - 1,
1482
+ toIndex: c.toString - 1,
1483
+ fret: c.fret,
1484
+ finger: c.finger,
1485
+ startingFret: n
1446
1486
  });
1447
- }), r;
1487
+ }), r.appendChild(a);
1488
+ const d = this.svgRendererInstance.createGroup("guitar-group-string-labels");
1489
+ return this.options.stringLabels.length >= 1 && this.drawStringLabels(d, this.options.stringLabels), r.appendChild(d), r;
1448
1490
  }
1449
1491
  // Repositions every existing chord diagram from scratch, in order, wrapping rows as needed.
1450
- // Called after any add/remove/change so the layout never has to track incremental deltas.
1492
+ // Called after any add/remove/change so the layout never has to track pos.
1451
1493
  relayoutChords() {
1452
- if (this.cursorX = E, this.cursorY = 0, this.chordEntries.length === 1) {
1453
- const t = this.chordEntries[0];
1454
- 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})`);
1455
- } else
1456
- this.chordEntries.forEach((t, s) => {
1457
- s > 0 && this.cursorX + this.diagramWidth > this.options.width && (this.cursorX = E, this.cursorY += this.rowHeight + at), t.xPos = this.cursorX, t.yPos = this.cursorY, t.gElement.setAttribute("transform", `translate(${this.cursorX}, ${this.cursorY})`), this.cursorX += this.diagramWidth + it;
1494
+ if (this.chordEntries.length === 0) {
1495
+ this.svgRendererInstance.setTotalRootSvgHeight(0), this.svgRendererInstance.applySizingToRootSvg();
1496
+ return;
1497
+ }
1498
+ const e = [];
1499
+ let t = [], s = u;
1500
+ this.chordEntries.forEach((n, o) => {
1501
+ o > 0 && s + this.diagramWidth > this.options.width && (e.push(t), t = [], s = u), t.push(n), s += this.diagramWidth + L;
1502
+ }), t.length > 0 && e.push(t), this.cursorY = dt, e.forEach((n, o) => {
1503
+ if (o > 0 && (this.cursorY += this.rowHeight + lt), this.options.centerChords) {
1504
+ const i = n.length * this.diagramWidth + (n.length - 1) * L;
1505
+ this.cursorX = this.options.width / 2 - i / 2;
1506
+ } else
1507
+ this.cursorX = u;
1508
+ n.forEach((i) => {
1509
+ i.xPos = this.cursorX, i.yPos = this.cursorY, i.gElement.setAttribute("transform", `translate(${this.cursorX}, ${this.cursorY})`), this.cursorX += this.diagramWidth + L;
1458
1510
  });
1459
- const e = this.cursorY + this.rowHeight;
1460
- this.svgRendererInstance.setTotalRootSvgHeight(e), this.svgRendererInstance.applySizingToRootSvg();
1511
+ });
1512
+ const r = this.cursorY + this.rowHeight;
1513
+ this.svgRendererInstance.setTotalRootSvgHeight(r), this.svgRendererInstance.applySizingToRootSvg();
1461
1514
  }
1462
1515
  /**
1463
1516
  * Adds a new chord diagram. Diagrams are placed left-to-right in the order added, wrapping to a
@@ -1483,14 +1536,14 @@ class Ot {
1483
1536
  * guitarChord.addChord("x32010", "032010", { label: "C" });
1484
1537
  */
1485
1538
  addChord(e, t, s) {
1486
- const r = v(e), o = G(t);
1539
+ const r = P(e), n = B(t);
1487
1540
  if (r.length !== this.options.stringCount) throw new Error("Invalid number of frets provided, entries should be equal to number of strings in diagram.");
1488
- if (o.length !== this.options.stringCount) throw new Error("Invalid number of fingers provided, entries should be equal to number of strings in diagram.");
1489
- const n = s?.startFret ?? Q(r, this.options.fretCount), i = s?.label, a = s?.barres, c = { startFret: n, label: i, barres: a }, l = this.renderChordDiagram(r, o, c), d = this.svgRendererInstance.getLayerByName("notes");
1490
- return this.svgRendererInstance.commitElementsToDOM(l, d), this.chordEntries.push({
1491
- gElement: l,
1492
- strings: K(r, o),
1493
- ...c,
1541
+ if (n.length !== this.options.stringCount) throw new Error("Invalid number of fingers provided, entries should be equal to number of strings in diagram.");
1542
+ 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;
1543
+ return this.svgRendererInstance.commitElementsToDOM(d, c), this.chordEntries.push({
1544
+ gElement: d,
1545
+ strings: tt(r, n),
1546
+ ...h,
1494
1547
  xPos: 0,
1495
1548
  yPos: 0
1496
1549
  }), this.relayoutChords(), this.chordEntries.length - 1;
@@ -1521,14 +1574,14 @@ class Ot {
1521
1574
  */
1522
1575
  modifyChordByIndex(e, t, s, r) {
1523
1576
  if (s >= this.chordEntries.length || s < 0) throw new Error("Chord index was out of bounds.");
1524
- const o = v(e), n = G(t);
1525
- if (o.length !== this.options.stringCount) throw new Error("Invalid number of frets provided, entries should be equal to number of strings in diagram.");
1526
- if (n.length !== this.options.stringCount) throw new Error("Invalid number of fingers provided, entries should be equal to number of strings in diagram.");
1527
- const i = this.chordEntries[s], a = r && "label" in r ? r.label === "" ? void 0 : r.label : i.label, c = r?.startFret ?? Q(o, this.options.fretCount), l = { ...r, label: a, startFret: c }, d = this.renderChordDiagram(o, n, l);
1528
- this.svgRendererInstance.getLayerByName("notes").replaceChild(d, i.gElement), this.chordEntries[s] = {
1529
- gElement: d,
1530
- strings: K(o, n),
1531
- ...l,
1577
+ const n = P(e), o = B(t);
1578
+ if (n.length !== this.options.stringCount) throw new Error("Invalid number of frets provided, entries should be equal to number of strings in diagram.");
1579
+ if (o.length !== this.options.stringCount) throw new Error("Invalid number of fingers provided, entries should be equal to number of strings in diagram.");
1580
+ 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);
1581
+ this.svgRendererInstance.parentGroupElement.replaceChild(c, i.gElement), this.chordEntries[s] = {
1582
+ gElement: c,
1583
+ strings: tt(n, o),
1584
+ ...d,
1532
1585
  xPos: i.xPos,
1533
1586
  yPos: i.yPos
1534
1587
  }, this.relayoutChords();
@@ -1548,7 +1601,7 @@ class Ot {
1548
1601
  * @returns void
1549
1602
  */
1550
1603
  clearAllChords() {
1551
- this.svgRendererInstance.getLayerByName("notes").replaceChildren(), this.chordEntries = [], this.cursorX = 0, this.cursorY = 0, this.svgRendererInstance.setTotalRootSvgHeight(this.rowHeight), this.svgRendererInstance.applySizingToRootSvg();
1604
+ this.svgRendererInstance.parentGroupElement.replaceChildren(), this.chordEntries = [], this.cursorX = 0, this.cursorY = 0, this.svgRendererInstance.setTotalRootSvgHeight(this.rowHeight), this.svgRendererInstance.applySizingToRootSvg();
1552
1605
  }
1553
1606
  /**
1554
1607
  * * Used to automatically determine options for creating barre lines.
@@ -1556,24 +1609,27 @@ class Ot {
1556
1609
  * @returns GuitarBarreDef[]
1557
1610
  */
1558
1611
  determineBarreOptions(e, t, s) {
1559
- const r = v(e), o = G(t), n = [];
1612
+ const r = P(e), n = B(t), o = [];
1560
1613
  return s.forEach((i) => {
1561
- const a = {};
1562
- for (let c = 0; c < r.length; c++) {
1563
- if (r[c].toLowerCase() === "x") continue;
1564
- if (parseInt(r[c], 36) === i && o[c] !== "0") {
1565
- const d = o[c];
1566
- a[d] || (a[d] = []), a[d].push(c);
1567
- }
1614
+ if (i === 0) return;
1615
+ const a = [], h = {};
1616
+ for (let g = 0; g < r.length; g++) {
1617
+ if (r[g].toLowerCase() === "x") continue;
1618
+ const N = parseInt(r[g], 36), b = Number(n[g]);
1619
+ N === i && (h[b] ? h[b] += 1 : h[b] = 1, a.push(g + 1));
1568
1620
  }
1569
- for (const [c, l] of Object.entries(a))
1570
- l.length > 1 && n.push({
1571
- fret: i,
1572
- fromString: Math.min(...l) + 1,
1573
- toString: Math.max(...l) + 1,
1574
- finger: Number(c)
1575
- });
1576
- }), n;
1621
+ a.sort();
1622
+ let d = 0, c = 0;
1623
+ for (const [g, N] of Object.entries(h))
1624
+ N > c && (c = N, d = Number(g));
1625
+ const f = a[0], E = a.at(-1);
1626
+ a.length > 1 && E && o.push({
1627
+ fret: i,
1628
+ fromString: f,
1629
+ toString: E,
1630
+ finger: d
1631
+ });
1632
+ }), o;
1577
1633
  }
1578
1634
  /**
1579
1635
  * Removes the root svg element and cleans up arrays.
@@ -1584,8 +1640,8 @@ class Ot {
1584
1640
  }
1585
1641
  }
1586
1642
  export {
1587
- Ot as GuitarChord,
1588
- Rt as MusicStaff,
1589
- yt as RhythmStaff,
1590
- wt as ScrollingStaff
1643
+ Gt as GuitarChord,
1644
+ bt as MusicStaff,
1645
+ vt as RhythmStaff,
1646
+ Ft as ScrollingStaff
1591
1647
  };