vector-score 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- const I = {
1
+ const S = {
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
+ }, 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 = {
41
41
  sharp: ["F", "C", "G", "D", "A", "E", "B"],
42
42
  flat: ["B", "E", "A", "D", "G", "C", "F"]
43
- }, G = {
43
+ }, k = {
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
+ }, B = {
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 dt(h) {
79
+ const e = k[h];
80
+ if (!e) throw new Error(`Unknown key signature "${h}". Valid keys: ${Object.keys(k).join(", ")}`);
81
81
  return e;
82
82
  }
83
- function k(h, e, t, s) {
84
- const r = Y(t);
83
+ function ft(h, e, t, s) {
84
+ const r = dt(t);
85
85
  if (r.count === 0) return 0;
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 });
86
+ const o = r.type === "sharp" ? "ACCIDENTAL_SHARP" : "ACCIDENTAL_FLAT", n = h.getLayerByName("staff");
87
+ return e.getKeySignatureYPositions(r.type, r.count).forEach((a) => {
88
+ a.forEach((c, l) => {
89
+ h.drawGlyph(o, n, { xOffset: s + l * $, yOffset: c });
90
90
  });
91
- }), r.count * w;
91
+ }), r.count * $;
92
92
  }
93
- const $ = {
93
+ const Et = {
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,26 +186,26 @@ 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
+ }, 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);
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
- let { name: t, accidental: s, octave: r, duration: n } = e.groups;
195
- t = t.toUpperCase(), n = n.toLowerCase(), n || (n = "w");
196
- const o = {
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 = {
197
197
  name: t,
198
198
  octave: parseInt(r),
199
- duration: n
199
+ duration: o
200
200
  };
201
- return s && (o.accidental = s), o;
201
+ return s && (n.accidental = s), n;
202
202
  }
203
- function N(h) {
204
- const e = h.match(Z);
203
+ function R(h) {
204
+ const e = h.match(gt);
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 x(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 W(h) {
225
+ let e = H.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 m(h, e) {
229
+ return H.indexOf(h.name) - H.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 y = 48, Z = 40 + 30 / 2, V = 20, q = 90;
232
+ class tt {
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 = S[t];
240
240
  if (!s) throw new Error(`Staff type ${t} is not supported`);
241
241
  this.params = s;
242
242
  }
@@ -251,106 +251,106 @@ class x {
251
251
  const t = this.rendererRef.getLayerByName("staff");
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
- 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);
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);
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 - V);
260
+ return e === Z ? !1 : t <= s ? !(e >= q) : e <= V;
261
261
  }
262
262
  getLedgerLinesX(e, t) {
263
- const s = [], r = F(e);
264
- let n = e.duration === "w" ? 17 : 12.5;
265
- if (r === C)
266
- return s.push({ x1: -2, x2: n, yPos: 0 }), s;
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;
267
267
  if (t < this.params.topLineYPos) {
268
- let o = this.params.topLineYPos - 10;
269
- for (; o >= t; )
268
+ let n = this.params.topLineYPos - 10;
269
+ for (; n >= t; )
270
270
  s.push({
271
271
  x1: -2,
272
- x2: n,
273
- yPos: o - t
274
- }), o -= 10;
272
+ x2: o,
273
+ yPos: n - t
274
+ }), n -= 10;
275
275
  } else if (t > this.params.bottomLineYPos) {
276
- let o = this.params.bottomLineYPos + 10;
277
- for (; o <= t; )
276
+ let n = this.params.bottomLineYPos + 10;
277
+ for (; n <= t; )
278
278
  s.push({
279
279
  x1: -2,
280
- x2: n,
281
- yPos: o - t
282
- }), o += 10;
280
+ x2: o,
281
+ yPos: n - t
282
+ }), n += 10;
283
283
  }
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 = m(this.params.topLineNote, e) * (10 / 2);
288
+ const r = W(e);
289
+ return r < y ? s += 10 : r === y && (s = Z), 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 = 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)
294
+ ), i = s.map(
295
+ (a, c) => m(S.bass.topLineNote, { name: a, octave: o[c] }) * (10 / 2) + this.trebleStaffHeight + 30
296
296
  );
297
- return [o, a];
297
+ return [n, i];
298
298
  }
299
299
  }
300
- const V = 20;
301
- class A {
300
+ const pt = 20;
301
+ class _ {
302
302
  params;
303
303
  rendererRef;
304
304
  constructor(e, t) {
305
305
  this.rendererRef = e;
306
- const s = I[t];
306
+ const s = S[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
- let r = s - 10 + 1, n = 1;
317
- const o = R(this.params.staffType);
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);
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);
319
319
  };
320
320
  shouldNoteFlip(e) {
321
- return e <= V;
321
+ return e <= pt;
322
322
  }
323
323
  getLedgerLinesX(e, t) {
324
324
  const s = [];
325
325
  let r = e.duration === "w" ? 17 : 12.5;
326
326
  if (t < this.params.topLineYPos) {
327
- let n = this.params.topLineYPos - 10;
328
- for (; n >= t; )
327
+ let o = this.params.topLineYPos - 10;
328
+ for (; o >= t; )
329
329
  s.push({
330
330
  x1: -2,
331
331
  x2: r,
332
- yPos: n - t
333
- }), n -= 10;
332
+ yPos: o - t
333
+ }), o -= 10;
334
334
  } else if (t > this.params.bottomLineYPos) {
335
- let n = this.params.bottomLineYPos + 10;
336
- for (; n <= t; )
335
+ let o = this.params.bottomLineYPos + 10;
336
+ for (; o <= t; )
337
337
  s.push({
338
338
  x1: -2,
339
339
  x2: r,
340
- yPos: n - t
341
- }), n += 10;
340
+ yPos: o - t
341
+ }), o += 10;
342
342
  }
