vector-score 1.0.2 → 1.1.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.
package/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  ![Alt Text](https://raw.githubusercontent.com/DrakeB1234/VectorScore/master/public/vector-score-icon.svg)
2
2
 
3
3
  # Vector Score
4
+ ![NPM Version](https://img.shields.io/npm/v/vector-score)
5
+ [![Bundlephobia](https://img.shields.io/bundlephobia/minzip/vector-score)](https://bundlephobia.com/package/vector-score)
6
+ ![NPM Downloads](https://img.shields.io/npm/d18m/vector-score)
4
7
 
5
8
  A lightweight, SVG-based TypeScript library for rendering musical staves, notes, and rhythm patterns in the browser.
6
9
 
@@ -56,7 +59,8 @@ const staff = new MusicStaff(container, {
56
59
  staffType: 'treble', // 'treble', 'bass', 'alto', or 'grand'
57
60
  width: 400,
58
61
  scale: 1.2,
59
- spaceBelow: 1
62
+ spaceBelow: 1,
63
+ keySignature: "Bb"
60
64
  });
61
65
 
62
66
  // Draw a C Minor scale (quarter notes)
@@ -224,10 +228,11 @@ Notes are defined using a specific string format parsed by the library:
224
228
  ### MusicStaffOptions
225
229
  * `width`: Total width of the SVG in pixels.
226
230
  * `scale`: Zoom factor (default: 1).
227
- * `noteStartX`: Position where notes start to draw.
228
231
  * `staffType`: `'treble' | 'bass' | 'alto' | 'grand'`.
232
+ * `keySignature`: Change key signature to display on the staff.
229
233
  * `spaceAbove`: Padding units above the staff (in staff line spaces).
230
234
  * `spaceBelow`: Padding units below the staff (in staff line spaces).
235
+ * `noteStartX`: Position where notes start to draw.
231
236
  * `staffColor`: CSS color string for lines and notes.
232
237
  * `staffBackgroundColor`: CSS color string for background.
233
238
 
@@ -4,6 +4,7 @@ export type MusicStaffOptions = {
4
4
  scale?: number;
5
5
  noteStartX?: number;
6
6
  staffType?: StaffTypes;
7
+ keySignature?: string;
7
8
  spaceAbove?: number;
8
9
  spaceBelow?: number;
9
10
  staffColor?: string;
@@ -24,6 +25,7 @@ export default class MusicStaff {
24
25
  * @param options - Optional configuration settings. Can adjust staff type (treble, bass, alto, grand), width, scale, spaces above/below, etc. All config options are in the type MusicStaffOptions
25
26
  */
26
27
  constructor(rootElementCtx: HTMLElement, options?: MusicStaffOptions);
28
+ private createKeySignature;
27
29
  /**
28
30
  * Draws a note on the staff.
29
31
  * @param notes - A single string OR array of note strings in the format `[Root][Accidental?][Octave][Duration?]`.
@@ -0,0 +1,9 @@
1
+ import { default as SVGRenderer } from '../classes/SVGRenderer';
2
+ import { StaffStrategy } from '../strategies/StrategyInterface';
3
+ import { AccidentalType, KeySignatureDef, NoteNames, StaffTypes } from '../types';
4
+ export declare const KEY_SIGNATURE_START_X = 40;
5
+ export declare const KEY_SIGNATURE_ORDER: Record<AccidentalType, NoteNames[]>;
6
+ export declare const KEY_SIGNATURES: Record<string, KeySignatureDef>;
7
+ export declare const KEY_SIG_OCTAVES: Record<StaffTypes, Record<AccidentalType, number[]>>;
8
+ export declare function parseKeySignature(key: string): KeySignatureDef;
9
+ export declare function drawKeySignature(svgRenderer: SVGRenderer, strategy: StaffStrategy, key: string, startX: number): number;
@@ -4,6 +4,5 @@ export declare function parseNoteString(noteString: string): NoteObj;
4
4
  export declare function parseDurationNoteString(note: string): Durations;
5
5
  export declare function parseRestString(rest: string): Durations;
6
6
  export declare function getGlyphNameByClef(clef: string): GlyphNames;
7
- export declare function getNoteSpacingFromReference(referenceNote: NoteObj, targetNote: NoteObj): number;
8
7
  export declare function noteToAbsoluteSemitone(note: NoteObj): number;
9
- export declare function getNameOctaveIdx(name: string, octave: number): number;
8
+ export declare function getNoteSpacingFromReference(referenceNote: Pick<NoteObj, "name" | "octave">, targetNote: Pick<NoteObj, "name" | "octave">): number;
@@ -1,14 +1,16 @@
1
1
  import { default as SVGRenderer } from '../classes/SVGRenderer';
2
- import { NoteObj, StaffTypes } from '../types';
2
+ import { AccidentalType, NoteObj, StaffTypes } from '../types';
3
3
  import { LedgerLineEntry, StaffStrategy } from './StrategyInterface';
4
4
  export default class GrandStaffStrategy implements StaffStrategy {
5
5
  private params;
6
6
  private rendererRef;
7
7
  private width;
8
+ private trebleStaffHeight;
8
9
  constructor(rendererRef: SVGRenderer, staffType: StaffTypes);
9
10
  private drawStaffLines;
10
11
  drawStaff: (width: number) => void;
11
12
  shouldNoteFlip(noteYPos: number): boolean;
12
13
  getLedgerLinesX(note: Omit<NoteObj, "accidental">, yPos: number): LedgerLineEntry[];
13
14
  calculateNoteYPos: (note: Omit<NoteObj, "accidental">) => number;
15
+ getKeySignatureYPositions(type: AccidentalType, count: number): number[][];
14
16
  }
@@ -1,5 +1,5 @@
1
1
  import { default as SVGRenderer } from '../classes/SVGRenderer';
2
- import { NoteObj, StaffTypes } from '../types';
2
+ import { AccidentalType, NoteObj, StaffTypes } from '../types';
3
3
  import { LedgerLineEntry, StaffStrategy } from './StrategyInterface';
4
4
  export default class SingleStaffStrategy implements StaffStrategy {
5
5
  private params;
@@ -9,4 +9,5 @@ export default class SingleStaffStrategy implements StaffStrategy {
9
9
  shouldNoteFlip(noteYPos: number): boolean;
10
10
  getLedgerLinesX(note: Omit<NoteObj, "accidental">, yPos: number): LedgerLineEntry[];
11
11
  calculateNoteYPos: (note: Omit<NoteObj, "accidental">) => number;
12
+ getKeySignatureYPositions(type: AccidentalType, count: number): number[][];
12
13
  }
@@ -1,9 +1,10 @@
1
- import { NoteObj, StaffTypes } from '../types';
1
+ import { AccidentalType, NoteObj, StaffTypes } from '../types';
2
2
  export interface StaffStrategy {
3
3
  drawStaff(width: number): void;
4
4
  calculateNoteYPos(note: Omit<NoteObj, "accidental">): number;
5
5
  getLedgerLinesX(note: Omit<NoteObj, "accidental">, yPos: number): LedgerLineEntry[];
6
6
  shouldNoteFlip(noteYPos: number): boolean;
7
+ getKeySignatureYPositions(type: AccidentalType, count: number): number[][];
7
8
  }
8
9
  export type StaffParams = {
9
10
  staffType: StaffTypes;
package/dist/types.d.ts CHANGED
@@ -9,3 +9,8 @@ export type NoteNames = 'C' | 'D' | 'E' | 'F' | 'G' | 'A' | 'B';
9
9
  export type Durations = 'w' | 'h' | 'q' | 'e' | 's';
10
10
  export type Accidentals = '#' | 'b' | '##' | 'bb' | 'n';
11
11
  export type DurationsBeatValues = 4 | 2 | 1 | 0.5;
12
+ export type AccidentalType = "sharp" | "flat";
13
+ export type KeySignatureDef = {
14
+ type: AccidentalType;
15
+ count: number;
16
+ };
@@ -1,4 +1,4 @@
1
- const B = {
1
+ const I = {
2
2
  treble: {
3
3
  staffType: "treble",
4
4
  paddingTop: 13,
@@ -31,13 +31,66 @@ const B = {
31
31
  topLineYPos: 0,
32
32
  bottomLineYPos: 110
33
33
  }
34
- }, d = {
34
+ }, E = {
35
35
  w: 4,
36
36
  h: 2,
37
37
  q: 1,
38
38
  e: 0.5,
39
39
  s: 0.25
40
- }, X = {
40
+ }, w = 8, M = 40, X = {
41
+ sharp: ["F", "C", "G", "D", "A", "E", "B"],
42
+ flat: ["B", "E", "A", "D", "G", "C", "F"]
43
+ }, G = {
44
+ C: { type: "sharp", count: 0 },
45
+ G: { type: "sharp", count: 1 },
46
+ D: { type: "sharp", count: 2 },
47
+ A: { type: "sharp", count: 3 },
48
+ E: { type: "sharp", count: 4 },
49
+ B: { type: "sharp", count: 5 },
50
+ "F#": { type: "sharp", count: 6 },
51
+ F: { type: "flat", count: 1 },
52
+ Bb: { type: "flat", count: 2 },
53
+ Eb: { type: "flat", count: 3 },
54
+ Ab: { type: "flat", count: 4 },
55
+ Db: { type: "flat", count: 5 },
56
+ Gb: { type: "flat", count: 6 }
57
+ }, L = {
58
+ treble: {
59
+ sharp: [5, 5, 5, 5, 4, 5, 4],
60
+ // F5 C5 G5 D5 A4 E5 B4
61
+ flat: [4, 5, 4, 5, 4, 5, 4]
62
+ // B4 E5 A4 D5 G4 C5 F4
63
+ },
64
+ bass: {
65
+ sharp: [3, 3, 3, 3, 2, 3, 2],
66
+ // F3 C3 G3 D3 A2 E3 B2
67
+ flat: [2, 3, 2, 3, 2, 3, 3]
68
+ // B2 E3 A2 D3 G2 C3 F3
69
+ },
70
+ alto: {
71
+ sharp: [4, 4, 4, 4, 3, 4, 4],
72
+ // F5 C5 G5 D5 A4 E5 B4
73
+ flat: [4, 5, 4, 5, 4, 5, 4]
74
+ // B4 E5 A4 D5 G4 C5 F4
75
+ },
76
+ grand: { sharp: [], flat: [] }
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(", ")}`);
81
+ return e;
82
+ }
83
+ function k(h, e, t, s) {
84
+ const r = Y(t);
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 });
90
+ });
91
+ }), r.count * w;
92
+ }
93
+ const $ = {
41
94
  CLEF_TREBLE: {
42
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",
43
96
  xOffset: 0,
@@ -133,30 +186,26 @@ const B = {
133
186
  xOffset: 0,
134
187
  yOffset: 0
135
188
  }
136
- }, x = /^(?<name>[A-Ga-g])(?<accidental>##|bb|[#bn]?)(?<octave>\d)(?<duration>[whqeWHQE]?)$/, U = /^[whqeWHQE]$/, I = ["C", "D", "E", "F", "G", "A", "B"];
137
- function g(h) {
138
- const e = h.match(x);
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);
139
192
  if (!e || !e.groups)
140
193
  throw new Error(`Invalid note string format: ${h}. Expected format: [A-Ga-g][#|b]?[0-9][w|h|q|e].`);
141
- let { name: t, accidental: s, octave: r, duration: o } = e.groups;
142
- if (t = t.toUpperCase(), o = o.toLowerCase(), !t)
143
- throw new Error(`Invalid note name: ${t}. Valid note names are: C, D, E, F, G, A, B.`);
144
- if (!r)
145
- throw new Error(`Invalid octave: ${r}. Octave must be a number between 0 and 9.`);
146
- o || (o = "w");
147
- const n = {
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 = {
148
197
  name: t,
149
198
  octave: parseInt(r),
150
- duration: o
199
+ duration: n
151
200
  };
152
- return s && (n.accidental = s), n;
201
+ return s && (o.accidental = s), o;
153
202
  }
154
- function T(h) {
155
- const e = h.match(U);
203
+ function N(h) {
204
+ const e = h.match(Z);
156
205
  if (!e) throw new Error(`Invalid note duration '${h}'. Use w | h | q | e.`);
157
- return e.toString().toLowerCase();
206
+ return e[0].toString().toLowerCase();
158
207
  }
159
- function S(h) {
208
+ function R(h) {
160
209
  let e;
161
210
  switch (h) {
162
211
  case "treble":
@@ -172,26 +221,22 @@ function S(h) {
172
221
  if (!e) throw new Error(`Invalid clef type: ${h}. Valid clef types are: treble, bass, alto.`);
173
222
  return e;
174
223
  }
175
- function D(h, e) {
176
- const t = I.indexOf(h.name) - I.indexOf(e.name);
177
- let s = h.octave - e.octave;
178
- return s *= 7, t + s;
179
- }
180
- function R(h) {
181
- let e = I.indexOf(h.name);
224
+ function F(h) {
225
+ let e = y.indexOf(h.name);
182
226
  return e += h.octave * 12, e;
183
227
  }
184
- function y(h, e) {
185
- return I.findIndex((s) => s === h) + 1 + e * 7;
228
+ function _(h, e) {
229
+ return y.indexOf(h.name) - y.indexOf(e.name) + (h.octave - e.octave) * 7;
186
230
  }
187
- const N = 48, w = 40 + 30 / 2, b = 20, F = 90;
188
- class H {
231
+ const C = 48, v = 40 + 30 / 2, D = 20, B = 90;
232
+ class x {
189
233
  params;
190
234
  rendererRef;
191
235
  width = 0;
236
+ trebleStaffHeight = 0;
192
237
  constructor(e, t) {
193
238
  this.rendererRef = e;
194
- const s = B[t];
239
+ const s = I[t];
195
240
  if (!s) throw new Error(`Staff type ${t} is not supported`);
196
241
  this.params = s;
197
242
  }
@@ -205,52 +250,60 @@ class H {
205
250
  this.width = e;
206
251
  const t = this.rendererRef.getLayerByName("staff");
207
252
  let s = this.drawStaffLines(0, t), r = this.drawStaffLines(s + 30, t);
208
- this.rendererRef.drawLine(0, 0, 0, r, t), this.rendererRef.drawLine(this.width, 0, this.width, r, t);
209
- let o = r, n = 1;
210
- const a = S("treble"), i = S("bass");
211
- this.rendererRef.drawGlyph(a, t), this.rendererRef.drawGlyph(i, t, { yOffset: s + 30 }), o += this.params.paddingBottom + 1, n += this.params.paddingTop, this.rendererRef.addTotalRootSvgHeight(o), this.rendererRef.addTotalRootSvgYOffset(n);
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);
212
257
  };
213
258
  shouldNoteFlip(e) {
214
- const t = Math.abs(e - F), s = Math.abs(e - b);
215
- return e === w ? !1 : t <= s ? !(e >= F) : e <= b;
259
+ const t = Math.abs(e - B), s = Math.abs(e - D);
260
+ return e === v ? !1 : t <= s ? !(e >= B) : e <= D;
216
261
  }
217
262
  getLedgerLinesX(e, t) {
218
- const s = [], r = R(e);
219
- let o = e.duration === "w" ? 17 : 12.5;
220
- if (r === N)
221
- return s.push({ x1: -2, x2: o, yPos: 0 }), s;
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;
222
267
  if (t < this.params.topLineYPos) {
223
- let n = this.params.topLineYPos - 10;
224
- for (; n >= t; )
268
+ let o = this.params.topLineYPos - 10;
269
+ for (; o >= t; )
225
270
  s.push({
226
271
  x1: -2,
227
- x2: o,
228
- yPos: n - t
229
- }), n -= 10;
272
+ x2: n,
273
+ yPos: o - t
274
+ }), o -= 10;
230
275
  } else if (t > this.params.bottomLineYPos) {
231
- let n = this.params.bottomLineYPos + 10;
232
- for (; n <= t; )
276
+ let o = this.params.bottomLineYPos + 10;
277
+ for (; o <= t; )
233
278
  s.push({
234
279
  x1: -2,
235
- x2: o,
236
- yPos: n - t
237
- }), n += 10;
280
+ x2: n,
281
+ yPos: o - t
282
+ }), o += 10;
238
283
  }
239
284
  return s;
240
285
  }
241
286
  calculateNoteYPos = (e) => {
242
- let s = D(this.params.topLineNote, e) * (10 / 2);
243
- const r = R(e);
244
- return r < N ? s += 10 : r === N && (s = w), s;
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;
245
290
  };
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
296
+ );
297
+ return [o, a];
298
+ }
246
299
  }
247
- const M = 20;
300
+ const V = 20;
248
301
  class A {
249
302
  params;
250
303
  rendererRef;
251
304
  constructor(e, t) {
252
305
  this.rendererRef = e;
253
- const s = B[t];
306
+ const s = I[t];
254
307
  if (!s) throw new Error(`Staff type ${t} is not supported`);
255
308
  this.params = s;
256
309
  }
@@ -260,38 +313,44 @@ class A {
260
313
  for (let a = 0; a < 5; a++)
261
314
  this.rendererRef.drawLine(0, s, e, s, t), s += 10;
262
315
  this.rendererRef.drawLine(0, 0, 0, s - 10, t), this.rendererRef.drawLine(e, 0, e, s - 10, t);
263
- let r = s - 10 + 1, o = 1;
264
- const n = S(this.params.staffType);
265
- this.rendererRef.drawGlyph(n, t), r += this.params.paddingTop + this.params.paddingBottom, o += this.params.paddingTop, this.rendererRef.addTotalRootSvgHeight(r), this.rendererRef.addTotalRootSvgYOffset(o);
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);
266
319
  };
267
320
  shouldNoteFlip(e) {
268
- return e <= M;
321
+ return e <= V;
269
322
  }
270
323
  getLedgerLinesX(e, t) {
271
324
  const s = [];
272
325
  let r = e.duration === "w" ? 17 : 12.5;
273
326
  if (t < this.params.topLineYPos) {
274
- let o = this.params.topLineYPos - 10;
275
- for (; o >= t; )
327
+ let n = this.params.topLineYPos - 10;
328
+ for (; n >= t; )
276
329
  s.push({
277
330
  x1: -2,
278
331
  x2: r,
279
- yPos: o - t
280
- }), o -= 10;
332
+ yPos: n - t
333
+ }), n -= 10;
281
334
  } else if (t > this.params.bottomLineYPos) {
282
- let o = this.params.bottomLineYPos + 10;
283
- for (; o <= t; )
335
+ let n = this.params.bottomLineYPos + 10;
336
+ for (; n <= t; )
284
337
  s.push({
285
338
  x1: -2,
286
339
  x2: r,
287
- yPos: o - t
288
- }), o += 10;
340
+ yPos: n - t
341
+ }), n += 10;
289
342
  }
290
343
  return s;
291
344
  }
292
- calculateNoteYPos = (e) => D(this.params.topLineNote, e) * (10 / 2);
345
+ calculateNoteYPos = (e) => _(this.params.topLineNote, e) * (10 / 2);
346
+ getKeySignatureYPositions(e, t) {
347
+ const s = X[e].slice(0, t), r = L[this.params.staffType][e];
348
+ return [s.map(
349
+ (o, a) => this.calculateNoteYPos({ name: o, octave: r[a] })
350
+ )];
351
+ }
293
352
  }
294
- class P {
353
+ class U {
295
354
  svgRendererInstance;
296
355
  strategyInstance;
297
356
  constructor(e, t) {
@@ -302,10 +361,10 @@ class P {
302
361
  }
303
362
  chordOffsetConsecutiveAccidentals(e) {
304
363
  let t = 0, s = 0, r = 0;
305
- for (let o = 0; o < e.length; o++) {
306
- const n = e[o];
307
- 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) {
308
- const i = Array.from(n.noteGroup.getElementsByTagName("use")).find((c) => c.getAttribute("href")?.includes("ACCIDENTAL"));
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"));
309
368
  if (!i) continue;
310
369
  i.setAttribute("transform", `translate(${t + 8}, 0)`);
311
370
  }
@@ -315,10 +374,10 @@ class P {
315
374
  chordOffsetCloseNotes(e) {
316
375
  let t = e[0], s = 0;
317
376
  for (let r = 1; r < e.length; r++) {
318
- const o = e[r];
319
- if (y(o.noteObj.name, o.noteObj.octave) - y(t.noteObj.name, t.noteObj.octave) === 1) {
320
- s = 28 / 2, o.noteGroup.setAttribute("transform", `translate(${s}, ${o.noteYPos})`);
321
- const i = Array.from(o.noteGroup.getElementsByTagName("use")).find((c) => c.getAttribute("href")?.includes("ACCIDENTAL"));
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"));
322
381
  if (i) {
323
382
  const c = i.getAttribute("transform")?.match(/([-]?\d+)/), l = c && c[0];
324
383
  let f = -s;
@@ -327,46 +386,46 @@ class P {
327
386
  r++, t = e[r];
328
387
  continue;
329
388
  }
330
- t = o;
389
+ t = n;
331
390
  }
332
391
  return s;
333
392
  }
334
393
  // Handles drawing the glyphs to internal group, applies the xPositioning to note Cursor X
335
394
  renderNote(e) {
336
- const t = this.svgRendererInstance.createGroup("note"), s = g(e), r = this.strategyInstance.calculateNoteYPos({
395
+ const t = this.svgRendererInstance.createGroup("note"), s = O(e), r = this.strategyInstance.calculateNoteYPos({
337
396
  name: s.name,
338
397
  octave: s.octave
339
398
  });
340
- let o = this.strategyInstance.shouldNoteFlip(r);
399
+ let n = this.strategyInstance.shouldNoteFlip(r);
341
400
  switch (s.duration) {
342
401
  case "h":
343
- this.svgRendererInstance.drawGlyph("NOTE_HEAD_HALF", t), this.drawStem(t, o);
402
+ this.svgRendererInstance.drawGlyph("NOTE_HEAD_HALF", t), this.drawStem(t, n);
344
403
  break;
345
404
  case "q":
346
- this.svgRendererInstance.drawGlyph("NOTE_HEAD_QUARTER", t), this.drawStem(t, o);
405
+ this.svgRendererInstance.drawGlyph("NOTE_HEAD_QUARTER", t), this.drawStem(t, n);
347
406
  break;
348
407
  case "e":
349
- o ? this.svgRendererInstance.drawGlyph("EIGHTH_NOTE_FLIPPED", t) : this.svgRendererInstance.drawGlyph("EIGHTH_NOTE", t);
408
+ n ? this.svgRendererInstance.drawGlyph("EIGHTH_NOTE_FLIPPED", t) : this.svgRendererInstance.drawGlyph("EIGHTH_NOTE", t);
350
409
  break;
351
410
  default:
352
411
  this.svgRendererInstance.drawGlyph("NOTE_HEAD_WHOLE", t);
353
412
  }
354
- let n = 0;
413
+ let o = 0;
355
414
  switch (s.accidental) {
356
415
  case "#":
357
- this.svgRendererInstance.drawGlyph("ACCIDENTAL_SHARP", t), n -= -8;
416
+ this.svgRendererInstance.drawGlyph("ACCIDENTAL_SHARP", t), o -= -8;
358
417
  break;
359
418
  case "b":
360
- this.svgRendererInstance.drawGlyph("ACCIDENTAL_FLAT", t), n -= -8;
419
+ this.svgRendererInstance.drawGlyph("ACCIDENTAL_FLAT", t), o -= -8;
361
420
  break;
362
421
  case "n":
363
- this.svgRendererInstance.drawGlyph("ACCIDENTAL_NATURAL", t), n -= -8;
422
+ this.svgRendererInstance.drawGlyph("ACCIDENTAL_NATURAL", t), o -= -8;
364
423
  break;
365
424
  case "##":
366
- this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_SHARP", t), n -= -10;
425
+ this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_SHARP", t), o -= -10;
367
426
  break;
368
427
  case "bb":
369
- this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_FLAT", t), n -= -14;
428
+ this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_FLAT", t), o -= -14;
370
429
  break;
371
430
  }
372
431
  return this.strategyInstance.getLedgerLinesX(s, r).forEach((i) => {
@@ -375,14 +434,14 @@ class P {
375
434
  noteGroup: t,
376
435
  noteObj: s,
377
436
  noteYPos: r,
378
- accidentalOffset: n,
437
+ accidentalOffset: o,
379
438
  cursorOffset: 0
380
439
  };
381
440
  }
382
441
  renderChord(e) {
383
442
  const t = this.svgRendererInstance.createGroup("chord"), s = [];
384
- for (const n of e) {
385
- const a = this.renderNote(n);
443
+ for (const o of e) {
444
+ const a = this.renderNote(o);
386
445
  a.noteGroup.setAttribute("transform", `translate(0, ${a.noteYPos})`), t.appendChild(a.noteGroup), s.push({
387
446
  noteGroup: a.noteGroup,
388
447
  noteObj: a.noteObj,
@@ -391,18 +450,18 @@ class P {
391
450
  accidentalOffset: 0
392
451
  });
393
452
  }
394
- const r = this.chordOffsetConsecutiveAccidentals(s), o = this.chordOffsetCloseNotes(s);
453
+ const r = this.chordOffsetConsecutiveAccidentals(s), n = this.chordOffsetCloseNotes(s);
395
454
  return {
396
455
  noteGroup: t,
397
456
  noteObj: s[0].noteObj,
398
457
  noteYPos: 0,
399
458
  accidentalOffset: r,
400
- cursorOffset: o
459
+ cursorOffset: n
401
460
  };
402
461
  }
403
462
  }
404
- const u = "http://www.w3.org/2000/svg", Y = 0.1, m = 1200;
405
- class O {
463
+ const u = "http://www.w3.org/2000/svg", q = 0.1, S = 1200;
464
+ class b {
406
465
  rootElementRef;
407
466
  svgElementRef;
408
467
  // Layers
@@ -420,14 +479,14 @@ class O {
420
479
  // from get rootSvgElement().
421
480
  // HEIGHT and YOfsset should be set externally, values are calculated internally.
422
481
  constructor(e, t) {
423
- this.rootElementRef = e, this.width = t.width, this.scale = t.scale, this.width > m && (this.width = m, console.warn(`Width provided for the staff ${this.width} exceeds the limit ${m}. 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 > 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);
424
483
  }
425
484
  // Creates SVG defs for all glyphs in GLYPH_ENTRIES, applies global scale and offsets, appends to root SVG
426
485
  makeGlyphDefs(e) {
427
486
  const t = document.createElementNS(u, "defs");
428
- Object.entries(X).filter(([r]) => e.includes(r)).forEach(([r, o]) => {
429
- const n = document.createElementNS(u, "path");
430
- n.setAttribute("id", `glyph-${r}`), n.setAttribute("d", o.path), n.setAttribute("fill", "currentColor"), n.setAttribute("transform", `translate(${o.xOffset}, ${o.yOffset}) scale(${Y})`), t.appendChild(n);
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);
431
490
  }), this.rootSvgElement.appendChild(t);
432
491
  }
433
492
  createGroup(e) {
@@ -471,13 +530,13 @@ class O {
471
530
  return this.parentGroupContainer;
472
531
  }
473
532
  // Drawing Methods
474
- drawLine(e, t, s, r, o) {
475
- const n = document.createElementNS(u, "line");
476
- 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);
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);
477
536
  }
478
537
  drawRect(e, t, s, r) {
479
- const o = document.createElementNS(u, "rect");
480
- 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"), s.appendChild(o), o;
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;
481
540
  }
482
541
  drawGlyph(e, t, s) {
483
542
  s = {
@@ -492,7 +551,7 @@ class O {
492
551
  this.rootElementRef && this.svgElementRef && this.rootElementRef.contains(this.svgElementRef) && this.rootElementRef.removeChild(this.svgElementRef);
493
552
  }
494
553
  }
495
- const $ = [
554
+ const j = [
496
555
  "CLEF_TREBLE",
497
556
  "CLEF_BASS",
498
557
  "CLEF_ALTO",
@@ -507,7 +566,7 @@ const $ = [
507
566
  "ACCIDENTAL_DOUBLE_SHARP",
508
567
  "ACCIDENTAL_DOUBLE_FLAT"
509
568
  ];
510
- class j {
569
+ class et {
511
570
  svgRendererInstance;
512
571
  strategyInstance;
513
572
  noteRendererInstance;
@@ -532,18 +591,18 @@ class j {
532
591
  staffColor: "black",
533
592
  staffBackgroundColor: "transparent",
534
593
  ...t
535
- }, this.svgRendererInstance = new O(e, {
594
+ }, this.svgRendererInstance = new b(e, {
536
595
  width: this.options.width,
537
596
  height: 100,
538
597
  scale: this.options.scale,
539
598
  staffColor: this.options.staffColor,
540
599
  staffBackgroundColor: this.options.staffBackgroundColor,
541
- useGlyphs: $
600
+ useGlyphs: j
542
601
  });
543
602
  const s = this.svgRendererInstance.rootSvgElement;
544
603
  switch (this.options.staffType) {
545
604
  case "grand":
546
- this.strategyInstance = new H(this.svgRendererInstance, "grand");
605
+ this.strategyInstance = new x(this.svgRendererInstance, "grand");
547
606
  break;
548
607
  case "bass":
549
608
  this.strategyInstance = new A(this.svgRendererInstance, "bass");
@@ -557,15 +616,19 @@ class j {
557
616
  default:
558
617
  throw new Error(`The staff type ${this.options.staffType} is not supported. Please use "treble", "bass", "alto", or "grand".`);
559
618
  }
560
- if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new P(this.svgRendererInstance, this.strategyInstance), this.options.spaceAbove) {
561
- const r = this.options.spaceAbove * 10;
562
- this.svgRendererInstance.addTotalRootSvgYOffset(r);
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);
563
622
  }
564
623
  if (this.options.spaceBelow) {
565
- let r = this.options.spaceBelow * 10;
566
- this.options.staffType === "grand" && (r -= 10 / 2), this.svgRendererInstance.addTotalRootSvgHeight(r);
624
+ let n = this.options.spaceBelow * 10;
625
+ this.options.staffType === "grand" && (n -= 10 / 2), this.svgRendererInstance.addTotalRootSvgHeight(n);
567
626
  }
568
- this.noteStartX = 38 + this.options.noteStartX, this.svgRendererInstance.getLayerByName("notes").setAttribute("transform", `translate(${this.noteStartX}, 0)`), this.svgRendererInstance.applySizingToRootSvg(), this.svgRendererInstance.commitElementsToDOM(s);
627
+ let r = 0;
628
+ 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
+ }
630
+ createKeySignature(e) {
631
+ return k(this.svgRendererInstance, this.strategyInstance, e, M);
569
632
  }
570
633
  /**
571
634
  * Draws a note on the staff.
@@ -589,20 +652,20 @@ class j {
589
652
  */
590
653
  drawNote(e) {
591
654
  const t = Array.isArray(e) ? e : [e], s = this.svgRendererInstance.getLayerByName("notes"), r = [];
592
- for (const o of t) {
593
- let n;
655
+ for (const n of t) {
656
+ let o;
594
657
  try {
595
- n = this.noteRendererInstance.renderNote(o);
658
+ o = this.noteRendererInstance.renderNote(n);
596
659
  } catch (a) {
597
660
  throw r.length > 0 && this.svgRendererInstance.commitElementsToDOM(r, s), a;
598
661
  }
599
- n.noteGroup.setAttribute("transform", `translate(${this.noteCursorX + n.accidentalOffset}, ${n.noteYPos})`), this.noteEntries.push({
600
- gElement: n.noteGroup,
601
- note: n.noteObj,
602
- xPos: this.noteCursorX + n.accidentalOffset,
603
- yPos: n.noteYPos,
604
- accidentalXOffset: n.accidentalOffset
605
- }), this.noteCursorX += 28 + n.accidentalOffset, r.push(n.noteGroup);
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);
606
669
  }
607
670
  this.svgRendererInstance.commitElementsToDOM(r, s);
608
671
  }
@@ -626,7 +689,7 @@ class j {
626
689
  const t = this.svgRendererInstance.getLayerByName("notes"), s = this.noteRendererInstance.renderChord(e);
627
690
  s.noteGroup.setAttribute("transform", `translate(${this.noteCursorX + s.accidentalOffset}, 0)`), this.noteEntries.push({
628
691
  gElement: s.noteGroup,
629
- note: g(e[0]),
692
+ note: O(e[0]),
630
693
  xPos: this.noteCursorX + s.accidentalOffset,
631
694
  yPos: 0,
632
695
  accidentalXOffset: s.accidentalOffset
@@ -637,19 +700,19 @@ class j {
637
700
  * @returns Returns early if no notes are on the staff
638
701
  */
639
702
  justifyNotes() {
640
- const e = this.options.width - 38, t = this.noteEntries.length;
703
+ const e = this.options.width - this.noteStartX, t = this.noteEntries.length;
641
704
  if (t <= 0 || e <= 0) return;
642
705
  const s = Math.round(e / t);
643
- this.noteEntries.map((o, n) => {
644
- const a = (n + 0.5) * s, i = o.gElement.getBBox(), c = a - i.width / 2 - i.x, l = Math.round(c * 10) / 10;
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;
645
708
  return {
646
- entry: o,
709
+ entry: n,
647
710
  newX: l,
648
- isChord: o.gElement.classList.contains("chord")
711
+ isChord: n.gElement.classList.contains("chord")
649
712
  };
650
- }).forEach((o) => {
651
- const { entry: n, newX: a, isChord: i } = o;
652
- i ? n.gElement.setAttribute("transform", `translate(${a}, 0)`) : n.gElement.setAttribute("transform", `translate(${a}, ${n.yPos})`), n.xPos = a;
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;
653
716
  });
654
717
  }
655
718
  /**
@@ -677,11 +740,11 @@ class j {
677
740
  */
678
741
  changeNoteByIndex(e, t) {
679
742
  if (t >= this.noteEntries.length) throw new Error("Note index was out of bounds.");
680
- const s = this.noteEntries[t], r = this.noteRendererInstance.renderNote(e), n = s.xPos - s.accidentalXOffset + r.accidentalOffset;
681
- r.noteGroup.setAttribute("transform", `translate(${n}, ${r.noteYPos})`), this.svgRendererInstance.getLayerByName("notes").replaceChild(r.noteGroup, s.gElement), this.noteEntries[t] = {
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] = {
682
745
  gElement: r.noteGroup,
683
746
  note: r.noteObj,
684
- xPos: n,
747
+ xPos: o,
685
748
  yPos: r.noteYPos,
686
749
  accidentalXOffset: r.accidentalOffset
687
750
  };
@@ -705,11 +768,11 @@ class j {
705
768
  changeChordByIndex(e, t) {
706
769
  if (t >= this.noteEntries.length) throw new Error("Chord index was out of bounds.");
707
770
  if (e.length < 2) throw new Error("Notes provided need to be more than one to be considered a chord.");
708
- const s = this.noteEntries[t], r = this.noteRendererInstance.renderChord(e), n = s.xPos - s.accidentalXOffset + r.accidentalOffset;
709
- r.noteGroup.setAttribute("transform", `translate(${n}, 0)`), this.svgRendererInstance.getLayerByName("notes").replaceChild(r.noteGroup, s.gElement), this.noteEntries[t] = {
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] = {
710
773
  gElement: r.noteGroup,
711
- note: g(e[0]),
712
- xPos: n,
774
+ note: O(e[0]),
775
+ xPos: o,
713
776
  yPos: 0,
714
777
  accidentalXOffset: r.accidentalOffset
715
778
  };
@@ -744,7 +807,7 @@ class j {
744
807
  this.noteEntries = [], this.svgRendererInstance.destroy();
745
808
  }
746
809
  }
747
- const E = 30, v = 19, C = 12, k = 4, W = 6, G = 1, L = 38, Z = [
810
+ const d = 30, H = 19, g = 12, K = 4, Q = 6, P = 1, m = 38, z = [
748
811
  "TIME_4",
749
812
  "TIME_3",
750
813
  "NOTE_HEAD_WHOLE",
@@ -756,7 +819,7 @@ const E = 30, v = 19, C = 12, k = 4, W = 6, G = 1, L = 38, Z = [
756
819
  "REST_QUARTER",
757
820
  "REST_EIGHTH"
758
821
  ];
759
- class Q {
822
+ class st {
760
823
  rendererInstance;
761
824
  options;
762
825
  barSpacing;
@@ -767,7 +830,7 @@ class Q {
767
830
  currentBeatCount = 0;
768
831
  currentBeatUICount = 0;
769
832
  currentBeatUIElement = null;
770
- currentBeatUIXPos = L;
833
+ currentBeatUIXPos = m;
771
834
  /**
772
835
  * Creates an instance of a RhythmStaff, A single staff that will automatically apply positioning of elements based on the duration of a note.
773
836
  *
@@ -787,13 +850,13 @@ class Q {
787
850
  staffBackgroundColor: "white",
788
851
  currentBeatUIColor: "#24ff7450",
789
852
  ...t
790
- }, this.rendererInstance = new O(e, {
853
+ }, this.rendererInstance = new b(e, {
791
854
  width: this.options.width,
792
855
  height: 100,
793
856
  scale: this.options.scale,
794
857
  staffColor: this.options.staffColor,
795
858
  staffBackgroundColor: this.options.staffBackgroundColor,
796
- useGlyphs: Z
859
+ useGlyphs: z
797
860
  });
798
861
  const s = this.rendererInstance.rootSvgElement;
799
862
  let r = "TIME_4";
@@ -816,34 +879,34 @@ class Q {
816
879
  let p = this.options.spaceBelow * 10;
817
880
  this.rendererInstance.addTotalRootSvgHeight(p);
818
881
  }
819
- const o = this.rendererInstance.getLayerByName("staff");
820
- this.rendererInstance.addTotalRootSvgHeight(E * 2);
821
- const n = this.rendererInstance.createGroup("time-signature");
822
- o.appendChild(n);
823
- const a = E - v;
824
- this.rendererInstance.drawGlyph(r, n), this.rendererInstance.drawGlyph("TIME_4", n, { yOffset: v }), n.setAttribute("transform", `translate(0, ${a})`);
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})`);
825
888
  let i = this.options.width - 38;
826
- this.options.barsCount > 1 && (i -= (this.options.barsCount - 1) * C), i -= G, this.rendererInstance.drawLine(0, E, this.options.width - G, E, o), this.barSpacing = i / this.options.barsCount, this.quarterNoteSpacing = Math.round(this.barSpacing / this.options.topNumber), this.maxBeatCount = this.options.barsCount * this.options.topNumber;
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;
827
890
  let c = this.barSpacing + 38;
828
- const l = E / 2, f = E + l;
891
+ const l = d / 2, f = d + l;
829
892
  for (let p = 0; p < this.options.barsCount - 1; p++)
830
- this.rendererInstance.drawLine(c, l, c, f, o), c += this.barSpacing;
831
- this.rendererInstance.getLayerByName("notes").setAttribute("transform", `translate(38, ${E})`), this.rendererInstance.applySizingToRootSvg(), this.rendererInstance.commitElementsToDOM(s);
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);
832
895
  }
833
896
  createBeatUIElement() {
834
897
  const e = this.rendererInstance.getLayerByName("ui");
835
898
  this.currentBeatUIElement = this.rendererInstance.drawRect(
836
899
  this.quarterNoteSpacing / 2,
837
- E * 2,
900
+ d * 2,
838
901
  e,
839
902
  {
840
- x: L,
903
+ x: m,
841
904
  fill: this.options.currentBeatUIColor
842
905
  }
843
906
  );
844
907
  }
845
908
  handleNewBar() {
846
- this.noteCursorX += C;
909
+ this.noteCursorX += g;
847
910
  }
848
911
  // Translates group, returns cursor increment amount
849
912
  translateGroupByDuration(e, t) {
@@ -902,15 +965,15 @@ class Q {
902
965
  let s = e;
903
966
  for (; s > 0; ) {
904
967
  const r = this.rendererInstance.createGroup("rest");
905
- let o = 0;
906
- s - d.h >= 0 ? (this.rendererInstance.drawGlyph("REST_HALF", r), o = d.h) : s - d.q >= 0 ? (this.rendererInstance.drawGlyph("REST_QUARTER", r), o = d.q) : (this.rendererInstance.drawGlyph("REST_EIGHTH", r), o = d.e), s -= o, this.currentBeatCount += o, r.setAttribute("transform", `translate(${this.noteCursorX}, 0)`), this.noteCursorX += o * this.quarterNoteSpacing, t.push(r);
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);
907
970
  }
908
971
  return t;
909
972
  }
910
973
  renderBeamRect(e, t, s, r) {
911
974
  this.rendererInstance.drawRect(
912
975
  e - t,
913
- k,
976
+ K,
914
977
  s,
915
978
  {
916
979
  x: 10,
@@ -939,14 +1002,14 @@ class Q {
939
1002
  */
940
1003
  drawNote(e) {
941
1004
  const t = Array.isArray(e) ? e : [e], s = this.rendererInstance.getLayerByName("notes"), r = [];
942
- for (const o of t) {
943
- let n = "w";
1005
+ for (const n of t) {
1006
+ let o = "w";
944
1007
  try {
945
- n = T(o);
1008
+ o = N(n);
946
1009
  } catch (f) {
947
1010
  throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), f;
948
1011
  }
949
- const a = d[n];
1012
+ const a = E[o];
950
1013
  if (this.currentBeatCount >= this.maxBeatCount)
951
1014
  throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), new Error("Max beat count reached. Can't add additional notes.");
952
1015
  this.checkAndCreateNewBar();
@@ -955,7 +1018,7 @@ class Q {
955
1018
  r.push(f), this.noteEntries.push(f);
956
1019
  });
957
1020
  const c = this.rendererInstance.createGroup("note"), l = this.translateGroupByDuration(a, c);
958
- this.noteCursorX += l, this.currentBeatCount += a, this.renderNote(n, c), r.push(c), this.noteEntries.push(c);
1021
+ this.noteCursorX += l, this.currentBeatCount += a, this.renderNote(o, c), r.push(c), this.noteEntries.push(c);
959
1022
  }
960
1023
  this.rendererInstance.commitElementsToDOM(r, s);
961
1024
  }
@@ -979,21 +1042,21 @@ class Q {
979
1042
  */
980
1043
  drawRest(e) {
981
1044
  const t = Array.isArray(e) ? e : [e], s = this.rendererInstance.getLayerByName("notes"), r = [];
982
- for (const o of t) {
983
- let n = "w";
1045
+ for (const n of t) {
1046
+ let o = "w";
984
1047
  try {
985
- n = T(o);
1048
+ o = N(n);
986
1049
  } catch (f) {
987
1050
  throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), f;
988
1051
  }
989
- const a = this.rendererInstance.createGroup("rest"), i = d[n], c = i * this.quarterNoteSpacing;
1052
+ const a = this.rendererInstance.createGroup("rest"), i = E[o], c = i * this.quarterNoteSpacing;
990
1053
  if (this.currentBeatCount >= this.maxBeatCount)
991
1054
  throw r.length > 0 && this.rendererInstance.commitElementsToDOM(r, s), new Error("Max beat count reached. Can't add additional notes.");
992
1055
  this.checkAndCreateNewBar();
993
1056
  const l = this.checkAndFillBarWithRests(i);
994
1057
  l && l.forEach((f) => {
995
1058
  r.push(f), this.noteEntries.push(f);
996
- }), this.renderRest(n, a), a.setAttribute("transform", `translate(${this.noteCursorX}, 0)`), this.noteCursorX += c, this.currentBeatCount += i, r.push(a), this.noteEntries.push(a);
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);
997
1060
  }
998
1061
  this.rendererInstance.commitElementsToDOM(r, s);
999
1062
  }
@@ -1020,13 +1083,13 @@ class Q {
1020
1083
  if (this.currentBeatCount >= this.maxBeatCount)
1021
1084
  throw new Error("Max beat count reached. Can't add additional beamed note.");
1022
1085
  let s = "s";
1023
- e === "s" ? s = "s" : s = T(e), this.checkAndCreateNewBar();
1024
- const r = this.rendererInstance.getLayerByName("notes"), o = d[s], n = o * this.quarterNoteSpacing, a = this.options.topNumber - this.currentBeatCount % this.options.topNumber, i = Math.min(t, a / o), c = this.rendererInstance.createGroup("beamed-note");
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");
1025
1088
  c.setAttribute("transform", `translate(${this.noteCursorX}, 0)`);
1026
1089
  let l = 0;
1027
1090
  for (let f = 0; f < i; f++)
1028
- this.rendererInstance.drawGlyph("NOTE_HEAD_QUARTER", c, { xOffset: l }), this.drawStem(c, l), l += n, this.currentBeatCount += o;
1029
- this.renderBeamRect(l, n, c), e === "s" && this.renderBeamRect(l, n, c, W), this.noteCursorX += l, this.noteEntries.push(c), this.rendererInstance.commitElementsToDOM(c, r);
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);
1030
1093
  }
1031
1094
  /**
1032
1095
  * Will increment the UI showing the current beat in quarters. Once exceeded, must be reset with `resetCurrentBeatUI()`
@@ -1037,14 +1100,14 @@ class Q {
1037
1100
  this.currentBeatUIElement.setAttribute("display", "none");
1038
1101
  return;
1039
1102
  }
1040
- this.currentBeatUIElement?.getAttribute("display") === "none" && this.currentBeatUIElement.removeAttribute("display"), this.currentBeatUICount++, this.currentBeatUICount > this.options.topNumber && this.currentBeatUICount % this.options.topNumber === 1 && (this.currentBeatUIXPos += C), this.currentBeatUICount > 1 && (this.currentBeatUIXPos += this.quarterNoteSpacing), this.currentBeatUIElement.setAttribute("x", this.currentBeatUIXPos.toString());
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());
1041
1104
  }
1042
1105
  /**
1043
1106
  * Resets the ui showing the current beat value.
1044
1107
  * @returns void
1045
1108
  */
1046
1109
  resetCurrentBeatUI() {
1047
- this.currentBeatUICount = 0, this.currentBeatUIXPos = L, this.currentBeatUIElement && (this.currentBeatUIElement.setAttribute("display", "none"), this.currentBeatUIElement.setAttribute("x", this.currentBeatUIXPos.toString()));
1110
+ this.currentBeatUICount = 0, this.currentBeatUIXPos = m, this.currentBeatUIElement && (this.currentBeatUIElement.setAttribute("display", "none"), this.currentBeatUIElement.setAttribute("x", this.currentBeatUIXPos.toString()));
1048
1111
  }
1049
1112
  /**
1050
1113
  * Clears staff of notes and resets internal positioning.
@@ -1061,7 +1124,7 @@ class Q {
1061
1124
  this.noteEntries = [], this.rendererInstance.destroy();
1062
1125
  }
1063
1126
  }
1064
- const V = [
1127
+ const J = [
1065
1128
  "CLEF_TREBLE",
1066
1129
  "CLEF_BASS",
1067
1130
  "CLEF_ALTO",
@@ -1075,8 +1138,8 @@ const V = [
1075
1138
  "ACCIDENTAL_NATURAL",
1076
1139
  "ACCIDENTAL_DOUBLE_SHARP",
1077
1140
  "ACCIDENTAL_DOUBLE_FLAT"
1078
- ], _ = 60, q = _;
1079
- class z {
1141
+ ], T = 60, tt = T;
1142
+ class rt {
1080
1143
  svgRendererInstance;
1081
1144
  strategyInstance;
1082
1145
  noteRendererInstance;
@@ -1103,18 +1166,18 @@ class z {
1103
1166
  staffColor: "black",
1104
1167
  staffBackgroundColor: "transparent",
1105
1168
  ...t
1106
- }, this.svgRendererInstance = new O(e, {
1169
+ }, this.svgRendererInstance = new b(e, {
1107
1170
  width: this.options.width,
1108
1171
  height: 100,
1109
1172
  scale: this.options.scale,
1110
1173
  staffColor: this.options.staffColor,
1111
1174
  staffBackgroundColor: this.options.staffBackgroundColor,
1112
- useGlyphs: V
1175
+ useGlyphs: J
1113
1176
  });
1114
1177
  const s = this.svgRendererInstance.rootSvgElement;
1115
1178
  switch (this.options.staffType) {
1116
1179
  case "grand":
1117
- this.strategyInstance = new H(this.svgRendererInstance, "grand");
1180
+ this.strategyInstance = new x(this.svgRendererInstance, "grand");
1118
1181
  break;
1119
1182
  case "bass":
1120
1183
  this.strategyInstance = new A(this.svgRendererInstance, "bass");
@@ -1128,7 +1191,7 @@ class z {
1128
1191
  default:
1129
1192
  throw new Error(`The staff type ${this.options.staffType} is not supported. Please use "treble", "bass", "alto", or "grand".`);
1130
1193
  }
1131
- if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new P(this.svgRendererInstance, this.strategyInstance), this.options.spaceAbove) {
1194
+ if (this.strategyInstance.drawStaff(this.options.width), this.noteRendererInstance = new U(this.svgRendererInstance, this.strategyInstance), this.options.spaceAbove) {
1132
1195
  const r = this.options.spaceAbove * 10;
1133
1196
  this.svgRendererInstance.addTotalRootSvgYOffset(r);
1134
1197
  }
@@ -1139,10 +1202,10 @@ class z {
1139
1202
  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);
1140
1203
  }
1141
1204
  renderFirstNoteGroups() {
1142
- const e = this.options.width - this.options.noteStartX + q;
1205
+ const e = this.options.width - this.options.noteStartX + tt;
1143
1206
  for (; this.noteBuffer.length > 0 && this.noteCursorX < e; )
1144
- this.renderNextNote(), this.noteCursorX += _;
1145
- this.activeEntries.length > 1 && (this.noteCursorX -= _);
1207
+ this.renderNextNote(), this.noteCursorX += T;
1208
+ this.activeEntries.length > 1 && (this.noteCursorX -= T);
1146
1209
  }
1147
1210
  renderNextNote() {
1148
1211
  if (this.noteBuffer.length < 1) return;
@@ -1201,7 +1264,7 @@ class z {
1201
1264
  return;
1202
1265
  }
1203
1266
  this.activeEntries.forEach((t) => {
1204
- t.xPos -= _, t.noteWrapper.style.transform = `translate(${t.xPos}px, 0px)`;
1267
+ t.xPos -= T, t.noteWrapper.style.transform = `translate(${t.xPos}px, 0px)`;
1205
1268
  });
1206
1269
  const e = this.activeEntries[0];
1207
1270
  e.xPos <= 0 && (this.notesLayer.removeChild(e.noteWrapper), this.activeEntries.shift()), this.renderNextNote();
@@ -1222,7 +1285,7 @@ class z {
1222
1285
  }
1223
1286
  }
1224
1287
  export {
1225
- j as MusicStaff,
1226
- Q as RhythmStaff,
1227
- z as ScrollingStaff
1288
+ et as MusicStaff,
1289
+ st as RhythmStaff,
1290
+ rt as ScrollingStaff
1228
1291
  };
@@ -1 +1 @@
1
- (function(d,I){typeof exports=="object"&&typeof module<"u"?I(exports):typeof define=="function"&&define.amd?define(["exports"],I):(d=typeof globalThis<"u"?globalThis:d||self,I(d.VectorScore={}))})(this,(function(d){"use strict";const w={treble:{staffType:"treble",paddingTop:13,paddingBottom:3,topLineNote:{name:"F",octave:5},topLineYPos:0,bottomLineYPos:40},bass:{staffType:"bass",paddingTop:0,paddingBottom:0,topLineNote:{name:"A",octave:3},topLineYPos:0,bottomLineYPos:40},alto:{staffType:"alto",paddingTop:0,paddingBottom:0,topLineNote:{name:"G",octave:4},topLineYPos:0,bottomLineYPos:40},grand:{staffType:"grand",paddingTop:13,paddingBottom:0,topLineNote:{name:"F",octave:5},topLineYPos:0,bottomLineYPos:110}},E={w:4,h:2,q:1,e:.5,s:.25},U={CLEF_TREBLE:{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",xOffset:0,yOffset:-14},CLEF_BASS:{path:"M101 0c68 0 110 46 110 114 0 120-102 190-199 237l-7 2c-3 0-5-2-5-5s2-5 6-7c92-52 146-114 146-223 0-62-18-103-60-103-40 0-64 29-64 44 0 4 1 8 7 8 5 0 9-3 19-3 20 0 38 15 38 41 0 24-17 41-42 41-32 0-48-27-48-58C2 50 33 0 101 0Zm148 32c13 0 22 10 22 22s-9 22-22 22c-12 0-21-10-21-22s9-22 21-22Zm1 99c12 0 21 9 21 21s-9 22-21 22-21-10-21-22 9-21 21-21Z",xOffset:0,yOffset:0},CLEF_ALTO:{path:"M91 9v174c0 3 2 2 3 2 11-3 27-13 36-58 1-6 3-10 7-10s6 4 8 11c5 17 15 37 43 37 25 0 32-25 32-77s-9-75-42-75c-5 0-33 2-33 10 0 2 6 5 11 6 7 3 15 11 15 26 0 17-11 27-26 27-17 0-31-11-31-32 0-25 22-50 69-50 65 0 93 45 93 87 0 54-30 92-83 92-11 0-18-2-24-4-4-1-8-1-11 1-6 3-14 16-14 24s8 21 14 24c3 2 7 2 11 1 6-2 13-4 24-4 53 0 83 38 83 92 0 42-28 87-93 87-47 0-69-25-69-50 0-21 14-32 31-32 15 0 26 10 26 27 0 15-8 23-15 26-5 1-11 4-11 6 0 8 28 10 33 10 33 0 42-23 42-75s-7-77-32-77c-28 0-38 20-43 37-2 7-4 11-8 11s-6-4-7-10c-9-45-25-55-36-58-1 0-3-1-3 2v174c0 5-3 8-8 8h-1c-5 0-8-3-8-8V9c0-5 3-8 8-8h1c5 0 8 3 8 8ZM8 1h34c6 0 9 3 9 8v382c0 5-3 8-9 8H8c-5 0-8-3-8-8V9c0-5 3-8 8-8Z",xOffset:0,yOffset:0},NOTE_HEAD_WHOLE:{path:"M77 0c34 0 74 19 74 45 0 24-19 45-77 45C21 90 0 68 0 45 0 20 30 0 77 0Zm-9 8c-17 0-30 5-30 24 0 22 23 50 47 50 16 0 28-8 28-26 0-21-20-48-45-48Z",xOffset:0,yOffset:-4.5},NOTE_HEAD_HALF:{path:"M35 90C15 90 0 79 0 60 0 42 17 0 70 0c21 0 36 12 36 30 0 12-12 60-71 60Zm-8-14c18 0 68-31 68-47l-2-6c-3-5-7-8-14-8-17 0-68 29-68 46l2 7c2 4 7 8 14 8Z",xOffset:0,yOffset:-4.5},NOTE_HEAD_QUARTER:{path:"M35 90C16 90 0 79 0 60 0 29 32 0 71 0c20 0 35 12 35 30 0 30-40 60-71 60Z",xOffset:0,yOffset:-4.5},EIGHTH_NOTE:{path:"M142 89c20 32 36 70 36 110 0 25-8 55-8 55-2 5-5 7-8 6h-1c-2-1-5-4-5-9l1-5c5-14 8-29 8-44 0-19-3-37-8-48-10-23-33-58-53-70v179c0 30-38 60-70 60-19 0-34-11-34-30 0-31 31-60 70-60 11 0 19 3 25 8V3c0-2 2-3 3-3 6 0 9 2 10 7 5 31 18 57 34 82Z",xOffset:0,yOffset:-28},EIGHTH_NOTE_FLIPPED:{path:"M9 323H0V60C0 29 32 0 71 0c20 0 35 12 35 30 0 30-40 60-71 60-19 0-26-9-26-9v158s58-56 58-89c0 0 0-25-8-43-5-12 10-17 14-6 13 34 9 48 9 48 0 39-41 97-41 97-20 27-32 77-32 77Z",xOffset:0,yOffset:-4},REST_WHOLE:{path:"M0 0h104v53H0V0Z",xOffset:0,yOffset:0},REST_HALF:{path:"M0 0h104v53H0V0Z",xOffset:0,yOffset:-5},REST_QUARTER:{path:"m28 151-18-22s-3-4-3-9c0-3 1-7 5-11 16-17 22-33 22-46 0-27-21-45-23-49l-1-6c0-5 4-8 7-8s5 1 7 3l61 71 1 7-1 5c-10 15-23 34-25 55v3c0 20 11 35 25 52 4 4 14 16 14 20 0 2-2 2-5 1-6-2-19-6-29-6-16 0-23 12-23 27 0 8 5 22 11 22 3 3 6 6 6 9s-2 5-7 5l-9-3c-27-21-43-39-43-57s13-35 32-35c3 0 10 3 14 0l-2-6-16-22Z",xOffset:0,yOffset:-16},REST_EIGHTH:{path:"M61 35c18 0 41-35 47-32 0 1 5 3 5 8l-5 17S64 189 62 190c-4 4-11 5-16 5-3 0-13 0-13-6 8-30 41-122 42-128 1-5 1-10-1-10-4 0-3 3-19 8C16 71 0 46 0 31 0 14 14 0 31 0c5 0 30 1 30 35Z",xOffset:0,yOffset:-10},ACCIDENTAL_SHARP:{path:"m67 66-8 3c-2 0-3 6-3 8v26c0 4 2 5 3 5l8-2 1-1c1 0 2 1 2 3v20c0 1-1 4-3 4l-8 4c-2 0-3 4-3 6v40c0 2-2 4-5 4-2 0-4-2-4-4v-35c0-2-1-5-4-5h-1l-17 7c-1 1-3 3-3 6v40c0 2-1 3-4 3-2 0-4-1-4-3v-35c0-1-1-5-3-5l-1 1-7 2v1c-2 0-3-1-3-3v-20c0-2 1-4 3-5l8-3c2-1 3-3 3-6V94c0-3-2-5-4-5l-7 3c-2 0-3-1-3-3V69l3-4 8-3c1-1 3-4 3-8V16c0-2 2-4 5-4 2 0 3 2 3 4v34c0 2 1 5 4 5l18-7c2-1 3-5 3-8V3c0-2 2-3 5-3 2 0 4 1 4 3v35c0 2 2 3 4 3l7-2h1c1 0 2 0 2 2v20c0 2-1 4-3 5Zm-20 46c2-11 2-23 0-34l-4-2c-7 0-20 6-21 11v35l4 1c6 0 20-5 21-11Z",xOffset:-8,yOffset:-10},ACCIDENTAL_FLAT:{path:"M4 196C1 193 0 9 0 9c0-6 5-9 10-9 3 0 6 2 6 5l-2 91c0 3 1 5 3 6h2l7-4c5-3 12-6 18-6 15 1 29 13 29 31 0 15-10 35-39 55-8 5-16 14-25 19l-2 1c-1 0-2 0-3-2Zm11-28c0 1 1 5 4 5l3-1c14-9 29-27 29-44 0-8-4-19-14-19-7 0-20 10-22 16l-1 10 1 33Z",xOffset:-8,yOffset:-14},ACCIDENTAL_NATURAL:{path:"m41 47 5-2h1l2 2v147c0 3-2 4-3 4h-4c-2 0-4-1-4-4v-43c0-2-2-3-5-3-8 0-25 7-29 8l-1 1c-2 0-3-1-3-3V4c0-3 1-4 4-4h3c2 0 4 1 4 4v48c0 2 1 2 3 2 7 0 26-7 26-7h1ZM11 88v31l3 1c8 0 24-6 24-12V78l-2-1c-7 0-25 7-25 11Z",xOffset:-8,yOffset:-10},ACCIDENTAL_DOUBLE_SHARP:{path:"M68 33h3c6 0 13 0 15-2l2-15C88 4 86 0 72 0c-6 0-12 1-14 4-2 1-2 7-2 13-1 5-8 17-12 17-5 0-9-10-11-15l-1-2c0-6-1-12-3-13-2-3-8-4-13-4C10 0 4 1 2 4L0 17l2 14c2 2 9 2 15 2h4c5 2 16 8 16 12 0 3-13 10-17 12h-3c-6 0-13 1-15 3L0 74l2 14 14 2 13-2c2-2 3-8 3-14 1-5 7-17 12-17 4 0 10 13 12 17 0 6 0 12 2 14l14 2c15 0 16-2 16-17l-2-13c-4-2-11-3-15-3h-3c-5-2-17-7-17-12 0-2 13-10 17-12Z",xOffset:-10,yOffset:-4},ACCIDENTAL_DOUBLE_FLAT:{path:"M102 93h2c15 0 29 12 29 30 0 15-10 35-39 55-8 5-16 14-26 19l-2 1-2-2-3-43c-6 7-15 16-27 25-7 5-15 14-25 19l-2 1c-1 0-2 0-3-2C2 193 0 8 0 8c0-5 6-8 10-8 3 0 6 2 6 5l-2 91c0 3 1 5 3 6h2c3 0 5-3 8-4 5-3 9-5 15-5h2c6 0 12 1 17 5L60 8c0-5 5-8 10-8 3 0 6 2 6 5l-2 91c0 3 1 5 3 6h2c3 0 5-3 7-4 6-3 10-5 16-5Zm-80 78c14-9 29-25 29-43 0-8-3-19-13-19-8 0-21 10-23 16l-1 11 1 31c0 2 1 5 4 5l3-1Zm59 0c15-9 29-25 29-43 0-6-2-12-5-16-2-2-4-3-8-3-7 0-21 10-23 16v8l1 34c0 2 1 5 3 5l3-1Z",xOffset:-14,yOffset:-14},TIME_4:{path:"M53 0h66S70 76 20 124h61V86l47-50v89h22v19h-22v27c0 9 13 9 13 9h9v10H61v-10h10s10 0 10-10v-26H0v-20S54 67 53 0Z",xOffset:0,yOffset:0},TIME_3:{path:"M2 43c0 21 15 30 30 30 5 0 28-2 28-27 0-11-16-20-16-24 0-14 56-15 56 26 0 26-19 38-31 38H45v13h24c12 0 33 15 33 41 0 38-54 40-54 25 0-3 10-11 10-21 0-20-15-27-27-27-17 0-32 8-31 30 1 30 36 43 75 43 36 0 75-19 75-50 0-34-23-47-37-47v-2c4 0 35-13 35-39 0-37-35-52-75-52C39 0 3 14 2 43Z",xOffset:0,yOffset:0}},M=/^(?<name>[A-Ga-g])(?<accidental>##|bb|[#bn]?)(?<octave>\d)(?<duration>[whqeWHQE]?)$/,Y=/^[whqeWHQE]$/,T=["C","D","E","F","G","A","B"];function m(h){const e=h.match(M);if(!e||!e.groups)throw new Error(`Invalid note string format: ${h}. Expected format: [A-Ga-g][#|b]?[0-9][w|h|q|e].`);let{name:t,accidental:s,octave:r,duration:o}=e.groups;if(t=t.toUpperCase(),o=o.toLowerCase(),!t)throw new Error(`Invalid note name: ${t}. Valid note names are: C, D, E, F, G, A, B.`);if(!r)throw new Error(`Invalid octave: ${r}. Octave must be a number between 0 and 9.`);o||(o="w");const n={name:t,octave:parseInt(r),duration:o};return s&&(n.accidental=s),n}function C(h){const e=h.match(Y);if(!e)throw new Error(`Invalid note duration '${h}'. Use w | h | q | e.`);return e.toString().toLowerCase()}function L(h){let e;switch(h){case"treble":e="CLEF_TREBLE";break;case"bass":e="CLEF_BASS";break;case"alto":e="CLEF_ALTO";break}if(!e)throw new Error(`Invalid clef type: ${h}. Valid clef types are: treble, bass, alto.`);return e}function b(h,e){const t=T.indexOf(h.name)-T.indexOf(e.name);let s=h.octave-e.octave;return s*=7,t+s}function F(h){let e=T.indexOf(h.name);return e+=h.octave*12,e}function v(h,e){return T.findIndex(s=>s===h)+1+e*7}const g=48,G=40+30/2,B=20,D=90;class H{params;rendererRef;width=0;constructor(e,t){this.rendererRef=e;const s=w[t];if(!s)throw new Error(`Staff type ${t} is not supported`);this.params=s}drawStaffLines=(e,t)=>{let s=e;for(let r=0;r<5;r++)this.rendererRef.drawLine(0,s,this.width,s,t),s+=10;return s-10};drawStaff=e=>{this.width=e;const t=this.rendererRef.getLayerByName("staff");let s=this.drawStaffLines(0,t),r=this.drawStaffLines(s+30,t);this.rendererRef.drawLine(0,0,0,r,t),this.rendererRef.drawLine(this.width,0,this.width,r,t);let o=r,n=1;const a=L("treble"),i=L("bass");this.rendererRef.drawGlyph(a,t),this.rendererRef.drawGlyph(i,t,{yOffset:s+30}),o+=this.params.paddingBottom+1,n+=this.params.paddingTop,this.rendererRef.addTotalRootSvgHeight(o),this.rendererRef.addTotalRootSvgYOffset(n)};shouldNoteFlip(e){const t=Math.abs(e-D),s=Math.abs(e-B);return e===G?!1:t<=s?!(e>=D):e<=B}getLedgerLinesX(e,t){const s=[],r=F(e);let o=e.duration==="w"?17:12.5;if(r===g)return s.push({x1:-2,x2:o,yPos:0}),s;if(t<this.params.topLineYPos){let n=this.params.topLineYPos-10;for(;n>=t;)s.push({x1:-2,x2:o,yPos:n-t}),n-=10}else if(t>this.params.bottomLineYPos){let n=this.params.bottomLineYPos+10;for(;n<=t;)s.push({x1:-2,x2:o,yPos:n-t}),n+=10}return s}calculateNoteYPos=e=>{let s=b(this.params.topLineNote,e)*(10/2);const r=F(e);return r<g?s+=10:r===g&&(s=G),s}}const $=20;class A{params;rendererRef;constructor(e,t){this.rendererRef=e;const s=w[t];if(!s)throw new Error(`Staff type ${t} is not supported`);this.params=s}drawStaff=e=>{const t=this.rendererRef.getLayerByName("staff");let s=0;for(let a=0;a<5;a++)this.rendererRef.drawLine(0,s,e,s,t),s+=10;this.rendererRef.drawLine(0,0,0,s-10,t),this.rendererRef.drawLine(e,0,e,s-10,t);let r=s-10+1,o=1;const n=L(this.params.staffType);this.rendererRef.drawGlyph(n,t),r+=this.params.paddingTop+this.params.paddingBottom,o+=this.params.paddingTop,this.rendererRef.addTotalRootSvgHeight(r),this.rendererRef.addTotalRootSvgYOffset(o)};shouldNoteFlip(e){return e<=$}getLedgerLinesX(e,t){const s=[];let r=e.duration==="w"?17:12.5;if(t<this.params.topLineYPos){let o=this.params.topLineYPos-10;for(;o>=t;)s.push({x1:-2,x2:r,yPos:o-t}),o-=10}else if(t>this.params.bottomLineYPos){let o=this.params.bottomLineYPos+10;for(;o<=t;)s.push({x1:-2,x2:r,yPos:o-t}),o+=10}return s}calculateNoteYPos=e=>b(this.params.topLineNote,e)*(10/2)}class P{svgRendererInstance;strategyInstance;constructor(e,t){this.svgRendererInstance=e,this.strategyInstance=t}drawStem(e,t){t?this.svgRendererInstance.drawLine(0,0,0,28,e):this.svgRendererInstance.drawLine(10,0,10,-28,e)}chordOffsetConsecutiveAccidentals(e){let t=0,s=0,r=0;for(let o=0;o<e.length;o++){const n=e[o];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){const i=Array.from(n.noteGroup.getElementsByTagName("use")).find(c=>c.getAttribute("href")?.includes("ACCIDENTAL"));if(!i)continue;i.setAttribute("transform",`translate(${t+8}, 0)`)}}return-s}chordOffsetCloseNotes(e){let t=e[0],s=0;for(let r=1;r<e.length;r++){const o=e[r];if(v(o.noteObj.name,o.noteObj.octave)-v(t.noteObj.name,t.noteObj.octave)===1){s=28/2,o.noteGroup.setAttribute("transform",`translate(${s}, ${o.noteYPos})`);const i=Array.from(o.noteGroup.getElementsByTagName("use")).find(c=>c.getAttribute("href")?.includes("ACCIDENTAL"));if(i){const c=i.getAttribute("transform")?.match(/([-]?\d+)/),l=c&&c[0];let f=-s;l&&(f+=Number(l)),i.setAttribute("transform",`translate(${f}, 0)`)}r++,t=e[r];continue}t=o}return s}renderNote(e){const t=this.svgRendererInstance.createGroup("note"),s=m(e),r=this.strategyInstance.calculateNoteYPos({name:s.name,octave:s.octave});let o=this.strategyInstance.shouldNoteFlip(r);switch(s.duration){case"h":this.svgRendererInstance.drawGlyph("NOTE_HEAD_HALF",t),this.drawStem(t,o);break;case"q":this.svgRendererInstance.drawGlyph("NOTE_HEAD_QUARTER",t),this.drawStem(t,o);break;case"e":o?this.svgRendererInstance.drawGlyph("EIGHTH_NOTE_FLIPPED",t):this.svgRendererInstance.drawGlyph("EIGHTH_NOTE",t);break;default:this.svgRendererInstance.drawGlyph("NOTE_HEAD_WHOLE",t)}let n=0;switch(s.accidental){case"#":this.svgRendererInstance.drawGlyph("ACCIDENTAL_SHARP",t),n-=-8;break;case"b":this.svgRendererInstance.drawGlyph("ACCIDENTAL_FLAT",t),n-=-8;break;case"n":this.svgRendererInstance.drawGlyph("ACCIDENTAL_NATURAL",t),n-=-8;break;case"##":this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_SHARP",t),n-=-10;break;case"bb":this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_FLAT",t),n-=-14;break}return this.strategyInstance.getLedgerLinesX(s,r).forEach(i=>{this.svgRendererInstance.drawLine(i.x1,i.yPos,i.x2,i.yPos,t)}),{noteGroup:t,noteObj:s,noteYPos:r,accidentalOffset:n,cursorOffset:0}}renderChord(e){const t=this.svgRendererInstance.createGroup("chord"),s=[];for(const n of e){const a=this.renderNote(n);a.noteGroup.setAttribute("transform",`translate(0, ${a.noteYPos})`),t.appendChild(a.noteGroup),s.push({noteGroup:a.noteGroup,noteObj:a.noteObj,noteYPos:a.noteYPos,cursorOffset:0,accidentalOffset:0})}const r=this.chordOffsetConsecutiveAccidentals(s),o=this.chordOffsetCloseNotes(s);return{noteGroup:t,noteObj:s[0].noteObj,noteYPos:0,accidentalOffset:r,cursorOffset:o}}}const p="http://www.w3.org/2000/svg",k=.1,S=1200;class O{rootElementRef;svgElementRef;parentGroupContainer;musicStaffLayer;musicNotesLayer;musicUILayer;width;scale;totalYOffset=0;totalHeight=0;constructor(e,t){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(p,"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)}makeGlyphDefs(e){const t=document.createElementNS(p,"defs");Object.entries(U).filter(([r])=>e.includes(r)).forEach(([r,o])=>{const n=document.createElementNS(p,"path");n.setAttribute("id",`glyph-${r}`),n.setAttribute("d",o.path),n.setAttribute("fill","currentColor"),n.setAttribute("transform",`translate(${o.xOffset}, ${o.yOffset}) scale(${k})`),t.appendChild(n)}),this.rootSvgElement.appendChild(t)}createGroup(e){const t=document.createElementNS(p,"g");return e&&t.classList.add(`vs-${e}`),t}commitElementsToDOM(e,t=this.rootElementRef){const s=document.createDocumentFragment();Array.isArray(e)?e.forEach(r=>{s.appendChild(r)}):s.appendChild(e),t.appendChild(s)}getLayerByName(e){switch(e){case"staff":return this.musicStaffLayer;case"notes":return this.musicNotesLayer;case"ui":return this.musicUILayer;default:throw new Error(`Layer with name '${e}' does not exist.`)}}addTotalRootSvgHeight(e){this.totalHeight+=e}addTotalRootSvgYOffset(e){this.totalYOffset+=e}applySizingToRootSvg(){this.parentGroupContainer.setAttribute("transform",`translate(0, ${this.totalYOffset})`);let e=this.width*this.scale;const t=(this.totalHeight+this.totalYOffset)*this.scale;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}`)}get rootSvgElement(){return this.svgElementRef}get parentGroupElement(){return this.parentGroupContainer}drawLine(e,t,s,r,o){const n=document.createElementNS(p,"line");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)}drawRect(e,t,s,r){const o=document.createElementNS(p,"rect");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"),s.appendChild(o),o}drawGlyph(e,t,s){s={xOffset:0,yOffset:0,...s};const r=document.createElementNS(p,"use");r.setAttribute("href",`#glyph-${e}`),(s.xOffset||s.yOffset)&&r.setAttribute("transform",`translate(${s.xOffset}, ${s.yOffset})`),t.appendChild(r)}destroy(){this.rootElementRef&&this.svgElementRef&&this.rootElementRef.contains(this.svgElementRef)&&this.rootElementRef.removeChild(this.svgElementRef)}}const W=["CLEF_TREBLE","CLEF_BASS","CLEF_ALTO","NOTE_HEAD_WHOLE","NOTE_HEAD_HALF","NOTE_HEAD_QUARTER","EIGHTH_NOTE","EIGHTH_NOTE_FLIPPED","ACCIDENTAL_SHARP","ACCIDENTAL_FLAT","ACCIDENTAL_NATURAL","ACCIDENTAL_DOUBLE_SHARP","ACCIDENTAL_DOUBLE_FLAT"];class Z{svgRendererInstance;strategyInstance;noteRendererInstance;options;noteEntries=[];noteCursorX=0;noteStartX;constructor(e,t){this.options={width:300,scale:1,noteStartX:0,staffType:"treble",spaceAbove:0,spaceBelow:0,staffColor:"black",staffBackgroundColor:"transparent",...t},this.svgRendererInstance=new O(e,{width:this.options.width,height:100,scale:this.options.scale,staffColor:this.options.staffColor,staffBackgroundColor:this.options.staffBackgroundColor,useGlyphs:W});const s=this.svgRendererInstance.rootSvgElement;switch(this.options.staffType){case"grand":this.strategyInstance=new H(this.svgRendererInstance,"grand");break;case"bass":this.strategyInstance=new A(this.svgRendererInstance,"bass");break;case"treble":this.strategyInstance=new A(this.svgRendererInstance,"treble");break;case"alto":this.strategyInstance=new A(this.svgRendererInstance,"alto");break;default:throw new Error(`The staff type ${this.options.staffType} is not supported. Please use "treble", "bass", "alto", or "grand".`)}if(this.strategyInstance.drawStaff(this.options.width),this.noteRendererInstance=new P(this.svgRendererInstance,this.strategyInstance),this.options.spaceAbove){const r=this.options.spaceAbove*10;this.svgRendererInstance.addTotalRootSvgYOffset(r)}if(this.options.spaceBelow){let r=this.options.spaceBelow*10;this.options.staffType==="grand"&&(r-=10/2),this.svgRendererInstance.addTotalRootSvgHeight(r)}this.noteStartX=38+this.options.noteStartX,this.svgRendererInstance.getLayerByName("notes").setAttribute("transform",`translate(${this.noteStartX}, 0)`),this.svgRendererInstance.applySizingToRootSvg(),this.svgRendererInstance.commitElementsToDOM(s)}drawNote(e){const t=Array.isArray(e)?e:[e],s=this.svgRendererInstance.getLayerByName("notes"),r=[];for(const o of t){let n;try{n=this.noteRendererInstance.renderNote(o)}catch(a){throw r.length>0&&this.svgRendererInstance.commitElementsToDOM(r,s),a}n.noteGroup.setAttribute("transform",`translate(${this.noteCursorX+n.accidentalOffset}, ${n.noteYPos})`),this.noteEntries.push({gElement:n.noteGroup,note:n.noteObj,xPos:this.noteCursorX+n.accidentalOffset,yPos:n.noteYPos,accidentalXOffset:n.accidentalOffset}),this.noteCursorX+=28+n.accidentalOffset,r.push(n.noteGroup)}this.svgRendererInstance.commitElementsToDOM(r,s)}drawChord(e){if(e.length<2)throw new Error("Provide more than one note for a chord.");const t=this.svgRendererInstance.getLayerByName("notes"),s=this.noteRendererInstance.renderChord(e);s.noteGroup.setAttribute("transform",`translate(${this.noteCursorX+s.accidentalOffset}, 0)`),this.noteEntries.push({gElement:s.noteGroup,note:m(e[0]),xPos:this.noteCursorX+s.accidentalOffset,yPos:0,accidentalXOffset:s.accidentalOffset}),this.noteCursorX+=28+s.accidentalOffset+s.cursorOffset,this.svgRendererInstance.commitElementsToDOM(s.noteGroup,t)}justifyNotes(){const e=this.options.width-38,t=this.noteEntries.length;if(t<=0||e<=0)return;const s=Math.round(e/t);this.noteEntries.map((o,n)=>{const a=(n+.5)*s,i=o.gElement.getBBox(),c=a-i.width/2-i.x,l=Math.round(c*10)/10;return{entry:o,newX:l,isChord:o.gElement.classList.contains("chord")}}).forEach(o=>{const{entry:n,newX:a,isChord:i}=o;i?n.gElement.setAttribute("transform",`translate(${a}, 0)`):n.gElement.setAttribute("transform",`translate(${a}, ${n.yPos})`),n.xPos=a})}clearAllNotes(){this.noteCursorX=0,this.svgRendererInstance.getLayerByName("notes").replaceChildren(),this.noteEntries=[]}changeNoteByIndex(e,t){if(t>=this.noteEntries.length)throw new Error("Note index was out of bounds.");const s=this.noteEntries[t],r=this.noteRendererInstance.renderNote(e),n=s.xPos-s.accidentalXOffset+r.accidentalOffset;r.noteGroup.setAttribute("transform",`translate(${n}, ${r.noteYPos})`),this.svgRendererInstance.getLayerByName("notes").replaceChild(r.noteGroup,s.gElement),this.noteEntries[t]={gElement:r.noteGroup,note:r.noteObj,xPos:n,yPos:r.noteYPos,accidentalXOffset:r.accidentalOffset}}changeChordByIndex(e,t){if(t>=this.noteEntries.length)throw new Error("Chord index was out of bounds.");if(e.length<2)throw new Error("Notes provided need to be more than one to be considered a chord.");const s=this.noteEntries[t],r=this.noteRendererInstance.renderChord(e),n=s.xPos-s.accidentalXOffset+r.accidentalOffset;r.noteGroup.setAttribute("transform",`translate(${n}, 0)`),this.svgRendererInstance.getLayerByName("notes").replaceChild(r.noteGroup,s.gElement),this.noteEntries[t]={gElement:r.noteGroup,note:m(e[0]),xPos:n,yPos:0,accidentalXOffset:r.accidentalOffset}}addClassToNoteByIndex(e,t){if(t>=this.noteEntries.length)throw new Error("Note index was out of bounds.");this.noteEntries[t].gElement.classList.add(e)}removeClassToNoteByIndex(e,t){if(t>=this.noteEntries.length)throw new Error("Note index was out of bounds.");this.noteEntries[t].gElement.classList.remove(e)}destroy(){this.noteEntries=[],this.svgRendererInstance.destroy()}}const u=30,X=19,y=12,V=4,j=6,x=1,R=38,q=["TIME_4","TIME_3","NOTE_HEAD_WHOLE","NOTE_HEAD_HALF","NOTE_HEAD_QUARTER","EIGHTH_NOTE","REST_WHOLE","REST_HALF","REST_QUARTER","REST_EIGHTH"];class Q{rendererInstance;options;barSpacing;quarterNoteSpacing;noteCursorX=0;noteEntries=[];maxBeatCount;currentBeatCount=0;currentBeatUICount=0;currentBeatUIElement=null;currentBeatUIXPos=R;constructor(e,t){this.options={width:300,scale:1,topNumber:4,barsCount:2,spaceAbove:0,spaceBelow:0,staffColor:"black",staffBackgroundColor:"white",currentBeatUIColor:"#24ff7450",...t},this.rendererInstance=new O(e,{width:this.options.width,height:100,scale:this.options.scale,staffColor:this.options.staffColor,staffBackgroundColor:this.options.staffBackgroundColor,useGlyphs:q});const s=this.rendererInstance.rootSvgElement;let r="TIME_4";switch(this.options.topNumber){case 3:r="TIME_3";break;case 4:r="TIME_4";break;default:throw new Error(`Time signature ${this.options.topNumber} not supported. Please use either 3 or 4.`)}if(this.options.barsCount<1||this.options.barsCount>3)throw new Error(`Bars count ${this.options.barsCount} not supported. Please use 1 - 3`);if(this.options.spaceAbove){const _=this.options.spaceAbove*10;this.rendererInstance.addTotalRootSvgYOffset(_)}if(this.options.spaceBelow){let _=this.options.spaceBelow*10;this.rendererInstance.addTotalRootSvgHeight(_)}const o=this.rendererInstance.getLayerByName("staff");this.rendererInstance.addTotalRootSvgHeight(u*2);const n=this.rendererInstance.createGroup("time-signature");o.appendChild(n);const a=u-X;this.rendererInstance.drawGlyph(r,n),this.rendererInstance.drawGlyph("TIME_4",n,{yOffset:X}),n.setAttribute("transform",`translate(0, ${a})`);let i=this.options.width-38;this.options.barsCount>1&&(i-=(this.options.barsCount-1)*y),i-=x,this.rendererInstance.drawLine(0,u,this.options.width-x,u,o),this.barSpacing=i/this.options.barsCount,this.quarterNoteSpacing=Math.round(this.barSpacing/this.options.topNumber),this.maxBeatCount=this.options.barsCount*this.options.topNumber;let c=this.barSpacing+38;const l=u/2,f=u+l;for(let _=0;_<this.options.barsCount-1;_++)this.rendererInstance.drawLine(c,l,c,f,o),c+=this.barSpacing;this.rendererInstance.getLayerByName("notes").setAttribute("transform",`translate(38, ${u})`),this.rendererInstance.applySizingToRootSvg(),this.rendererInstance.commitElementsToDOM(s)}createBeatUIElement(){const e=this.rendererInstance.getLayerByName("ui");this.currentBeatUIElement=this.rendererInstance.drawRect(this.quarterNoteSpacing/2,u*2,e,{x:R,fill:this.options.currentBeatUIColor})}handleNewBar(){this.noteCursorX+=y}translateGroupByDuration(e,t){return t.setAttribute("transform",`translate(${this.noteCursorX}, 0)`),this.quarterNoteSpacing*e}drawStem(e,t){this.rendererInstance.drawLine(10+(t??0),0,10+(t??0),-28,e)}renderNote(e,t){switch(e){case"w":this.rendererInstance.drawGlyph("NOTE_HEAD_WHOLE",t);break;case"h":this.rendererInstance.drawGlyph("NOTE_HEAD_HALF",t),this.drawStem(t);break;case"q":this.rendererInstance.drawGlyph("NOTE_HEAD_QUARTER",t),this.drawStem(t);break;case"e":this.rendererInstance.drawGlyph("EIGHTH_NOTE",t),this.drawStem(t);break}}renderRest(e,t){switch(e){case"w":this.rendererInstance.drawGlyph("REST_WHOLE",t);break;case"h":this.rendererInstance.drawGlyph("REST_HALF",t);break;case"q":this.rendererInstance.drawGlyph("REST_QUARTER",t);break;case"e":this.rendererInstance.drawGlyph("REST_EIGHTH",t);break}}checkAndCreateNewBar(){const e=this.currentBeatCount>0&&this.currentBeatCount%this.options.topNumber===0,t=this.currentBeatCount<this.maxBeatCount;e&&t&&this.handleNewBar()}checkAndFillBarWithRests(e){const t=this.options.topNumber-this.currentBeatCount%this.options.topNumber;if(e>t){const s=this.createRemainingRests(t);return this.handleNewBar(),s}return null}createRemainingRests(e){const t=[];let s=e;for(;s>0;){const r=this.rendererInstance.createGroup("rest");let o=0;s-E.h>=0?(this.rendererInstance.drawGlyph("REST_HALF",r),o=E.h):s-E.q>=0?(this.rendererInstance.drawGlyph("REST_QUARTER",r),o=E.q):(this.rendererInstance.drawGlyph("REST_EIGHTH",r),o=E.e),s-=o,this.currentBeatCount+=o,r.setAttribute("transform",`translate(${this.noteCursorX}, 0)`),this.noteCursorX+=o*this.quarterNoteSpacing,t.push(r)}return t}renderBeamRect(e,t,s,r){this.rendererInstance.drawRect(e-t,V,s,{x:10,y:-28+(r??0),fill:this.options.staffColor})}drawNote(e){const t=Array.isArray(e)?e:[e],s=this.rendererInstance.getLayerByName("notes"),r=[];for(const o of t){let n="w";try{n=C(o)}catch(f){throw r.length>0&&this.rendererInstance.commitElementsToDOM(r,s),f}const a=E[n];if(this.currentBeatCount>=this.maxBeatCount)throw r.length>0&&this.rendererInstance.commitElementsToDOM(r,s),new Error("Max beat count reached. Can't add additional notes.");this.checkAndCreateNewBar();const i=this.checkAndFillBarWithRests(a);i&&i.forEach(f=>{r.push(f),this.noteEntries.push(f)});const c=this.rendererInstance.createGroup("note"),l=this.translateGroupByDuration(a,c);this.noteCursorX+=l,this.currentBeatCount+=a,this.renderNote(n,c),r.push(c),this.noteEntries.push(c)}this.rendererInstance.commitElementsToDOM(r,s)}drawRest(e){const t=Array.isArray(e)?e:[e],s=this.rendererInstance.getLayerByName("notes"),r=[];for(const o of t){let n="w";try{n=C(o)}catch(f){throw r.length>0&&this.rendererInstance.commitElementsToDOM(r,s),f}const a=this.rendererInstance.createGroup("rest"),i=E[n],c=i*this.quarterNoteSpacing;if(this.currentBeatCount>=this.maxBeatCount)throw r.length>0&&this.rendererInstance.commitElementsToDOM(r,s),new Error("Max beat count reached. Can't add additional notes.");this.checkAndCreateNewBar();const l=this.checkAndFillBarWithRests(i);l&&l.forEach(f=>{r.push(f),this.noteEntries.push(f)}),this.renderRest(n,a),a.setAttribute("transform",`translate(${this.noteCursorX}, 0)`),this.noteCursorX+=c,this.currentBeatCount+=i,r.push(a),this.noteEntries.push(a)}this.rendererInstance.commitElementsToDOM(r,s)}drawBeamedNotes(e,t){if(t<2)throw new Error("Must provide a value greater than 2 for beamed note.");if(this.currentBeatCount>=this.maxBeatCount)throw new Error("Max beat count reached. Can't add additional beamed note.");let s="s";e==="s"?s="s":s=C(e),this.checkAndCreateNewBar();const r=this.rendererInstance.getLayerByName("notes"),o=E[s],n=o*this.quarterNoteSpacing,a=this.options.topNumber-this.currentBeatCount%this.options.topNumber,i=Math.min(t,a/o),c=this.rendererInstance.createGroup("beamed-note");c.setAttribute("transform",`translate(${this.noteCursorX}, 0)`);let l=0;for(let f=0;f<i;f++)this.rendererInstance.drawGlyph("NOTE_HEAD_QUARTER",c,{xOffset:l}),this.drawStem(c,l),l+=n,this.currentBeatCount+=o;this.renderBeamRect(l,n,c),e==="s"&&this.renderBeamRect(l,n,c,j),this.noteCursorX+=l,this.noteEntries.push(c),this.rendererInstance.commitElementsToDOM(c,r)}incrementCurrentBeatUI(){if(this.currentBeatUIElement||this.createBeatUIElement(),this.currentBeatUICount>=this.maxBeatCount){this.currentBeatUIElement.setAttribute("display","none");return}this.currentBeatUIElement?.getAttribute("display")==="none"&&this.currentBeatUIElement.removeAttribute("display"),this.currentBeatUICount++,this.currentBeatUICount>this.options.topNumber&&this.currentBeatUICount%this.options.topNumber===1&&(this.currentBeatUIXPos+=y),this.currentBeatUICount>1&&(this.currentBeatUIXPos+=this.quarterNoteSpacing),this.currentBeatUIElement.setAttribute("x",this.currentBeatUIXPos.toString())}resetCurrentBeatUI(){this.currentBeatUICount=0,this.currentBeatUIXPos=R,this.currentBeatUIElement&&(this.currentBeatUIElement.setAttribute("display","none"),this.currentBeatUIElement.setAttribute("x",this.currentBeatUIXPos.toString()))}clearAllNotes(){this.noteCursorX=0,this.currentBeatCount=0,this.rendererInstance.getLayerByName("notes").replaceChildren(),this.noteEntries=[]}destroy(){this.noteEntries=[],this.rendererInstance.destroy()}}const z=["CLEF_TREBLE","CLEF_BASS","CLEF_ALTO","NOTE_HEAD_WHOLE","NOTE_HEAD_HALF","NOTE_HEAD_QUARTER","EIGHTH_NOTE","EIGHTH_NOTE_FLIPPED","ACCIDENTAL_SHARP","ACCIDENTAL_FLAT","ACCIDENTAL_NATURAL","ACCIDENTAL_DOUBLE_SHARP","ACCIDENTAL_DOUBLE_FLAT"],N=60,K=N;class J{svgRendererInstance;strategyInstance;noteRendererInstance;options;activeEntries=[];noteBuffer=[];notesLayer;noteCursorX=0;noteStartX;constructor(e,t){this.options={width:300,scale:1,noteStartX:0,staffType:"treble",spaceAbove:0,spaceBelow:0,staffColor:"black",staffBackgroundColor:"transparent",...t},this.svgRendererInstance=new O(e,{width:this.options.width,height:100,scale:this.options.scale,staffColor:this.options.staffColor,staffBackgroundColor:this.options.staffBackgroundColor,useGlyphs:z});const s=this.svgRendererInstance.rootSvgElement;switch(this.options.staffType){case"grand":this.strategyInstance=new H(this.svgRendererInstance,"grand");break;case"bass":this.strategyInstance=new A(this.svgRendererInstance,"bass");break;case"treble":this.strategyInstance=new A(this.svgRendererInstance,"treble");break;case"alto":this.strategyInstance=new A(this.svgRendererInstance,"alto");break;default:throw new Error(`The staff type ${this.options.staffType} is not supported. Please use "treble", "bass", "alto", or "grand".`)}if(this.strategyInstance.drawStaff(this.options.width),this.noteRendererInstance=new P(this.svgRendererInstance,this.strategyInstance),this.options.spaceAbove){const r=this.options.spaceAbove*10;this.svgRendererInstance.addTotalRootSvgYOffset(r)}if(this.options.spaceBelow){let r=this.options.spaceBelow*10;this.options.staffType==="grand"&&(r-=10/2),this.svgRendererInstance.addTotalRootSvgHeight(r)}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)}renderFirstNoteGroups(){const e=this.options.width-this.options.noteStartX+K;for(;this.noteBuffer.length>0&&this.noteCursorX<e;)this.renderNextNote(),this.noteCursorX+=N;this.activeEntries.length>1&&(this.noteCursorX-=N)}renderNextNote(){if(this.noteBuffer.length<1)return;const e=this.noteBuffer[0],t=this.svgRendererInstance.createGroup("note-wrapper");if(e.type==="chord"){const s=this.noteRendererInstance.renderChord(e.notes);s.noteGroup.setAttribute("transform",`translate(0, ${s.noteYPos})`),t.appendChild(s.noteGroup)}else{const s=this.noteRendererInstance.renderNote(e.notes[0]);s.noteGroup.setAttribute("transform",`translate(0, ${s.noteYPos})`),t.appendChild(s.noteGroup)}t.style.transform=`translate(${this.noteCursorX}px, 0px)`,this.activeEntries.push({noteWrapper:t,xPos:this.noteCursorX}),this.noteBuffer.shift(),this.notesLayer.appendChild(t)}queueNotes(e){this.clearAllNotes();for(const t of e)Array.isArray(t)?this.noteBuffer.push({type:"chord",notes:t}):this.noteBuffer.push({type:"note",notes:[t]});this.renderFirstNoteGroups()}advanceNotes(){if(this.activeEntries.length<=0){this.clearAllNotes(),this.options.onNotesOut&&this.options.onNotesOut();return}this.activeEntries.forEach(t=>{t.xPos-=N,t.noteWrapper.style.transform=`translate(${t.xPos}px, 0px)`});const e=this.activeEntries[0];e.xPos<=0&&(this.notesLayer.removeChild(e.noteWrapper),this.activeEntries.shift()),this.renderNextNote()}clearAllNotes(){this.noteCursorX=0,this.notesLayer.replaceChildren(),this.activeEntries=[],this.noteBuffer=[]}destroy(){this.svgRendererInstance.destroy(),this.activeEntries=[],this.noteBuffer=[]}}d.MusicStaff=Z,d.RhythmStaff=Q,d.ScrollingStaff=J,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(d,T){typeof exports=="object"&&typeof module<"u"?T(exports):typeof define=="function"&&define.amd?define(["exports"],T):(d=typeof globalThis<"u"?globalThis:d||self,T(d.VectorScore={}))})(this,(function(d){"use strict";const N={treble:{staffType:"treble",paddingTop:13,paddingBottom:3,topLineNote:{name:"F",octave:5},topLineYPos:0,bottomLineYPos:40},bass:{staffType:"bass",paddingTop:0,paddingBottom:0,topLineNote:{name:"A",octave:3},topLineYPos:0,bottomLineYPos:40},alto:{staffType:"alto",paddingTop:0,paddingBottom:0,topLineNote:{name:"G",octave:4},topLineYPos:0,bottomLineYPos:40},grand:{staffType:"grand",paddingTop:13,paddingBottom:0,topLineNote:{name:"F",octave:5},topLineYPos:0,bottomLineYPos:110}},E={w:4,h:2,q:1,e:.5,s:.25},F=8,k=40,v={sharp:["F","C","G","D","A","E","B"],flat:["B","E","A","D","G","C","F"]},D={C:{type:"sharp",count:0},G:{type:"sharp",count:1},D:{type:"sharp",count:2},A:{type:"sharp",count:3},E:{type:"sharp",count:4},B:{type:"sharp",count:5},"F#":{type:"sharp",count:6},F:{type:"flat",count:1},Bb:{type:"flat",count:2},Eb:{type:"flat",count:3},Ab:{type:"flat",count:4},Db:{type:"flat",count:5},Gb:{type:"flat",count:6}},C={treble:{sharp:[5,5,5,5,4,5,4],flat:[4,5,4,5,4,5,4]},bass:{sharp:[3,3,3,3,2,3,2],flat:[2,3,2,3,2,3,3]},alto:{sharp:[4,4,4,4,3,4,4],flat:[4,5,4,5,4,5,4]},grand:{sharp:[],flat:[]}};function $(h){const e=D[h];if(!e)throw new Error(`Unknown key signature "${h}". Valid keys: ${Object.keys(D).join(", ")}`);return e}function W(h,e,t,s){const n=$(t);if(n.count===0)return 0;const r=n.type==="sharp"?"ACCIDENTAL_SHARP":"ACCIDENTAL_FLAT",o=h.getLayerByName("staff");return e.getKeySignatureYPositions(n.type,n.count).forEach(i=>{i.forEach((c,l)=>{h.drawGlyph(r,o,{xOffset:s+l*F,yOffset:c})})}),n.count*F}const Z={CLEF_TREBLE:{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",xOffset:0,yOffset:-14},CLEF_BASS:{path:"M101 0c68 0 110 46 110 114 0 120-102 190-199 237l-7 2c-3 0-5-2-5-5s2-5 6-7c92-52 146-114 146-223 0-62-18-103-60-103-40 0-64 29-64 44 0 4 1 8 7 8 5 0 9-3 19-3 20 0 38 15 38 41 0 24-17 41-42 41-32 0-48-27-48-58C2 50 33 0 101 0Zm148 32c13 0 22 10 22 22s-9 22-22 22c-12 0-21-10-21-22s9-22 21-22Zm1 99c12 0 21 9 21 21s-9 22-21 22-21-10-21-22 9-21 21-21Z",xOffset:0,yOffset:0},CLEF_ALTO:{path:"M91 9v174c0 3 2 2 3 2 11-3 27-13 36-58 1-6 3-10 7-10s6 4 8 11c5 17 15 37 43 37 25 0 32-25 32-77s-9-75-42-75c-5 0-33 2-33 10 0 2 6 5 11 6 7 3 15 11 15 26 0 17-11 27-26 27-17 0-31-11-31-32 0-25 22-50 69-50 65 0 93 45 93 87 0 54-30 92-83 92-11 0-18-2-24-4-4-1-8-1-11 1-6 3-14 16-14 24s8 21 14 24c3 2 7 2 11 1 6-2 13-4 24-4 53 0 83 38 83 92 0 42-28 87-93 87-47 0-69-25-69-50 0-21 14-32 31-32 15 0 26 10 26 27 0 15-8 23-15 26-5 1-11 4-11 6 0 8 28 10 33 10 33 0 42-23 42-75s-7-77-32-77c-28 0-38 20-43 37-2 7-4 11-8 11s-6-4-7-10c-9-45-25-55-36-58-1 0-3-1-3 2v174c0 5-3 8-8 8h-1c-5 0-8-3-8-8V9c0-5 3-8 8-8h1c5 0 8 3 8 8ZM8 1h34c6 0 9 3 9 8v382c0 5-3 8-9 8H8c-5 0-8-3-8-8V9c0-5 3-8 8-8Z",xOffset:0,yOffset:0},NOTE_HEAD_WHOLE:{path:"M77 0c34 0 74 19 74 45 0 24-19 45-77 45C21 90 0 68 0 45 0 20 30 0 77 0Zm-9 8c-17 0-30 5-30 24 0 22 23 50 47 50 16 0 28-8 28-26 0-21-20-48-45-48Z",xOffset:0,yOffset:-4.5},NOTE_HEAD_HALF:{path:"M35 90C15 90 0 79 0 60 0 42 17 0 70 0c21 0 36 12 36 30 0 12-12 60-71 60Zm-8-14c18 0 68-31 68-47l-2-6c-3-5-7-8-14-8-17 0-68 29-68 46l2 7c2 4 7 8 14 8Z",xOffset:0,yOffset:-4.5},NOTE_HEAD_QUARTER:{path:"M35 90C16 90 0 79 0 60 0 29 32 0 71 0c20 0 35 12 35 30 0 30-40 60-71 60Z",xOffset:0,yOffset:-4.5},EIGHTH_NOTE:{path:"M142 89c20 32 36 70 36 110 0 25-8 55-8 55-2 5-5 7-8 6h-1c-2-1-5-4-5-9l1-5c5-14 8-29 8-44 0-19-3-37-8-48-10-23-33-58-53-70v179c0 30-38 60-70 60-19 0-34-11-34-30 0-31 31-60 70-60 11 0 19 3 25 8V3c0-2 2-3 3-3 6 0 9 2 10 7 5 31 18 57 34 82Z",xOffset:0,yOffset:-28},EIGHTH_NOTE_FLIPPED:{path:"M9 323H0V60C0 29 32 0 71 0c20 0 35 12 35 30 0 30-40 60-71 60-19 0-26-9-26-9v158s58-56 58-89c0 0 0-25-8-43-5-12 10-17 14-6 13 34 9 48 9 48 0 39-41 97-41 97-20 27-32 77-32 77Z",xOffset:0,yOffset:-4},REST_WHOLE:{path:"M0 0h104v53H0V0Z",xOffset:0,yOffset:0},REST_HALF:{path:"M0 0h104v53H0V0Z",xOffset:0,yOffset:-5},REST_QUARTER:{path:"m28 151-18-22s-3-4-3-9c0-3 1-7 5-11 16-17 22-33 22-46 0-27-21-45-23-49l-1-6c0-5 4-8 7-8s5 1 7 3l61 71 1 7-1 5c-10 15-23 34-25 55v3c0 20 11 35 25 52 4 4 14 16 14 20 0 2-2 2-5 1-6-2-19-6-29-6-16 0-23 12-23 27 0 8 5 22 11 22 3 3 6 6 6 9s-2 5-7 5l-9-3c-27-21-43-39-43-57s13-35 32-35c3 0 10 3 14 0l-2-6-16-22Z",xOffset:0,yOffset:-16},REST_EIGHTH:{path:"M61 35c18 0 41-35 47-32 0 1 5 3 5 8l-5 17S64 189 62 190c-4 4-11 5-16 5-3 0-13 0-13-6 8-30 41-122 42-128 1-5 1-10-1-10-4 0-3 3-19 8C16 71 0 46 0 31 0 14 14 0 31 0c5 0 30 1 30 35Z",xOffset:0,yOffset:-10},ACCIDENTAL_SHARP:{path:"m67 66-8 3c-2 0-3 6-3 8v26c0 4 2 5 3 5l8-2 1-1c1 0 2 1 2 3v20c0 1-1 4-3 4l-8 4c-2 0-3 4-3 6v40c0 2-2 4-5 4-2 0-4-2-4-4v-35c0-2-1-5-4-5h-1l-17 7c-1 1-3 3-3 6v40c0 2-1 3-4 3-2 0-4-1-4-3v-35c0-1-1-5-3-5l-1 1-7 2v1c-2 0-3-1-3-3v-20c0-2 1-4 3-5l8-3c2-1 3-3 3-6V94c0-3-2-5-4-5l-7 3c-2 0-3-1-3-3V69l3-4 8-3c1-1 3-4 3-8V16c0-2 2-4 5-4 2 0 3 2 3 4v34c0 2 1 5 4 5l18-7c2-1 3-5 3-8V3c0-2 2-3 5-3 2 0 4 1 4 3v35c0 2 2 3 4 3l7-2h1c1 0 2 0 2 2v20c0 2-1 4-3 5Zm-20 46c2-11 2-23 0-34l-4-2c-7 0-20 6-21 11v35l4 1c6 0 20-5 21-11Z",xOffset:-8,yOffset:-10},ACCIDENTAL_FLAT:{path:"M4 196C1 193 0 9 0 9c0-6 5-9 10-9 3 0 6 2 6 5l-2 91c0 3 1 5 3 6h2l7-4c5-3 12-6 18-6 15 1 29 13 29 31 0 15-10 35-39 55-8 5-16 14-25 19l-2 1c-1 0-2 0-3-2Zm11-28c0 1 1 5 4 5l3-1c14-9 29-27 29-44 0-8-4-19-14-19-7 0-20 10-22 16l-1 10 1 33Z",xOffset:-8,yOffset:-14},ACCIDENTAL_NATURAL:{path:"m41 47 5-2h1l2 2v147c0 3-2 4-3 4h-4c-2 0-4-1-4-4v-43c0-2-2-3-5-3-8 0-25 7-29 8l-1 1c-2 0-3-1-3-3V4c0-3 1-4 4-4h3c2 0 4 1 4 4v48c0 2 1 2 3 2 7 0 26-7 26-7h1ZM11 88v31l3 1c8 0 24-6 24-12V78l-2-1c-7 0-25 7-25 11Z",xOffset:-8,yOffset:-10},ACCIDENTAL_DOUBLE_SHARP:{path:"M68 33h3c6 0 13 0 15-2l2-15C88 4 86 0 72 0c-6 0-12 1-14 4-2 1-2 7-2 13-1 5-8 17-12 17-5 0-9-10-11-15l-1-2c0-6-1-12-3-13-2-3-8-4-13-4C10 0 4 1 2 4L0 17l2 14c2 2 9 2 15 2h4c5 2 16 8 16 12 0 3-13 10-17 12h-3c-6 0-13 1-15 3L0 74l2 14 14 2 13-2c2-2 3-8 3-14 1-5 7-17 12-17 4 0 10 13 12 17 0 6 0 12 2 14l14 2c15 0 16-2 16-17l-2-13c-4-2-11-3-15-3h-3c-5-2-17-7-17-12 0-2 13-10 17-12Z",xOffset:-10,yOffset:-4},ACCIDENTAL_DOUBLE_FLAT:{path:"M102 93h2c15 0 29 12 29 30 0 15-10 35-39 55-8 5-16 14-26 19l-2 1-2-2-3-43c-6 7-15 16-27 25-7 5-15 14-25 19l-2 1c-1 0-2 0-3-2C2 193 0 8 0 8c0-5 6-8 10-8 3 0 6 2 6 5l-2 91c0 3 1 5 3 6h2c3 0 5-3 8-4 5-3 9-5 15-5h2c6 0 12 1 17 5L60 8c0-5 5-8 10-8 3 0 6 2 6 5l-2 91c0 3 1 5 3 6h2c3 0 5-3 7-4 6-3 10-5 16-5Zm-80 78c14-9 29-25 29-43 0-8-3-19-13-19-8 0-21 10-23 16l-1 11 1 31c0 2 1 5 4 5l3-1Zm59 0c15-9 29-25 29-43 0-6-2-12-5-16-2-2-4-3-8-3-7 0-21 10-23 16v8l1 34c0 2 1 5 3 5l3-1Z",xOffset:-14,yOffset:-14},TIME_4:{path:"M53 0h66S70 76 20 124h61V86l47-50v89h22v19h-22v27c0 9 13 9 13 9h9v10H61v-10h10s10 0 10-10v-26H0v-20S54 67 53 0Z",xOffset:0,yOffset:0},TIME_3:{path:"M2 43c0 21 15 30 30 30 5 0 28-2 28-27 0-11-16-20-16-24 0-14 56-15 56 26 0 26-19 38-31 38H45v13h24c12 0 33 15 33 41 0 38-54 40-54 25 0-3 10-11 10-21 0-20-15-27-27-27-17 0-32 8-31 30 1 30 36 43 75 43 36 0 75-19 75-50 0-34-23-47-37-47v-2c4 0 35-13 35-39 0-37-35-52-75-52C39 0 3 14 2 43Z",xOffset:0,yOffset:0}},V=/^(?<name>[A-Ga-g])(?<accidental>##|bb|[#bn]?)(?<octave>\d)(?<duration>[whqeWHQE]?)$/,j=/^[whqeWHQE]$/,g=["C","D","E","F","G","A","B"];function m(h){const e=h.match(V);if(!e||!e.groups)throw new Error(`Invalid note string format: ${h}. Expected format: [A-Ga-g][#|b]?[0-9][w|h|q|e].`);let{name:t,accidental:s,octave:n,duration:r}=e.groups;t=t.toUpperCase(),r=r.toLowerCase(),r||(r="w");const o={name:t,octave:parseInt(n),duration:r};return s&&(o.accidental=s),o}function L(h){const e=h.match(j);if(!e)throw new Error(`Invalid note duration '${h}'. Use w | h | q | e.`);return e[0].toString().toLowerCase()}function y(h){let e;switch(h){case"treble":e="CLEF_TREBLE";break;case"bass":e="CLEF_BASS";break;case"alto":e="CLEF_ALTO";break}if(!e)throw new Error(`Invalid clef type: ${h}. Valid clef types are: treble, bass, alto.`);return e}function B(h){let e=g.indexOf(h.name);return e+=h.octave*12,e}function I(h,e){return g.indexOf(h.name)-g.indexOf(e.name)+(h.octave-e.octave)*7}const O=48,H=40+30/2,P=20,X=90;class x{params;rendererRef;width=0;trebleStaffHeight=0;constructor(e,t){this.rendererRef=e;const s=N[t];if(!s)throw new Error(`Staff type ${t} is not supported`);this.params=s}drawStaffLines=(e,t)=>{let s=e;for(let n=0;n<5;n++)this.rendererRef.drawLine(0,s,this.width,s,t),s+=10;return s-10};drawStaff=e=>{this.width=e;const t=this.rendererRef.getLayerByName("staff");let s=this.drawStaffLines(0,t),n=this.drawStaffLines(s+30,t);this.rendererRef.drawLine(0,0,0,n,t),this.rendererRef.drawLine(this.width,0,this.width,n,t),this.trebleStaffHeight=s;let r=n,o=1;const a=y("treble"),i=y("bass");this.rendererRef.drawGlyph(a,t),this.rendererRef.drawGlyph(i,t,{yOffset:s+30}),r+=this.params.paddingBottom+1,o+=this.params.paddingTop,this.rendererRef.addTotalRootSvgHeight(r),this.rendererRef.addTotalRootSvgYOffset(o)};shouldNoteFlip(e){const t=Math.abs(e-X),s=Math.abs(e-P);return e===H?!1:t<=s?!(e>=X):e<=P}getLedgerLinesX(e,t){const s=[],n=B(e);let r=e.duration==="w"?17:12.5;if(n===O)return s.push({x1:-2,x2:r,yPos:0}),s;if(t<this.params.topLineYPos){let o=this.params.topLineYPos-10;for(;o>=t;)s.push({x1:-2,x2:r,yPos:o-t}),o-=10}else if(t>this.params.bottomLineYPos){let o=this.params.bottomLineYPos+10;for(;o<=t;)s.push({x1:-2,x2:r,yPos:o-t}),o+=10}return s}calculateNoteYPos=e=>{let s=I(this.params.topLineNote,e)*(10/2);const n=B(e);return n<O?s+=10:n===O&&(s=H),s};getKeySignatureYPositions(e,t){const s=v[e].slice(0,t),n=C.treble[e],r=C.bass[e],o=s.map((i,c)=>I(N.treble.topLineNote,{name:i,octave:n[c]})*(10/2)),a=s.map((i,c)=>I(N.bass.topLineNote,{name:i,octave:r[c]})*(10/2)+this.trebleStaffHeight+30);return[o,a]}}const q=20;class A{params;rendererRef;constructor(e,t){this.rendererRef=e;const s=N[t];if(!s)throw new Error(`Staff type ${t} is not supported`);this.params=s}drawStaff=e=>{const t=this.rendererRef.getLayerByName("staff");let s=0;for(let a=0;a<5;a++)this.rendererRef.drawLine(0,s,e,s,t),s+=10;this.rendererRef.drawLine(0,0,0,s-10,t),this.rendererRef.drawLine(e,0,e,s-10,t);let n=s-10+1,r=1;const o=y(this.params.staffType);this.rendererRef.drawGlyph(o,t),n+=this.params.paddingTop+this.params.paddingBottom,r+=this.params.paddingTop,this.rendererRef.addTotalRootSvgHeight(n),this.rendererRef.addTotalRootSvgYOffset(r)};shouldNoteFlip(e){return e<=q}getLedgerLinesX(e,t){const s=[];let n=e.duration==="w"?17:12.5;if(t<this.params.topLineYPos){let r=this.params.topLineYPos-10;for(;r>=t;)s.push({x1:-2,x2:n,yPos:r-t}),r-=10}else if(t>this.params.bottomLineYPos){let r=this.params.bottomLineYPos+10;for(;r<=t;)s.push({x1:-2,x2:n,yPos:r-t}),r+=10}return s}calculateNoteYPos=e=>I(this.params.topLineNote,e)*(10/2);getKeySignatureYPositions(e,t){const s=v[e].slice(0,t),n=C[this.params.staffType][e];return[s.map((o,a)=>this.calculateNoteYPos({name:o,octave:n[a]}))]}}class U{svgRendererInstance;strategyInstance;constructor(e,t){this.svgRendererInstance=e,this.strategyInstance=t}drawStem(e,t){t?this.svgRendererInstance.drawLine(0,0,0,28,e):this.svgRendererInstance.drawLine(10,0,10,-28,e)}chordOffsetConsecutiveAccidentals(e){let t=0,s=0,n=0;for(let r=0;r<e.length;r++){const o=e[r];if(o.noteObj.accidental&&n<3?(t+=-8,s=Math.min(s,t),n++):o.noteObj.accidental&&n<=3?(t=-8,n=1):(t=0,n=0),t!==0){const i=Array.from(o.noteGroup.getElementsByTagName("use")).find(c=>c.getAttribute("href")?.includes("ACCIDENTAL"));if(!i)continue;i.setAttribute("transform",`translate(${t+8}, 0)`)}}return-s}chordOffsetCloseNotes(e){let t=e[0],s=0;for(let n=1;n<e.length;n++){const r=e[n];if(-I(t.noteObj,r.noteObj)===1){s=28/2,r.noteGroup.setAttribute("transform",`translate(${s}, ${r.noteYPos})`);const i=Array.from(r.noteGroup.getElementsByTagName("use")).find(c=>c.getAttribute("href")?.includes("ACCIDENTAL"));if(i){const c=i.getAttribute("transform")?.match(/([-]?\d+)/),l=c&&c[0];let f=-s;l&&(f+=Number(l)),i.setAttribute("transform",`translate(${f}, 0)`)}n++,t=e[n];continue}t=r}return s}renderNote(e){const t=this.svgRendererInstance.createGroup("note"),s=m(e),n=this.strategyInstance.calculateNoteYPos({name:s.name,octave:s.octave});let r=this.strategyInstance.shouldNoteFlip(n);switch(s.duration){case"h":this.svgRendererInstance.drawGlyph("NOTE_HEAD_HALF",t),this.drawStem(t,r);break;case"q":this.svgRendererInstance.drawGlyph("NOTE_HEAD_QUARTER",t),this.drawStem(t,r);break;case"e":r?this.svgRendererInstance.drawGlyph("EIGHTH_NOTE_FLIPPED",t):this.svgRendererInstance.drawGlyph("EIGHTH_NOTE",t);break;default:this.svgRendererInstance.drawGlyph("NOTE_HEAD_WHOLE",t)}let o=0;switch(s.accidental){case"#":this.svgRendererInstance.drawGlyph("ACCIDENTAL_SHARP",t),o-=-8;break;case"b":this.svgRendererInstance.drawGlyph("ACCIDENTAL_FLAT",t),o-=-8;break;case"n":this.svgRendererInstance.drawGlyph("ACCIDENTAL_NATURAL",t),o-=-8;break;case"##":this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_SHARP",t),o-=-10;break;case"bb":this.svgRendererInstance.drawGlyph("ACCIDENTAL_DOUBLE_FLAT",t),o-=-14;break}return this.strategyInstance.getLedgerLinesX(s,n).forEach(i=>{this.svgRendererInstance.drawLine(i.x1,i.yPos,i.x2,i.yPos,t)}),{noteGroup:t,noteObj:s,noteYPos:n,accidentalOffset:o,cursorOffset:0}}renderChord(e){const t=this.svgRendererInstance.createGroup("chord"),s=[];for(const o of e){const a=this.renderNote(o);a.noteGroup.setAttribute("transform",`translate(0, ${a.noteYPos})`),t.appendChild(a.noteGroup),s.push({noteGroup:a.noteGroup,noteObj:a.noteObj,noteYPos:a.noteYPos,cursorOffset:0,accidentalOffset:0})}const n=this.chordOffsetConsecutiveAccidentals(s),r=this.chordOffsetCloseNotes(s);return{noteGroup:t,noteObj:s[0].noteObj,noteYPos:0,accidentalOffset:n,cursorOffset:r}}}const p="http://www.w3.org/2000/svg",K=.1,R=1200;class b{rootElementRef;svgElementRef;parentGroupContainer;musicStaffLayer;musicNotesLayer;musicUILayer;width;scale;totalYOffset=0;totalHeight=0;constructor(e,t){this.rootElementRef=e,this.width=t.width,this.scale=t.scale,this.width>R&&(this.width=R,console.warn(`Width provided for the staff ${this.width} exceeds the limit ${R}. Please use this value to fix positioning issues.`)),this.svgElementRef=document.createElementNS(p,"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)}makeGlyphDefs(e){const t=document.createElementNS(p,"defs");Object.entries(Z).filter(([n])=>e.includes(n)).forEach(([n,r])=>{const o=document.createElementNS(p,"path");o.setAttribute("id",`glyph-${n}`),o.setAttribute("d",r.path),o.setAttribute("fill","currentColor"),o.setAttribute("transform",`translate(${r.xOffset}, ${r.yOffset}) scale(${K})`),t.appendChild(o)}),this.rootSvgElement.appendChild(t)}createGroup(e){const t=document.createElementNS(p,"g");return e&&t.classList.add(`vs-${e}`),t}commitElementsToDOM(e,t=this.rootElementRef){const s=document.createDocumentFragment();Array.isArray(e)?e.forEach(n=>{s.appendChild(n)}):s.appendChild(e),t.appendChild(s)}getLayerByName(e){switch(e){case"staff":return this.musicStaffLayer;case"notes":return this.musicNotesLayer;case"ui":return this.musicUILayer;default:throw new Error(`Layer with name '${e}' does not exist.`)}}addTotalRootSvgHeight(e){this.totalHeight+=e}addTotalRootSvgYOffset(e){this.totalYOffset+=e}applySizingToRootSvg(){this.parentGroupContainer.setAttribute("transform",`translate(0, ${this.totalYOffset})`);let e=this.width*this.scale;const t=(this.totalHeight+this.totalYOffset)*this.scale;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}`)}get rootSvgElement(){return this.svgElementRef}get parentGroupElement(){return this.parentGroupContainer}drawLine(e,t,s,n,r){const o=document.createElementNS(p,"line");o.setAttribute("x1",e.toString()),o.setAttribute("y1",t.toString()),o.setAttribute("x2",s.toString()),o.setAttribute("y2",n.toString()),o.setAttribute("stroke","currentColor"),o.setAttribute("stroke-width","1"),r.appendChild(o)}drawRect(e,t,s,n){const r=document.createElementNS(p,"rect");return r.setAttribute("width",e.toString()),r.setAttribute("height",t.toString()),r.setAttribute("x",(n?.x??0).toString()),r.setAttribute("y",(n?.y??0).toString()),n?.fill?r.setAttribute("fill",n.fill):r.setAttribute("fill","currentColor"),s.appendChild(r),r}drawGlyph(e,t,s){s={xOffset:0,yOffset:0,...s};const n=document.createElementNS(p,"use");n.setAttribute("href",`#glyph-${e}`),(s.xOffset||s.yOffset)&&n.setAttribute("transform",`translate(${s.xOffset}, ${s.yOffset})`),t.appendChild(n)}destroy(){this.rootElementRef&&this.svgElementRef&&this.rootElementRef.contains(this.svgElementRef)&&this.rootElementRef.removeChild(this.svgElementRef)}}const Q=["CLEF_TREBLE","CLEF_BASS","CLEF_ALTO","NOTE_HEAD_WHOLE","NOTE_HEAD_HALF","NOTE_HEAD_QUARTER","EIGHTH_NOTE","EIGHTH_NOTE_FLIPPED","ACCIDENTAL_SHARP","ACCIDENTAL_FLAT","ACCIDENTAL_NATURAL","ACCIDENTAL_DOUBLE_SHARP","ACCIDENTAL_DOUBLE_FLAT"];class z{svgRendererInstance;strategyInstance;noteRendererInstance;options;noteEntries=[];noteCursorX=0;noteStartX;constructor(e,t){this.options={width:300,scale:1,noteStartX:0,staffType:"treble",spaceAbove:0,spaceBelow:0,staffColor:"black",staffBackgroundColor:"transparent",...t},this.svgRendererInstance=new b(e,{width:this.options.width,height:100,scale:this.options.scale,staffColor:this.options.staffColor,staffBackgroundColor:this.options.staffBackgroundColor,useGlyphs:Q});const s=this.svgRendererInstance.rootSvgElement;switch(this.options.staffType){case"grand":this.strategyInstance=new x(this.svgRendererInstance,"grand");break;case"bass":this.strategyInstance=new A(this.svgRendererInstance,"bass");break;case"treble":this.strategyInstance=new A(this.svgRendererInstance,"treble");break;case"alto":this.strategyInstance=new A(this.svgRendererInstance,"alto");break;default:throw new Error(`The staff type ${this.options.staffType} is not supported. Please use "treble", "bass", "alto", or "grand".`)}if(this.strategyInstance.drawStaff(this.options.width),this.noteRendererInstance=new U(this.svgRendererInstance,this.strategyInstance),this.options.spaceAbove){const r=this.options.spaceAbove*10;this.svgRendererInstance.addTotalRootSvgYOffset(r)}if(this.options.spaceBelow){let r=this.options.spaceBelow*10;this.options.staffType==="grand"&&(r-=10/2),this.svgRendererInstance.addTotalRootSvgHeight(r)}let n=0;this.options.keySignature&&(n=this.createKeySignature(this.options.keySignature)),this.noteStartX=38+this.options.noteStartX+n,this.svgRendererInstance.getLayerByName("notes").setAttribute("transform",`translate(${this.noteStartX}, 0)`),this.svgRendererInstance.applySizingToRootSvg(),this.svgRendererInstance.commitElementsToDOM(s)}createKeySignature(e){return W(this.svgRendererInstance,this.strategyInstance,e,k)}drawNote(e){const t=Array.isArray(e)?e:[e],s=this.svgRendererInstance.getLayerByName("notes"),n=[];for(const r of t){let o;try{o=this.noteRendererInstance.renderNote(r)}catch(a){throw n.length>0&&this.svgRendererInstance.commitElementsToDOM(n,s),a}o.noteGroup.setAttribute("transform",`translate(${this.noteCursorX+o.accidentalOffset}, ${o.noteYPos})`),this.noteEntries.push({gElement:o.noteGroup,note:o.noteObj,xPos:this.noteCursorX+o.accidentalOffset,yPos:o.noteYPos,accidentalXOffset:o.accidentalOffset}),this.noteCursorX+=28+o.accidentalOffset,n.push(o.noteGroup)}this.svgRendererInstance.commitElementsToDOM(n,s)}drawChord(e){if(e.length<2)throw new Error("Provide more than one note for a chord.");const t=this.svgRendererInstance.getLayerByName("notes"),s=this.noteRendererInstance.renderChord(e);s.noteGroup.setAttribute("transform",`translate(${this.noteCursorX+s.accidentalOffset}, 0)`),this.noteEntries.push({gElement:s.noteGroup,note:m(e[0]),xPos:this.noteCursorX+s.accidentalOffset,yPos:0,accidentalXOffset:s.accidentalOffset}),this.noteCursorX+=28+s.accidentalOffset+s.cursorOffset,this.svgRendererInstance.commitElementsToDOM(s.noteGroup,t)}justifyNotes(){const e=this.options.width-this.noteStartX,t=this.noteEntries.length;if(t<=0||e<=0)return;const s=Math.round(e/t);this.noteEntries.map((r,o)=>{const a=(o+.5)*s,i=r.gElement.getBBox(),c=a-i.width/2-i.x,l=Math.round(c*10)/10;return{entry:r,newX:l,isChord:r.gElement.classList.contains("chord")}}).forEach(r=>{const{entry:o,newX:a,isChord:i}=r;i?o.gElement.setAttribute("transform",`translate(${a}, 0)`):o.gElement.setAttribute("transform",`translate(${a}, ${o.yPos})`),o.xPos=a})}clearAllNotes(){this.noteCursorX=0,this.svgRendererInstance.getLayerByName("notes").replaceChildren(),this.noteEntries=[]}changeNoteByIndex(e,t){if(t>=this.noteEntries.length)throw new Error("Note index was out of bounds.");const s=this.noteEntries[t],n=this.noteRendererInstance.renderNote(e),o=s.xPos-s.accidentalXOffset+n.accidentalOffset;n.noteGroup.setAttribute("transform",`translate(${o}, ${n.noteYPos})`),this.svgRendererInstance.getLayerByName("notes").replaceChild(n.noteGroup,s.gElement),this.noteEntries[t]={gElement:n.noteGroup,note:n.noteObj,xPos:o,yPos:n.noteYPos,accidentalXOffset:n.accidentalOffset}}changeChordByIndex(e,t){if(t>=this.noteEntries.length)throw new Error("Chord index was out of bounds.");if(e.length<2)throw new Error("Notes provided need to be more than one to be considered a chord.");const s=this.noteEntries[t],n=this.noteRendererInstance.renderChord(e),o=s.xPos-s.accidentalXOffset+n.accidentalOffset;n.noteGroup.setAttribute("transform",`translate(${o}, 0)`),this.svgRendererInstance.getLayerByName("notes").replaceChild(n.noteGroup,s.gElement),this.noteEntries[t]={gElement:n.noteGroup,note:m(e[0]),xPos:o,yPos:0,accidentalXOffset:n.accidentalOffset}}addClassToNoteByIndex(e,t){if(t>=this.noteEntries.length)throw new Error("Note index was out of bounds.");this.noteEntries[t].gElement.classList.add(e)}removeClassToNoteByIndex(e,t){if(t>=this.noteEntries.length)throw new Error("Note index was out of bounds.");this.noteEntries[t].gElement.classList.remove(e)}destroy(){this.noteEntries=[],this.svgRendererInstance.destroy()}}const u=30,M=19,w=12,J=4,tt=6,Y=1,G=38,et=["TIME_4","TIME_3","NOTE_HEAD_WHOLE","NOTE_HEAD_HALF","NOTE_HEAD_QUARTER","EIGHTH_NOTE","REST_WHOLE","REST_HALF","REST_QUARTER","REST_EIGHTH"];class st{rendererInstance;options;barSpacing;quarterNoteSpacing;noteCursorX=0;noteEntries=[];maxBeatCount;currentBeatCount=0;currentBeatUICount=0;currentBeatUIElement=null;currentBeatUIXPos=G;constructor(e,t){this.options={width:300,scale:1,topNumber:4,barsCount:2,spaceAbove:0,spaceBelow:0,staffColor:"black",staffBackgroundColor:"white",currentBeatUIColor:"#24ff7450",...t},this.rendererInstance=new b(e,{width:this.options.width,height:100,scale:this.options.scale,staffColor:this.options.staffColor,staffBackgroundColor:this.options.staffBackgroundColor,useGlyphs:et});const s=this.rendererInstance.rootSvgElement;let n="TIME_4";switch(this.options.topNumber){case 3:n="TIME_3";break;case 4:n="TIME_4";break;default:throw new Error(`Time signature ${this.options.topNumber} not supported. Please use either 3 or 4.`)}if(this.options.barsCount<1||this.options.barsCount>3)throw new Error(`Bars count ${this.options.barsCount} not supported. Please use 1 - 3`);if(this.options.spaceAbove){const _=this.options.spaceAbove*10;this.rendererInstance.addTotalRootSvgYOffset(_)}if(this.options.spaceBelow){let _=this.options.spaceBelow*10;this.rendererInstance.addTotalRootSvgHeight(_)}const r=this.rendererInstance.getLayerByName("staff");this.rendererInstance.addTotalRootSvgHeight(u*2);const o=this.rendererInstance.createGroup("time-signature");r.appendChild(o);const a=u-M;this.rendererInstance.drawGlyph(n,o),this.rendererInstance.drawGlyph("TIME_4",o,{yOffset:M}),o.setAttribute("transform",`translate(0, ${a})`);let i=this.options.width-38;this.options.barsCount>1&&(i-=(this.options.barsCount-1)*w),i-=Y,this.rendererInstance.drawLine(0,u,this.options.width-Y,u,r),this.barSpacing=i/this.options.barsCount,this.quarterNoteSpacing=Math.round(this.barSpacing/this.options.topNumber),this.maxBeatCount=this.options.barsCount*this.options.topNumber;let c=this.barSpacing+38;const l=u/2,f=u+l;for(let _=0;_<this.options.barsCount-1;_++)this.rendererInstance.drawLine(c,l,c,f,r),c+=this.barSpacing;this.rendererInstance.getLayerByName("notes").setAttribute("transform",`translate(38, ${u})`),this.rendererInstance.applySizingToRootSvg(),this.rendererInstance.commitElementsToDOM(s)}createBeatUIElement(){const e=this.rendererInstance.getLayerByName("ui");this.currentBeatUIElement=this.rendererInstance.drawRect(this.quarterNoteSpacing/2,u*2,e,{x:G,fill:this.options.currentBeatUIColor})}handleNewBar(){this.noteCursorX+=w}translateGroupByDuration(e,t){return t.setAttribute("transform",`translate(${this.noteCursorX}, 0)`),this.quarterNoteSpacing*e}drawStem(e,t){this.rendererInstance.drawLine(10+(t??0),0,10+(t??0),-28,e)}renderNote(e,t){switch(e){case"w":this.rendererInstance.drawGlyph("NOTE_HEAD_WHOLE",t);break;case"h":this.rendererInstance.drawGlyph("NOTE_HEAD_HALF",t),this.drawStem(t);break;case"q":this.rendererInstance.drawGlyph("NOTE_HEAD_QUARTER",t),this.drawStem(t);break;case"e":this.rendererInstance.drawGlyph("EIGHTH_NOTE",t),this.drawStem(t);break}}renderRest(e,t){switch(e){case"w":this.rendererInstance.drawGlyph("REST_WHOLE",t);break;case"h":this.rendererInstance.drawGlyph("REST_HALF",t);break;case"q":this.rendererInstance.drawGlyph("REST_QUARTER",t);break;case"e":this.rendererInstance.drawGlyph("REST_EIGHTH",t);break}}checkAndCreateNewBar(){const e=this.currentBeatCount>0&&this.currentBeatCount%this.options.topNumber===0,t=this.currentBeatCount<this.maxBeatCount;e&&t&&this.handleNewBar()}checkAndFillBarWithRests(e){const t=this.options.topNumber-this.currentBeatCount%this.options.topNumber;if(e>t){const s=this.createRemainingRests(t);return this.handleNewBar(),s}return null}createRemainingRests(e){const t=[];let s=e;for(;s>0;){const n=this.rendererInstance.createGroup("rest");let r=0;s-E.h>=0?(this.rendererInstance.drawGlyph("REST_HALF",n),r=E.h):s-E.q>=0?(this.rendererInstance.drawGlyph("REST_QUARTER",n),r=E.q):(this.rendererInstance.drawGlyph("REST_EIGHTH",n),r=E.e),s-=r,this.currentBeatCount+=r,n.setAttribute("transform",`translate(${this.noteCursorX}, 0)`),this.noteCursorX+=r*this.quarterNoteSpacing,t.push(n)}return t}renderBeamRect(e,t,s,n){this.rendererInstance.drawRect(e-t,J,s,{x:10,y:-28+(n??0),fill:this.options.staffColor})}drawNote(e){const t=Array.isArray(e)?e:[e],s=this.rendererInstance.getLayerByName("notes"),n=[];for(const r of t){let o="w";try{o=L(r)}catch(f){throw n.length>0&&this.rendererInstance.commitElementsToDOM(n,s),f}const a=E[o];if(this.currentBeatCount>=this.maxBeatCount)throw n.length>0&&this.rendererInstance.commitElementsToDOM(n,s),new Error("Max beat count reached. Can't add additional notes.");this.checkAndCreateNewBar();const i=this.checkAndFillBarWithRests(a);i&&i.forEach(f=>{n.push(f),this.noteEntries.push(f)});const c=this.rendererInstance.createGroup("note"),l=this.translateGroupByDuration(a,c);this.noteCursorX+=l,this.currentBeatCount+=a,this.renderNote(o,c),n.push(c),this.noteEntries.push(c)}this.rendererInstance.commitElementsToDOM(n,s)}drawRest(e){const t=Array.isArray(e)?e:[e],s=this.rendererInstance.getLayerByName("notes"),n=[];for(const r of t){let o="w";try{o=L(r)}catch(f){throw n.length>0&&this.rendererInstance.commitElementsToDOM(n,s),f}const a=this.rendererInstance.createGroup("rest"),i=E[o],c=i*this.quarterNoteSpacing;if(this.currentBeatCount>=this.maxBeatCount)throw n.length>0&&this.rendererInstance.commitElementsToDOM(n,s),new Error("Max beat count reached. Can't add additional notes.");this.checkAndCreateNewBar();const l=this.checkAndFillBarWithRests(i);l&&l.forEach(f=>{n.push(f),this.noteEntries.push(f)}),this.renderRest(o,a),a.setAttribute("transform",`translate(${this.noteCursorX}, 0)`),this.noteCursorX+=c,this.currentBeatCount+=i,n.push(a),this.noteEntries.push(a)}this.rendererInstance.commitElementsToDOM(n,s)}drawBeamedNotes(e,t){if(t<2)throw new Error("Must provide a value greater than 2 for beamed note.");if(this.currentBeatCount>=this.maxBeatCount)throw new Error("Max beat count reached. Can't add additional beamed note.");let s="s";e==="s"?s="s":s=L(e),this.checkAndCreateNewBar();const n=this.rendererInstance.getLayerByName("notes"),r=E[s],o=r*this.quarterNoteSpacing,a=this.options.topNumber-this.currentBeatCount%this.options.topNumber,i=Math.min(t,a/r),c=this.rendererInstance.createGroup("beamed-note");c.setAttribute("transform",`translate(${this.noteCursorX}, 0)`);let l=0;for(let f=0;f<i;f++)this.rendererInstance.drawGlyph("NOTE_HEAD_QUARTER",c,{xOffset:l}),this.drawStem(c,l),l+=o,this.currentBeatCount+=r;this.renderBeamRect(l,o,c),e==="s"&&this.renderBeamRect(l,o,c,tt),this.noteCursorX+=l,this.noteEntries.push(c),this.rendererInstance.commitElementsToDOM(c,n)}incrementCurrentBeatUI(){if(this.currentBeatUIElement||this.createBeatUIElement(),this.currentBeatUICount>=this.maxBeatCount){this.currentBeatUIElement.setAttribute("display","none");return}this.currentBeatUIElement?.getAttribute("display")==="none"&&this.currentBeatUIElement.removeAttribute("display"),this.currentBeatUICount++,this.currentBeatUICount>this.options.topNumber&&this.currentBeatUICount%this.options.topNumber===1&&(this.currentBeatUIXPos+=w),this.currentBeatUICount>1&&(this.currentBeatUIXPos+=this.quarterNoteSpacing),this.currentBeatUIElement.setAttribute("x",this.currentBeatUIXPos.toString())}resetCurrentBeatUI(){this.currentBeatUICount=0,this.currentBeatUIXPos=G,this.currentBeatUIElement&&(this.currentBeatUIElement.setAttribute("display","none"),this.currentBeatUIElement.setAttribute("x",this.currentBeatUIXPos.toString()))}clearAllNotes(){this.noteCursorX=0,this.currentBeatCount=0,this.rendererInstance.getLayerByName("notes").replaceChildren(),this.noteEntries=[]}destroy(){this.noteEntries=[],this.rendererInstance.destroy()}}const nt=["CLEF_TREBLE","CLEF_BASS","CLEF_ALTO","NOTE_HEAD_WHOLE","NOTE_HEAD_HALF","NOTE_HEAD_QUARTER","EIGHTH_NOTE","EIGHTH_NOTE_FLIPPED","ACCIDENTAL_SHARP","ACCIDENTAL_FLAT","ACCIDENTAL_NATURAL","ACCIDENTAL_DOUBLE_SHARP","ACCIDENTAL_DOUBLE_FLAT"],S=60,rt=S;class ot{svgRendererInstance;strategyInstance;noteRendererInstance;options;activeEntries=[];noteBuffer=[];notesLayer;noteCursorX=0;noteStartX;constructor(e,t){this.options={width:300,scale:1,noteStartX:0,staffType:"treble",spaceAbove:0,spaceBelow:0,staffColor:"black",staffBackgroundColor:"transparent",...t},this.svgRendererInstance=new b(e,{width:this.options.width,height:100,scale:this.options.scale,staffColor:this.options.staffColor,staffBackgroundColor:this.options.staffBackgroundColor,useGlyphs:nt});const s=this.svgRendererInstance.rootSvgElement;switch(this.options.staffType){case"grand":this.strategyInstance=new x(this.svgRendererInstance,"grand");break;case"bass":this.strategyInstance=new A(this.svgRendererInstance,"bass");break;case"treble":this.strategyInstance=new A(this.svgRendererInstance,"treble");break;case"alto":this.strategyInstance=new A(this.svgRendererInstance,"alto");break;default:throw new Error(`The staff type ${this.options.staffType} is not supported. Please use "treble", "bass", "alto", or "grand".`)}if(this.strategyInstance.drawStaff(this.options.width),this.noteRendererInstance=new U(this.svgRendererInstance,this.strategyInstance),this.options.spaceAbove){const n=this.options.spaceAbove*10;this.svgRendererInstance.addTotalRootSvgYOffset(n)}if(this.options.spaceBelow){let n=this.options.spaceBelow*10;this.options.staffType==="grand"&&(n-=10/2),this.svgRendererInstance.addTotalRootSvgHeight(n)}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)}renderFirstNoteGroups(){const e=this.options.width-this.options.noteStartX+rt;for(;this.noteBuffer.length>0&&this.noteCursorX<e;)this.renderNextNote(),this.noteCursorX+=S;this.activeEntries.length>1&&(this.noteCursorX-=S)}renderNextNote(){if(this.noteBuffer.length<1)return;const e=this.noteBuffer[0],t=this.svgRendererInstance.createGroup("note-wrapper");if(e.type==="chord"){const s=this.noteRendererInstance.renderChord(e.notes);s.noteGroup.setAttribute("transform",`translate(0, ${s.noteYPos})`),t.appendChild(s.noteGroup)}else{const s=this.noteRendererInstance.renderNote(e.notes[0]);s.noteGroup.setAttribute("transform",`translate(0, ${s.noteYPos})`),t.appendChild(s.noteGroup)}t.style.transform=`translate(${this.noteCursorX}px, 0px)`,this.activeEntries.push({noteWrapper:t,xPos:this.noteCursorX}),this.noteBuffer.shift(),this.notesLayer.appendChild(t)}queueNotes(e){this.clearAllNotes();for(const t of e)Array.isArray(t)?this.noteBuffer.push({type:"chord",notes:t}):this.noteBuffer.push({type:"note",notes:[t]});this.renderFirstNoteGroups()}advanceNotes(){if(this.activeEntries.length<=0){this.clearAllNotes(),this.options.onNotesOut&&this.options.onNotesOut();return}this.activeEntries.forEach(t=>{t.xPos-=S,t.noteWrapper.style.transform=`translate(${t.xPos}px, 0px)`});const e=this.activeEntries[0];e.xPos<=0&&(this.notesLayer.removeChild(e.noteWrapper),this.activeEntries.shift()),this.renderNextNote()}clearAllNotes(){this.noteCursorX=0,this.notesLayer.replaceChildren(),this.activeEntries=[],this.noteBuffer=[]}destroy(){this.svgRendererInstance.destroy(),this.activeEntries=[],this.noteBuffer=[]}}d.MusicStaff=z,d.RhythmStaff=st,d.ScrollingStaff=ot,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vector-score",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "keywords": [