343
343
  return s;
344
344
  }
345
- calculateNoteYPos = (e) => _(this.params.topLineNote, e) * (10 / 2);
345
+ calculateNoteYPos = (e) => m(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 = J[e].slice(0, t), r = B[this.params.staffType][e];
348
348
  return [s.map(
349
- (o, a) => this.calculateNoteYPos({ name: o, octave: r[a] })
349
+ (n, i) => this.calculateNoteYPos({ name: n, octave: r[i] })
350
350
  )];
351
351
  }
352
352
  }
353
- class U {
353
+ class et {
354
354
  svgRendererInstance;
355
355
  strategyInstance;
356
356
  constructor(e, t) {
@@ -361,12 +361,12 @@ class U {
361
361
  }
362
362
  chordOffsetConsecutiveAccidentals(e) {
363
363
  let t = 0, s = 0, r = 0;
364
- for (let n = 0; n < e.length; n++) {
365
- const o = e[n];
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)`);
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"));
368
+ if (!a) continue;
369
+ a.setAttribute("transform", `translate(${t + 8}, 0)`);
370
370
  }
371
371
  }
372
372
  return -s;
@@ -374,94 +374,94 @@ class U {
374
374
  chordOffsetCloseNotes(e) {
375
375
  let t = e[0], s = 0;
376
376
  for (let r = 1; r < e.length; r++) {
377
- const n = e[r];
378
- if (-_(t.noteObj, n.noteObj) === 1) {
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)`);
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"));
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;
388
388
  }
389
- t = n;
389
+ t = o;
390
390
  }
391
391
  return s;
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 = P(e), r = this.strategyInstance.calculateNoteYPos({
396
396
  name: s.name,
397
397
  octave: s.octave
398
398
  });
399
- let n = this.strategyInstance.shouldNoteFlip(r);
399
+ let o = this.strategyInstance.shouldNoteFlip(r);
400
400
  switch (s.duration) {
401
401
  case "h":
402
- this.svgRendererInstance.drawGlyph("NOTE_HEAD_HALF", t), this.drawStem(t, n);
402
+ this.svgRendererInstance.drawGlyph("NOTE_HEAD_HALF", t), this.drawStem(t, o);
403
403
  break;
404
404
  case "q":
405
- this.svgRendererInstance.drawGlyph("NOTE_HEAD_QUARTER", t), this.drawStem(t, n);
405
+ this.svgRendererInstance.drawGlyph("NOTE_HEAD_QUARTER", t), this.drawStem(t, o);
406
406
  break;
407
407
  case "e":
408
- n ? this.svgRendererInstance.drawGlyph("EIGHTH_NOTE_FLIPPED", t) : this.svgRendererInstance.drawGlyph("EIGHTH_NOTE", t);
408
+ o ? this.svgRendererInstance.drawGlyph("EIGHTH_NOTE_FLIPPED", t) : this.svgRendererInstance.drawGlyph("EIGHTH_NOTE", t);
409
409
  break;
410
410
  default:
411
411
  this.svgRendererInstance.drawGlyph("NOTE_HEAD_WHOLE", t);
412
412
  }
413
- let o = 0;
413
+ let n = 0;
414
414
  switch (s.accidental) {
415
415
  case "#":
416
- this.svgRendererInstance.drawGlyph("ACCIDENTAL_SHARP", t), o -= -8;
416
+ this.svgRendererInstance.drawGlyph("ACCIDENTAL_SHARP", t), n -= -8;
417
417
  break;
418
418
  case "b":
419
- this.svgRendererInstance.drawGlyph("ACCIDENTAL_FLAT", t), o -= -8;
419
+ this.svgRendererInstance.drawGlyph("ACCIDENTAL_FLAT", t), n -= -8;
420
420
  break;
421
421
  case "n":
422
- this.svgRendererInstance.drawGlyph("ACCIDENTAL_NATURAL", t), o -= -8;
422
+ this.svgRendererInstance.drawGlyph("ACCIDENTAL_NATURAL", t), n -= -8;
423
423
  break;
424
424
  case "##":
425
- this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_SHARP", t), o -= -10;
425
+ this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_SHARP", t), n -= -10;
426
426
  break;
427
427
  case "bb":
428
- this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_FLAT", t), o -= -14;
428
+ this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_FLAT", t), n -= -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,
436
436
  noteYPos: r,
437
- accidentalOffset: o,
437
+ accidentalOffset: n,
438
438
  cursorOffset: 0
439
439
  };
440
440
  }
441
441
  renderChord(e) {
442
442
  const t = this.svgRendererInstance.createGroup("chord"), s = [];
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,
443
+ for (const n of e) {
444
+ const i = this.renderNote(n);
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
  });
452
452
  }
453
- const r = this.chordOffsetConsecutiveAccidentals(s), n = this.chordOffsetCloseNotes(s);
453
+ const r = this.chordOffsetConsecutiveAccidentals(s), o = this.chordOffsetCloseNotes(s);
454
454
  return {
455
455
  noteGroup: t,
456
456
  noteObj: s[0].noteObj,
457
457
  noteYPos: 0,
458
458
  accidentalOffset: r,
459
- cursorOffset: n
459
+ cursorOffset: o
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 g = "http://www.w3.org/2000/svg", At = 0.1, w = 1200;
464
+ class L {
465
465
  rootElementRef;
466
466
  svgElementRef;
467
467
  // Layers
@@ -479,18 +479,18 @@ 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 > 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);
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(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);
490
490
  }), this.rootSvgElement.appendChild(t);
491
491
  }
492
492
  createGroup(e) {
493
- const t = document.createElementNS(u, "g");
493
+ const t = document.createElementNS(g, "g");
494
494
  return e && t.classList.add(`vs-${e}`), t;
495
495
  }
496
496
  commitElementsToDOM(e, t = this.rootElementRef) {
@@ -514,6 +514,9 @@ class b {
514
514
  addTotalRootSvgHeight(e) {
515
515
  this.totalHeight += e;
516
516
  }
517
+ setTotalRootSvgHeight(e) {
518
+ this.totalHeight = e;
519
+ }
517
520
  addTotalRootSvgYOffset(e) {
518
521
  this.totalYOffset += e;
519
522
  }
@@ -530,13 +533,13 @@ class b {
530
533
  return this.parentGroupContainer;
531
534
  }
532
535
  // Drawing Methods
533
- drawLine(e, t, s, r, n) {
534
- const o = document.createElementNS(u, "line");
535
- 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
+ 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);
536
539
  }
537
540
  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;
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;
540
543
  }
541
544
  drawGlyph(e, t, s) {
542
545
  s = {
@@ -544,14 +547,22 @@ class b {
544
547
  yOffset: 0,
545
548
  ...s
546
549
  };
547
- const r = document.createElementNS(u, "use");
550
+ const r = document.createElementNS(g, "use");
548
551
  r.setAttribute("href", `#glyph-${e}`), (s.xOffset || s.yOffset) && r.setAttribute("transform", `translate(${s.xOffset}, ${s.yOffset})`), t.appendChild(r);
549
552
  }
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;
556
+ }
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;
560
+ }
550
561
  destroy() {
551
562
  this.rootElementRef && this.svgElementRef && this.rootElementRef.contains(this.svgElementRef) && this.rootElementRef.removeChild(this.svgElementRef);
552
563
  }
553
564
  }
554
- const j = [
565
+ const It = [
555
566
  "CLEF_TREBLE",
556
567
  "CLEF_BASS",
557
568
  "CLEF_ALTO",
@@ -566,7 +577,7 @@ const j = [
566
577
  "ACCIDENTAL_DOUBLE_SHARP",
567
578
  "ACCIDENTAL_DOUBLE_FLAT"
568
579
  ];
569
- class et {
580
+ class Rt {
570
581
  svgRendererInstance;
571
582
  strategyInstance;
572
583
  noteRendererInstance;
@@ -591,44 +602,44 @@ class et {
591
602
  staffColor: "black",
592
603
  staffBackgroundColor: "transparent",
593
604
  ...t
594
- }, this.svgRendererInstance = new b(e, {
605
+ }, this.svgRendererInstance = new L(e, {
595
606
  width: this.options.width,
596
607
  height: 100,
597
608
  scale: this.options.scale,
598
609
  staffColor: this.options.staffColor,
599
610
  staffBackgroundColor: this.options.staffBackgroundColor,
600
- useGlyphs: j
611
+ useGlyphs: It
601
612
  });
602
613
  const s = this.svgRendererInstance.rootSvgElement;
603
614
  switch (this.options.staffType) {
604
615
  case "grand":
605
- this.strategyInstance = new x(this.svgRendererInstance, "grand");
616
+ this.strategyInstance = new tt(this.svgRendererInstance, "grand");
606
617
  break;
607
618
  case "bass":
608
- this.strategyInstance = new A(this.svgRendererInstance, "bass");
619
+ this.strategyInstance = new _(this.svgRendererInstance, "bass");
609
620
  break;
610
621
  case "treble":
611
- this.strategyInstance = new A(this.svgRendererInstance, "treble");
622
+ this.strategyInstance = new _(this.svgRendererInstance, "treble");
612
623
  break;
613
624
  case "alto":
614
- this.strategyInstance = new A(this.svgRendererInstance, "alto");
625
+ this.strategyInstance = new _(this.svgRendererInstance, "alto");
615
626
  break;
616
627
  default:
617
628
  throw new Error(`The staff type ${this.options.staffType} is not supported. Please use "treble", "bass", "alto", or "grand".`);
618
629
  }
619
- if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new U(this.svgRendererInstance, this.strategyInstance), this.options.spaceAbove) {
620
- const n = this.options.spaceAbove * 10;
621
- this.svgRendererInstance.addTotalRootSvgYOffset(n);
630
+ if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new et(this.svgRendererInstance, this.strategyInstance), this.options.spaceAbove) {
631
+ const o = this.options.spaceAbove * 10;
632
+ this.svgRendererInstance.addTotalRootSvgYOffset(o);
622
633
  }
623
634
  if (this.options.spaceBelow) {
624
- let n = this.options.spaceBelow * 10;
625
- this.options.staffType === "grand" && (n -= 10 / 2), this.svgRendererInstance.addTotalRootSvgHeight(n);
635
+ let o = this.options.spaceBelow * 10;
636
+ this.options.staffType === "grand" && (o -= 10 / 2), this.svgRendererInstance.addTotalRootSvgHeight(o);
626
637
  }
627
638
  let r = 0;
628
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);
629
640
  }
630
641
  createKeySignature(e) {
631
- return k(this.svgRendererInstance, this.strategyInstance, e, M);
642
+ return ft(this.svgRendererInstance, this.strategyInstance, e, lt);
632
643
  }
633
644
  /**
634
645
  * Draws a note on the staff.
@@ -652,20 +663,20 @@ class et {
652
663
  */
653
664
  drawNote(e) {
654
665
  const t = Array.isArray(e) ? e : [e], s = this.svgRendererInstance.getLayerByName("notes"), r = [];
655
- for (const n of t) {
656
- let o;
666
+ for (const o of t) {
667
+ let n;
657
668
  try {
658
- o = this.noteRendererInstance.renderNote(n);
659
- } catch (a) {
660
- throw r.length > 0 && this.svgRendererInstance.commitElementsToDOM(r, s), a;
669
+ n = this.noteRendererInstance.renderNote(o);
670
+ } catch (i) {
671
+ throw r.length > 0 && this.svgRendererInstance.commitElementsToDOM(r, s), i;
661
672
  }
662
- o.noteGroup.setAttribute("transform", `translate(${this.noteCursorX + o.accidentalOffset}, ${o.noteYPos})`), this.noteEntries.push({
663
- gElement: o.noteGroup,
664
- note: o.noteObj,
665
- xPos: this.noteCursorX + o.accidentalOffset,
666
- yPos: o.noteYPos,
667
- accidentalXOffset: o.accidentalOffset
668
- }), this.noteCursorX += 28 + o.accidentalOffset, r.push(o.noteGroup);
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);
669
680
  }
670
681
  this.svgRendererInstance.commitElementsToDOM(r, s);
671
682
  }
@@ -689,7 +700,7 @@ class et {
689
700
  const t = this.svgRendererInstance.getLayerByName("notes"), s = this.noteRendererInstance.renderChord(e);
690
701
  s.noteGroup.setAttribute("transform", `translate(${this.noteCursorX + s.accidentalOffset}, 0)`), this.noteEntries.push({
691
702
  gElement: s.noteGroup,
692
- note: O(e[0]),
703
+ note: P(e[0]),
693
704
  xPos: this.noteCursorX + s.accidentalOffset,
694
705
  yPos: 0,
695
706
  accidentalXOffset: s.accidentalOffset
@@ -703,16 +714,16 @@ class et {
703
714
  const e = this.options.width - this.noteStartX, t = this.noteEntries.length;
704
715
  if (t <= 0 || e <= 0) return;
705
716
  const s = Math.round(e / t);
706
- 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;
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;
708
719
  return {
709
- entry: n,
720
+ entry: o,
710
721
  newX: l,
711
- isChord: n.gElement.classList.contains("chord")
722
+ isChord: o.gElement.classList.contains("chord")
712
723
  };
713
- }).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;
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;
716
727
  });
717
728
  }
718
729
  /**
@@ -740,11 +751,11 @@ class et {
740
751
  */
741
752
  changeNoteByIndex(e, t) {
742
753
  if (t >= this.noteEntries.length) throw new Error("Note index was out of bounds.");
743
- const s = this.noteEntries[t], r = this.noteRendererInstance.renderNote(e), o = s.xPos - s.accidentalXOffset + r.accidentalOffset;
744
- r.noteGroup.setAttribute("transform", `translate(${o}, ${r.noteYPos})`), this.svgRendererInstance.getLayerByName("notes").replaceChild(r.noteGroup, s.gElement), this.noteEntries[t] = {
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] = {
745
756
  gElement: r.noteGroup,
746
757
  note: r.noteObj,
747
- xPos: o,
758
+ xPos: n,
748
759
  yPos: r.noteYPos,
749
760
  accidentalXOffset: r.accidentalOffset
750
761
  };
@@ -768,11 +779,11 @@ class et {
768
779
  changeChordByIndex(e, t) {
769
780
  if (t >= this.noteEntries.length) throw new Error("Chord index was out of bounds.");
770
781
  if (e.length < 2) throw new Error("Notes provided need to be more than one to be considered a chord.");
771
- const s = this.noteEntries[t], r = this.noteRendererInstance.renderChord(e), o = s.xPos - s.accidentalXOffset + r.accidentalOffset;
772
- r.noteGroup.setAttribute("transform", `translate(${o}, 0)`), this.svgRendererInstance.getLayerByName("notes").replaceChild(r.noteGroup, s.gElement), this.noteEntries[t] = {
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] = {
773
784
  gElement: r.noteGroup,
774
- note: O(e[0]),
775
- xPos: o,
785
+ note: P(e[0]),
786
+ xPos: n,
776
787
  yPos: 0,
777
788
  accidentalXOffset: r.accidentalOffset
778
789
  };
@@ -807,7 +818,7 @@ class et {
807
818
  this.noteEntries = [], this.svgRendererInstance.destroy();
808
819
  }
809
820
  }
810
- const d = 30, H = 19, g = 12, K = 4, Q = 6, P = 1, m = 38, z = [
821
+ const A = 30, z = 19, O = 12, _t = 4, Tt = 6, j = 1, b = 38, mt = [
811
822
  "TIME_4",
812
823
  "TIME_3",
813
824
  "NOTE_HEAD_WHOLE",
@@ -819,7 +830,7 @@ const d = 30, H = 19, g = 12, K = 4, Q = 6, P = 1, m = 38, z = [
819
830
  "REST_QUARTER",
820
831
  "REST_EIGHTH"
821
832
  ];
822
- class st {
833
+ class yt {
823
834
  rendererInstance;
824
835
  options;
825
836
  barSpacing;
@@ -830,7 +841,7 @@ class st {
830
841
  currentBeatCount = 0;
831
842
  currentBeatUICount = 0;
832
843
  currentBeatUIElement = null;
833
- currentBeatUIXPos = m;
844
+ currentBeatUIXPos = b;
834
845
  /**
835
846
  * Creates an instance of a RhythmStaff, A single staff that will automatically apply positioning of elements based on the duration of a note.
836
847
  *
@@ -850,13 +861,13 @@ class st {
850
861
  staffBackgroundColor: "white",
851
862
  currentBeatUIColor: "#24ff7450",
852
863
  ...t
853
- }, this.rendererInstance = new b(e, {
864
+ }, this.rendererInstance = new L(e, {
854
865
  width: this.options.width,
855
866
  height: 100,
856
867
  scale: this.options.scale,
857
868
  staffColor: this.options.staffColor,
858
869
  staffBackgroundColor: this.options.staffBackgroundColor,
859
- useGlyphs: z
870
+ useGlyphs: mt
860
871
  });
861
872
  const s = this.rendererInstance.rootSvgElement;
862
873
  let r = "TIME_4";
@@ -872,41 +883,41 @@ class st {
872
883
  }
873
884
  if (this.options.barsCount < 1 || this.options.barsCount > 3) throw new Error(`Bars count ${this.options.barsCount} not supported. Please use 1 - 3`);
874
885
  if (this.options.spaceAbove) {
875
- const p = this.options.spaceAbove * 10;
876
- this.rendererInstance.addTotalRootSvgYOffset(p);
886
+ const u = this.options.spaceAbove * 10;
887
+ this.rendererInstance.addTotalRootSvgYOffset(u);
877
888
  }
878
889
  if (this.options.spaceBelow) {
879
- let p = this.options.spaceBelow * 10;
880
- this.rendererInstance.addTotalRootSvgHeight(p);
890
+ let u = this.options.spaceBelow * 10;
891
+ this.rendererInstance.addTotalRootSvgHeight(u);
881
892
  }
882
- const n = this.rendererInstance.getLayerByName("staff");
883
- this.rendererInstance.addTotalRootSvgHeight(d * 2);
884
- const o = this.rendererInstance.createGroup("time-signature");
885
- 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;
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;
890
901
  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);
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);
895
906
  }
896
907
  createBeatUIElement() {
897
908
  const e = this.rendererInstance.getLayerByName("ui");
898
909
  this.currentBeatUIElement = this.rendererInstance.drawRect(
899
910
  this.quarterNoteSpacing / 2,
900
- d * 2,
911
+ A * 2,
901
912
  e,
902
913
  {
903
- x: m,
914
+ x: b,
904
915
  fill: this.options.currentBeatUIColor
905
916
  }
906
917
  );
907
918
  }
908
919
  handleNewBar() {
909
- this.noteCursorX += g;
920
+ this.noteCursorX += O;
910
921
  }
911
922
  // Translates group, returns cursor increment amount
912
923
  translateGroupByDuration(e, t) {
@@ -965,15 +976,15 @@ class st {
965
976
  let s = e;
966
977
  for (; s > 0; ) {
967
978
  const r = this.rendererInstance.createGroup("rest");
968
- 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);
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);
970
981
  }
971
982
  return t;
972
983
  }
973
984
  renderBeamRect(e, t, s, r) {
974
985
  this.rendererInstance.drawRect(
975
986
  e - t,
976
- K,
987
+ _t,
977
988
  s,
978
989
  {
979
990
  x: 10,
@@ -1002,23 +1013,23 @@ class st {
1002
1013
  */
1003
1014
  drawNote(e) {
1004
1015
  const t = Array.isArray(e) ? e : [e], s = this.rendererInstance.getLayerByName("notes"), r = [];
1005
- for (const n of t) {
1006
- let o = "w";
1016
+ for (const o of t) {
1017
+ let n = "w";
1007
1018
  try {
1008
- o = N(n);
1009
- } catch (f) {
1010
- throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), f;
1019
+ n = R(o);
1020
+ } catch (d) {
1021
+ throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), d;
1011
1022
  }
1012
- const a = E[o];
1023
+ const i = p[n];
1013
1024
  if (this.currentBeatCount >= this.maxBeatCount)
1014
1025
  throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), new Error("Max beat count reached. Can't add additional notes.");
1015
1026
  this.checkAndCreateNewBar();
1016
- const i = this.checkAndFillBarWithRests(a);
1017
- i && i.forEach((f) => {
1018
- r.push(f), this.noteEntries.push(f);
1027
+ const a = this.checkAndFillBarWithRests(i);
1028
+ a && a.forEach((d) => {
1029
+ r.push(d), this.noteEntries.push(d);
1019
1030
  });
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);
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);
1022
1033
  }
1023
1034
  this.rendererInstance.commitElementsToDOM(r, s);
1024
1035
  }
@@ -1042,21 +1053,21 @@ class st {
1042
1053
  */
1043
1054
  drawRest(e) {
1044
1055
  const t = Array.isArray(e) ? e : [e], s = this.rendererInstance.getLayerByName("notes"), r = [];
1045
- for (const n of t) {
1046
- let o = "w";
1056
+ for (const o of t) {
1057
+ let n = "w";
1047
1058
  try {
1048
- o = N(n);
1049
- } catch (f) {
1050
- throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), f;
1059
+ n = R(o);
1060
+ } catch (d) {
1061
+ throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), d;
1051
1062
  }
1052
- const a = this.rendererInstance.createGroup("rest"), i = E[o], c = i * this.quarterNoteSpacing;
1063
+ const i = this.rendererInstance.createGroup("rest"), a = p[n], c = a * this.quarterNoteSpacing;
1053
1064
  if (this.currentBeatCount >= this.maxBeatCount)
1054
1065
  throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), new Error("Max beat count reached. Can't add additional notes.");
1055
1066
  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);
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);
1060
1071
  }
1061
1072
  this.rendererInstance.commitElementsToDOM(r, s);
1062
1073
  }
@@ -1083,13 +1094,13 @@ class st {
1083
1094
  if (this.currentBeatCount >= this.maxBeatCount)
1084
1095
  throw new Error("Max beat count reached. Can't add additional beamed note.");
1085
1096
  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");
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");
1088
1099
  c.setAttribute("transform", `translate(${this.noteCursorX}, 0)`);
1089
1100
  let l = 0;
1090
- for (let f = 0; f < i; f++)
1091
- 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);
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);
1093
1104
  }
1094
1105
  /**
1095
1106
  * Will increment the UI showing the current beat in quarters. Once exceeded, must be reset with `resetCurrentBeatUI()`
@@ -1100,14 +1111,14 @@ class st {
1100
1111
  this.currentBeatUIElement.setAttribute("display", "none");
1101
1112
  return;
1102
1113
  }
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());
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());
1104
1115
  }
1105
1116
  /**
1106
1117
  * Resets the ui showing the current beat value.
1107
1118
  * @returns void
1108
1119
  */
1109
1120
  resetCurrentBeatUI() {
1110
- this.currentBeatUICount = 0, this.currentBeatUIXPos = m, this.currentBeatUIElement && (this.currentBeatUIElement.setAttribute("display", "none"), this.currentBeatUIElement.setAttribute("x", this.currentBeatUIXPos.toString()));
1121
+ this.currentBeatUICount = 0, this.currentBeatUIXPos = b, this.currentBeatUIElement && (this.currentBeatUIElement.setAttribute("display", "none"), this.currentBeatUIElement.setAttribute("x", this.currentBeatUIXPos.toString()));
1111
1122
  }
1112
1123
  /**
1113
1124
  * Clears staff of notes and resets internal positioning.
@@ -1124,7 +1135,7 @@ class st {
1124
1135
  this.noteEntries = [], this.rendererInstance.destroy();
1125
1136
  }
1126
1137
  }
1127
- const J = [
1138
+ const Ct = [
1128
1139
  "CLEF_TREBLE",
1129
1140
  "CLEF_BASS",
1130
1141
  "CLEF_ALTO",
@@ -1138,8 +1149,8 @@ const J = [
1138
1149
  "ACCIDENTAL_NATURAL",
1139
1150
  "ACCIDENTAL_DOUBLE_SHARP",
1140
1151
  "ACCIDENTAL_DOUBLE_FLAT"
1141
- ], T = 60, tt = T;
1142
- class rt {
1152
+ ], N = 60, St = N;
1153
+ class wt {
1143
1154
  svgRendererInstance;
1144
1155
  strategyInstance;
1145
1156
  noteRendererInstance;
@@ -1166,32 +1177,32 @@ class rt {
1166
1177
  staffColor: "black",
1167
1178
  staffBackgroundColor: "transparent",
1168
1179
  ...t
1169
- }, this.svgRendererInstance = new b(e, {
1180
+ }, this.svgRendererInstance = new L(e, {
1170
1181
  width: this.options.width,
1171
1182
  height: 100,
1172
1183
  scale: this.options.scale,
1173
1184
  staffColor: this.options.staffColor,
1174
1185
  staffBackgroundColor: this.options.staffBackgroundColor,
1175
- useGlyphs: J
1186
+ useGlyphs: Ct
1176
1187
  });
1177
1188
  const s = this.svgRendererInstance.rootSvgElement;
1178
1189
  switch (this.options.staffType) {
1179
1190
  case "grand":
1180
- this.strategyInstance = new x(this.svgRendererInstance, "grand");
1191
+ this.strategyInstance = new tt(this.svgRendererInstance, "grand");
1181
1192
  break;
1182
1193
  case "bass":
1183
- this.strategyInstance = new A(this.svgRendererInstance, "bass");
1194
+ this.strategyInstance = new _(this.svgRendererInstance, "bass");
1184
1195
  break;
1185
1196
  case "treble":
1186
- this.strategyInstance = new A(this.svgRendererInstance, "treble");
1197
+ this.strategyInstance = new _(this.svgRendererInstance, "treble");
1187
1198
  break;
1188
1199
  case "alto":
1189
- this.strategyInstance = new A(this.svgRendererInstance, "alto");
1200
+ this.strategyInstance = new _(this.svgRendererInstance, "alto");
1190
1201
  break;
1191
1202
  default:
1192
1203
  throw new Error(`The staff type ${this.options.staffType} is not supported. Please use "treble", "bass", "alto", or "grand".`);
1193
1204
  }
1194
- if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new U(this.svgRendererInstance, this.strategyInstance), this.options.spaceAbove) {
1205
+ if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new et(this.svgRendererInstance, this.strategyInstance), this.options.spaceAbove) {
1195
1206
  const r = this.options.spaceAbove * 10;
1196
1207
  this.svgRendererInstance.addTotalRootSvgYOffset(r);
1197
1208
  }
@@ -1202,10 +1213,10 @@ class rt {
1202
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);
1203
1214
  }
1204
1215
  renderFirstNoteGroups() {
1205
- const e = this.options.width - this.options.noteStartX + tt;
1216
+ const e = this.options.width - this.options.noteStartX + St;
1206
1217
  for (; this.noteBuffer.length > 0 && this.noteCursorX < e; )
1207
- this.renderNextNote(), this.noteCursorX += T;
1208
- this.activeEntries.length > 1 && (this.noteCursorX -= T);
1218
+ this.renderNextNote(), this.noteCursorX += N;
1219
+ this.activeEntries.length > 1 && (this.noteCursorX -= N);
1209
1220
  }
1210
1221
  renderNextNote() {
1211
1222
  if (this.noteBuffer.length < 1) return;
@@ -1264,7 +1275,7 @@ class rt {
1264
1275
  return;
1265
1276
  }
1266
1277
  this.activeEntries.forEach((t) => {
1267
- t.xPos -= T, t.noteWrapper.style.transform = `translate(${t.xPos}px, 0px)`;
1278
+ t.xPos -= N, t.noteWrapper.style.transform = `translate(${t.xPos}px, 0px)`;
1268
1279
  });
1269
1280
  const e = this.activeEntries[0];
1270
1281
  e.xPos <= 0 && (this.notesLayer.removeChild(e.noteWrapper), this.activeEntries.shift()), this.renderNextNote();
@@ -1284,8 +1295,297 @@ class rt {
1284
1295
  this.svgRendererInstance.destroy(), this.activeEntries = [], this.noteBuffer = [];
1285
1296
  }
1286
1297
  }
1298
+ const Nt = /^[xX\da-zA-Z]+$/, Lt = /^[\d]+$/;
1299
+ function K(h, e) {
1300
+ const t = [];
1301
+ for (let s = 0; s < h.length; s++)
1302
+ t.push({
1303
+ fret: h[s],
1304
+ finger: e[s]
1305
+ });
1306
+ return t;
1307
+ }
1308
+ function Q(h, e) {
1309
+ const t = h.filter((o) => o.toLowerCase() !== "x" && o !== "0").map((o) => parseInt(o, 36));
1310
+ if (t.length === 0) return 1;
1311
+ const s = Math.min(...t);
1312
+ return Math.max(...t) <= e ? 1 : s;
1313
+ }
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("");
1317
+ }
1318
+ function G(h) {
1319
+ if (!Lt.test(h)) throw new Error("Invalid fingers string. Only digits are allowed.");
1320
+ return h.split("");
1321
+ }
1322
+ class Ot {
1323
+ svgRendererInstance;
1324
+ options;
1325
+ chordEntries = [];
1326
+ cursorX = 0;
1327
+ cursorY = 0;
1328
+ // Fixed per-instance sizing, derived once from options
1329
+ diagramWidth;
1330
+ diagramHeight;
1331
+ gridTopY;
1332
+ rowHeight;
1333
+ /**
1334
+ * Creates an instance of a GuitarChord diagram renderer.
1335
+ *
1336
+ * @param rootElementCtx - The element (div) reference that the chord diagram(s) will be appended to.
1337
+ * @param options - Optional configuration. Can adjust total width, scale, string/fret count, and coloring.
1338
+ * All config options are in the type GuitarChordOptions.
1339
+ */
1340
+ constructor(e, t) {
1341
+ if (this.options = {
1342
+ width: 300,
1343
+ scale: 1,
1344
+ stringCount: st,
1345
+ fretCount: rt,
1346
+ stringLabels: [],
1347
+ color: "black",
1348
+ backgroundColor: "transparent",
1349
+ ...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)
1351
+ 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, {
1353
+ width: this.options.width,
1354
+ height: 100,
1355
+ scale: this.options.scale,
1356
+ staffColor: this.options.color,
1357
+ staffBackgroundColor: this.options.backgroundColor,
1358
+ useGlyphs: []
1359
+ });
1360
+ const s = this.svgRendererInstance.rootSvgElement;
1361
+ this.svgRendererInstance.setTotalRootSvgHeight(this.rowHeight), this.svgRendererInstance.applySizingToRootSvg(), this.svgRendererInstance.commitElementsToDOM(s);
1362
+ }
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 });
1371
+ 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
+ }
1383
+ }
1384
+ }
1385
+ }
1386
+ drawStringLabels(e, t) {
1387
+ 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 });
1394
+ }
1395
+ }
1396
+ // Passed in 'from' and 'to' index values are zero-based
1397
+ drawBarre(e, t) {
1398
+ const s = t.fret;
1399
+ if (t.fromIndex < 0 || t.toIndex >= this.options.stringCount || t.fromIndex >= t.toIndex)
1400
+ throw new Error(`Barre fret error: Invalid string range ${t.fromIndex + 1}:${t.toIndex + 1}.`);
1401
+ if (s < t.startingFret || s > t.startingFret + (this.options.fretCount - 1))
1402
+ 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
+ }
1415
+ }
1416
+ // Builds a single chord diagram's group element: grid, nut/fret-position label, and per-string markers.
1417
+ 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, {
1431
+ anchor: "start",
1432
+ fontSize: ct,
1433
+ fontWeight: "bold"
1434
+ });
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);
1438
+ }
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
1446
+ });
1447
+ }), r;
1448
+ }
1449
+ // 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.
1451
+ 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;
1458
+ });
1459
+ const e = this.cursorY + this.rowHeight;
1460
+ this.svgRendererInstance.setTotalRootSvgHeight(e), this.svgRendererInstance.applySizingToRootSvg();
1461
+ }
1462
+ /**
1463
+ * Adds a new chord diagram. Diagrams are placed left-to-right in the order added, wrapping to a
1464
+ * new row automatically once the configured width is exceeded.
1465
+ *
1466
+ * @param frets - A string, with each value being ordered low-to-high (e.g. first position in string 0 is the low E string)
1467
+ * * `x` - muted string
1468
+ * * `0` - open string
1469
+ * * `1...n` - fretted at the given absolute fret number (e.g. `3`)
1470
+ * @param fingers - A string, with each value being ordered low-to-high (e.g. first position in string 0 is the low E string)
1471
+ * * `0` - No finger labeled
1472
+ * * `1...n` - Finger labeled as number provided
1473
+ *
1474
+ * @param options - Optional per-chord settings: `startFret` (default `1`, for diagrams higher up the neck)
1475
+ * and `label` (a chord name drawn above the diagram).
1476
+ *
1477
+ * @returns The index of the newly added chord, for later use with the CRUD-by-index methods.
1478
+ *
1479
+ * @throws {Error} If fret or finger's string length doesn't match the configured string count.
1480
+ *
1481
+ * @example
1482
+ * // Draw an open C major chord
1483
+ * guitarChord.addChord("x32010", "032010", { label: "C" });
1484
+ */
1485
+ addChord(e, t, s) {
1486
+ const r = v(e), o = G(t);
1487
+ 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,
1494
+ xPos: 0,
1495
+ yPos: 0
1496
+ }), this.relayoutChords(), this.chordEntries.length - 1;
1497
+ }
1498
+ /**
1499
+ * Replaces the chord diagram at the specified index with a new one, in place.
1500
+ *
1501
+ * @param frets - A string, with each value being ordered low-to-high (e.g. first position in string 0 is the low E string)
1502
+ * * `x` - muted string
1503
+ * * `0` - open string
1504
+ * * `1...n` - fretted at the given absolute fret number (e.g. `3`)
1505
+ * @param fingers - A string, with each value being ordered low-to-high (e.g. first position in string 0 is the low E string)
1506
+ * * `0` - No finger labeled
1507
+ * * `1...n` - Finger labeled as number provided
1508
+ *
1509
+ * @param chordIndex - The index of the chord to replace (as returned by addChord).
1510
+ *
1511
+ * @param options - Optional per-chord settings, see addChord.
1512
+ *
1513
+ * @returns void
1514
+ *
1515
+ * @throws {Error} If the index is out of bounds, or if chordDef is invalid (see addChord).
1516
+ *
1517
+ * @example
1518
+ * // Change chord at index 0 to a D major chord
1519
+ * guitarChord.modifyChordByIndex("xx0232", "000132", 0, { label: "D" });
1520
+ *
1521
+ */
1522
+ modifyChordByIndex(e, t, s, r) {
1523
+ 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,
1532
+ xPos: i.xPos,
1533
+ yPos: i.yPos
1534
+ }, this.relayoutChords();
1535
+ }
1536
+ /**
1537
+ * Removes the chord diagram at the specified index. Remaining chords are re-flowed to close the gap.
1538
+ * @param chordIndex - The index of the chord to remove.
1539
+ * @returns void
1540
+ * @throws {Error} If the index is out of bounds.
1541
+ */
1542
+ removeChordByIndex(e) {
1543
+ if (e >= this.chordEntries.length || e < 0) throw new Error("Chord index was out of bounds.");
1544
+ this.chordEntries[e].gElement.remove(), this.chordEntries.splice(e, 1), this.relayoutChords();
1545
+ }
1546
+ /**
1547
+ * Removes all chord diagrams and resets internal positioning.
1548
+ * @returns void
1549
+ */
1550
+ clearAllChords() {
1551
+ this.svgRendererInstance.getLayerByName("notes").replaceChildren(), this.chordEntries = [], this.cursorX = 0, this.cursorY = 0, this.svgRendererInstance.setTotalRootSvgHeight(this.rowHeight), this.svgRendererInstance.applySizingToRootSvg();
1552
+ }
1553
+ /**
1554
+ * * Used to automatically determine options for creating barre lines.
1555
+ * * The returned value then can be used in addChord and modifyChord methods.
1556
+ * @returns GuitarBarreDef[]
1557
+ */
1558
+ determineBarreOptions(e, t, s) {
1559
+ const r = v(e), o = G(t), n = [];
1560
+ 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
+ }
1568
+ }
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;
1577
+ }
1578
+ /**
1579
+ * Removes the root svg element and cleans up arrays.
1580
+ * @returns void
1581
+ */
1582
+ destroy() {
1583
+ this.chordEntries = [], this.svgRendererInstance.destroy();
1584
+ }
1585
+ }
1287
1586
  export {
1288
- et as MusicStaff,
1289
- st as RhythmStaff,
1290
- rt as ScrollingStaff
1587
+ Ot as GuitarChord,
1588
+ Rt as MusicStaff,
1589
+ yt as RhythmStaff,
1590
+ wt as ScrollingStaff
1291
1591
  };