vector-score 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Drake Buentello
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,240 @@
1
+ <img src="public/vector-score-icon.svg" alt="VectorScore Logo" width="150" height="150" />
2
+
3
+ # Vector Score
4
+
5
+ A lightweight, SVG-based TypeScript library for rendering musical staves, notes, and rhythm patterns in the browser.
6
+
7
+ ## Features
8
+
9
+ * **Multiple Staff Types**: Supports Treble, Bass, Alto, and Grand staves.
10
+ * **Rhythm Staff**: Dedicated staff for rhythm exercises with customizable time signatures and bar handling.
11
+ * **Scrolling Staff** Staff made to allow for 'endless' style of notes.
12
+ * **SVG Rendering**: Crisp, scalable vector graphics suitable for any screen size.
13
+ * **Flexible Note Input**: Simple string-based syntax for defining notes, chords, and rests.
14
+ * **Interactive Features**: Includes methods for error feedback (highlighting wrong notes) and note justification.
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install DrakeB1234/VectorScore
20
+ ````
21
+
22
+ ## Development
23
+
24
+ To start the development server with a playground:
25
+
26
+ ```bash
27
+ npm run dev
28
+ ```
29
+
30
+ To build the library for production:
31
+
32
+ ```bash
33
+ npm run build
34
+ ```
35
+
36
+ ## Usage
37
+
38
+ ### 1. Setup HTML
39
+
40
+ Create a container element in your HTML where the staff will be rendered.
41
+
42
+ ```html
43
+ <div id="staff-container"></div>
44
+ ```
45
+
46
+ ### 2. Import and Initialize
47
+
48
+ ### Standard Music Staff (Treble, Bass, Alto)
49
+
50
+ ```typescript
51
+ import { MusicStaff } from 'vector-score';
52
+
53
+ const container = document.getElementById('staff-container');
54
+
55
+ const staff = new MusicStaff(container, {
56
+ staffType: 'treble', // 'treble', 'bass', 'alto', or 'grand'
57
+ width: 400,
58
+ scale: 1.2,
59
+ spaceBelow: 1
60
+ });
61
+
62
+ // Draw a C Minor scale (quarter notes)
63
+ // Format: NoteName + Accidental(optional) + Octave + Duration
64
+ staff.drawNote(['C4q', 'D4q', 'Eb4q', 'F4q', 'G4q', 'Ab4q', 'Bb4q', 'C5q']);
65
+
66
+ // Draw a C Chord
67
+ staff.drawChord(['C4w', 'E4w', 'G4w']);
68
+
69
+ // Evenly space all notes on the staff
70
+ staff.justifyNotes();
71
+ ```
72
+ #### Resulting Staff
73
+ ![Alt Text](https://raw.githubusercontent.com/DrakeB1234/VectorScore/master/public/MusicStaffTrebleResult.svg)
74
+
75
+ ### Grand Staff
76
+
77
+ ```typescript
78
+ import { MusicStaff } from 'vector-score';
79
+
80
+ const grandStaff = new MusicStaff(container, {
81
+ staffType: 'grand',
82
+ width: 400,
83
+ spaceBelow: 2,
84
+ spaceAbove: 2
85
+ });
86
+
87
+ // Notes are automatically positioned on the correct stave based on pitch
88
+ grandStaff.drawNote(['G4q', 'E4h', 'C4w', "A3h", "F3h"]);
89
+
90
+ grandStaff.drawChord(["G3w", "C4w", "E4w"]);
91
+ ```
92
+ #### Resulting Staff
93
+ ![Alt Text](https://raw.githubusercontent.com/DrakeB1234/VectorScore/master/public/MusicStaffGrandResult.svg)
94
+
95
+ ### Rhythm Staff
96
+
97
+ ```typescript
98
+ import { RhythmStaff } from 'vector-score';
99
+
100
+ const rhythmContainer = document.getElementById('rhythm-container');
101
+
102
+ const rhythm = new RhythmStaff(rhythmContainer, {
103
+ width: 400,
104
+ topNumber: 4, // Time signature numerator (e.g., 4/4 time)
105
+ barsCount: 2
106
+ });
107
+
108
+ // Draw notes and rests
109
+ rhythm.drawNote(['q', 'q']); // Duration only
110
+ rhythm.drawRest(['h']);
111
+
112
+ // Draw beamed note
113
+ rhythm.drawBeamedNotes("e", 4); // Draws a beamed note of 4 eighth notes
114
+
115
+ // Finish the bar
116
+ rhythm.drawNote(['q', 'q']);
117
+
118
+ // Increment the UI to show the first beat in the bar
119
+ rhythm.incrementCurrentBeatUI();
120
+ ```
121
+ #### Resulting Staff
122
+ ![Alt Text](https://raw.githubusercontent.com/DrakeB1234/VectorScore/master/public/RhythmStaffResult.svg)
123
+
124
+ ### Scrolling Staff
125
+
126
+ ```typescript
127
+ import { ScrollingStaff } from 'vector-score';
128
+
129
+ const scrollingContainer = document.getElementById('scrolling-container');
130
+
131
+ const scrollingStaff = new ScrollingStaff(scrollingContainer, {
132
+ width: 400,
133
+ spaceBelow: 2,
134
+ spaceAbove: 2,
135
+ onNotesOut: handleNotesOut, // Connect a handler when notes run out (optional)
136
+ });
137
+
138
+ // Handler for when notes run out
139
+ function handleNotesOut() {
140
+ isNotesOut = true;
141
+ }
142
+
143
+ // ****
144
+ // NOTE CSS SELECTOR FOR NOTES FOR ANIMATION IS
145
+ // .vs-scrolling-notes-layer > g.vs-note-wrapper { transition: transform 0.2s ease-in }
146
+ // ****
147
+
148
+ // Add notes to the queue
149
+ // 5 single notes, a C chord, 2 more notes, finally a D chord
150
+ scrollingStaff.queueNotes([
151
+ "C4w",
152
+ "F4w",
153
+ "C4w",
154
+ "B4w",
155
+ "D4w",
156
+ ["C4w", "E4w", "G4w"],
157
+ "B4w",
158
+ "D4w",
159
+ ["D4w", "F#4w", "A4w"],
160
+ ]);
161
+
162
+ // The button event listener calls 'advanceNotes()' to move the notes over, one step at a time.
163
+ ```
164
+ #### Resulting Staff
165
+ ![Alt Text](https://raw.githubusercontent.com/DrakeB1234/VectorScore/master/public/ScrollingStaffResult.webp)
166
+
167
+ ## Note String Syntax
168
+
169
+ Notes are defined using a specific string format parsed by the library:
170
+
171
+ `[Name][Accidental?][Octave][Duration]`
172
+
173
+ * **Name**: `A` - `G` (Case insensitive)
174
+ * **Accidental**: `#` (Sharp) or `b` (Flat). Optional.
175
+ * **Octave**: `0` - `9`
176
+ * **Duration**:
177
+ * `w`: Whole
178
+ * `h`: Half
179
+ * `q`: Quarter
180
+ * `e`: Eighth
181
+
182
+ **Examples:**
183
+ * `C4w`: C, Octave 4, Whole note
184
+ * `F#5q`: F Sharp, Octave 5, Quarter note
185
+ * `Bb3e`: B Flat, Octave 3, Eighth note
186
+
187
+ ## API Reference
188
+
189
+ ### MusicStaff Class
190
+
191
+ | Method | Description |
192
+ | :--- | :--- |
193
+ | `drawNote(notes: string \| string[])` | Draws one or multiple notes sequentially. |
194
+ | `drawChord(notes: string \| string[])` | Draws multiple notes stacked as a chord at the current cursor position. |
195
+ | `justifyNotes()` | Evenly spaces all currently drawn notes across the staff width. |
196
+ | `clearAllNotes()` | Removes all notes from the staff and resets the cursor. |
197
+ | `changeNoteByIndex(note: string, index: number)` | Replaces a note at a specific index with a new note. |
198
+ | `changeChordByIndex(notes: string[], index: number)` | Replaces a chord at a specific index with a new chord. |
199
+ | `destroy()` | Destroys internal arrays and elements |
200
+
201
+ ### RhythmStaff Class
202
+
203
+ | Method | Description |
204
+ | :--- | :--- |
205
+ | `drawNote(notes: string \| string[])` | Draws rhythm notes. |
206
+ | `drawRest(rests: string \| string[])` | Draws rests. |
207
+ | `drawBeamedNotes(type: 'e'\|'s', count: number)` | Draws a group of beamed eighth or sixteenth notes. |
208
+ | `clearAllNotes()` | Removes all items from the staff. |
209
+ | `incrementCurrentBeatUI()` | Starts the UI for showing the current beat. Connect to a external interval for accurate showing of current beat. |
210
+ | `resetCurrentBeatUI()` | Must be called if current beat goes over the total beats in the bar to reset its state |
211
+ | `destroy()` | Destroys internal arrays and elements |
212
+
213
+ ### ScrollingStaff Class
214
+
215
+ | Method | Description |
216
+ | :--- | :--- |
217
+ | `queueNotes(notes: (string \| string[])[])` | Queues notes on the staff. ["C4", ["C4", "E4", "G4"], "B4"] |
218
+ | `advanceNotes()` | Advances notes to the next position |
219
+ | `clearAllNote()` | Clears all notes on the staff |
220
+ | `destroy()` | Destroys internal arrays and elements |
221
+
222
+ ## Configuration Options
223
+
224
+ ### MusicStaffOptions
225
+ * `width`: Total width of the SVG in pixels.
226
+ * `scale`: Zoom factor (default: 1).
227
+ * `staffType`: `'treble' | 'bass' | 'alto' | 'grand'`.
228
+ * `spaceAbove`: Padding units above the staff (in staff line spaces).
229
+ * `spaceBelow`: Padding units below the staff (in staff line spaces).
230
+ * `staffColor`: CSS color string for lines and notes.
231
+ * `staffBackgroundColor`: CSS color string for background.
232
+
233
+ ### RhythmStaffOptions
234
+ * `topNumber`: The top number of the time signature (e.g., 4 for 4/4 time).
235
+ * `barsCount`: Number of measures to draw.
236
+ * `currentBeatUIColor`: CSS color string for current beat UI.
237
+ * *Inherits sizing and color options from MusicStaffOptions.*
238
+
239
+ ### ScrollingStaffOptions
240
+ * same as MusicStaffOptions
@@ -0,0 +1,127 @@
1
+ import { StaffTypes } from '../types';
2
+ export type MusicStaffOptions = {
3
+ width?: number;
4
+ scale?: number;
5
+ staffType?: StaffTypes;
6
+ spaceAbove?: number;
7
+ spaceBelow?: number;
8
+ staffColor?: string;
9
+ staffBackgroundColor?: string;
10
+ };
11
+ export default class MusicStaff {
12
+ private svgRendererInstance;
13
+ private strategyInstance;
14
+ private noteRendererInstance;
15
+ private options;
16
+ private noteEntries;
17
+ private noteCursorX;
18
+ /**
19
+ * Creates an instance of a MusicStaff, A single staff.
20
+ *
21
+ * @param rootElementCtx - The element (div) reference that will append the music staff elements to.
22
+ * @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
23
+ */
24
+ constructor(rootElementCtx: HTMLElement, options?: MusicStaffOptions);
25
+ /**
26
+ * Draws a note on the staff.
27
+ * @param notes - A single string OR array of note strings in the format `[Root][Accidental?][Octave][Duration?]`.
28
+ * If an array is passed, it will draw each individual note on the staff.
29
+ *
30
+ * * **Root**: (A-G)
31
+ * * **Accidental** (Optional): `#` (sharp) `b` (flat) `n` (natural) `##` (double sharp) or `bb` (double flat).
32
+ * * **Octave**: The octave number (e.g., `4`).
33
+ * * **Duration** (Optional): `w` (whole) `h` (half) `q` (quarter) or `e` (eighth). Defaults to `w` if duration is omitted
34
+ * @returns void
35
+ * @throws {Error} If a note string is not correct format. If an array was passed, it will still draw whatever correctly formatted notes before it.
36
+ *
37
+ * * @example
38
+ * // Draws the specified notes individually on the staff
39
+ * drawNote(["D4w", "F4w", "A4w", "B#5q", "Ebb4e"]);
40
+ *
41
+ * * @example
42
+ * // Draws the specified single note on the staff
43
+ * drawNote("D4w");
44
+ */
45
+ drawNote(notes: string | string[]): void;
46
+ /**
47
+ * Draws a chord on the staff.
48
+ * @param notes - An array of note strings in the format `[Root][Accidental?][Octave][Duration?]`.
49
+ *
50
+ * * **Root**: (A-G)
51
+ * * **Accidental** (Optional): `#` (sharp) `b` (flat) `n` (natural) `##` (double sharp) or `bb` (double flat).
52
+ * * **Octave**: The octave number (e.g., `4`).
53
+ * * **Duration** (Optional): `w` (whole) `h` (half) `q` (quarter) or `e` (eighth). Defaults to `w` if duration is omitted
54
+ * @returns void
55
+ * @throws {Error} If a note string is not correct format OR if less than one note was provided.
56
+ *
57
+ * * @example
58
+ * // Draw a D minor chord starting on 4th octave
59
+ * drawChord(["D4w", "F4w", "A4w"], 0);
60
+ */
61
+ drawChord(notes: string[]): void;
62
+ /**
63
+ * Evenly spaces out the notes on the staff.
64
+ * @returns Returns early if no notes are on the staff
65
+ */
66
+ justifyNotes(): void;
67
+ /**
68
+ * Clears staff of notes and resets internal positioning.
69
+ * @returns void
70
+ */
71
+ clearAllNotes(): void;
72
+ /**
73
+ * Changes the note by index to the specified note.
74
+ * @param notes - A note string in the format `[Root][Accidental?][Octave][Duration?]`.
75
+ *
76
+ * * **Root**: (A-G)
77
+ * * **Accidental** (Optional): `#` (sharp) `b` (flat) `n` (natural) `##` (double sharp) or `bb` (double flat).
78
+ * * **Octave**: The octave number (e.g., `4`).
79
+ * * **Duration** (Optional): `w` (whole) `h` (half) `q` (quarter) or `e` (eighth). Defaults to `w` if duration is omitted
80
+ * @param noteIndex The index of the note that will replaced by the specified note.
81
+ * @returns void
82
+ * @throws {Error} If the index provided is out of bounds, or if a note string is not correct format.
83
+ *
84
+ * * @example
85
+ * // Changes note at pos `0` to a B flat quarter note on the 3rd octave
86
+ * changeNoteByIndex("Bb3q", 0);
87
+ */
88
+ changeNoteByIndex(note: string, noteIndex: number): void;
89
+ /**
90
+ * Changes the note by index to the specified chord.
91
+ * @param notes - An array of note strings in the format `[Root][Accidental?][Octave][Duration?]`.
92
+ *
93
+ * * **Root**: (A-G)
94
+ * * **Accidental** (Optional): `#` (sharp) `b` (flat) `n` (natural) `##` (double sharp) or `bb` (double flat).
95
+ * * **Octave**: The octave number (e.g., `4`).
96
+ * * **Duration** (Optional): `w` (whole) `h` (half) `q` (quarter) or `e` (eighth). Defaults to `w` if duration is omitted
97
+ * @param noteIndex The index of the note that will replaced by the specified chord.
98
+ * @returns void
99
+ * @throws {Error} If the index provided is out of bounds, or if a note string is not correct format.
100
+ *
101
+ * * @example
102
+ * // Changes chord at pos `0` to a C Minor chord
103
+ * changeChordByIndex(["C4w", "D#4w", "G4w"], 0);
104
+ */
105
+ changeChordByIndex(notes: string[], chordIndex: number): void;
106
+ /**
107
+ * Adds a class to the note by the index provided.
108
+ * @param className The name added to the note
109
+ * @param noteIndex The index of the note that will have 'className' added to it.
110
+ * @returns void
111
+ * @throws {Error} If the index provided is out of bounds
112
+ */
113
+ addClassToNoteByIndex(className: string, noteIndex: number): void;
114
+ /**
115
+ * Removes a class to the note by the index provided.
116
+ * @param className The name removed from the note
117
+ * @param noteIndex The index of the note that will have 'className' removed from it.
118
+ * @returns void
119
+ * @throws {Error} If the index provided is out of bounds
120
+ */
121
+ removeClassToNoteByIndex(className: string, noteIndex: number): void;
122
+ /**
123
+ * Removes the root svg element and cleans up arrays.
124
+ * @returns void
125
+ */
126
+ destroy(): void;
127
+ }
@@ -0,0 +1,27 @@
1
+ import { StaffStrategy } from '../strategies/StrategyInterface';
2
+ import { NoteObj } from '../types';
3
+ import { default as SVGRenderer } from './SVGRenderer';
4
+ /**
5
+ * @param {SVGGElement} noteGroup - The group that is returned from renderNote or renderGroup
6
+ * @param {NoteObj} noteObj - The parse note string into NoteObj
7
+ * @param {number} noteYPos - The Y pos of the notes group
8
+ * @param {number} accidentalOffset - The total xOffset from any accidentals from a note. Chords could have a 1..3 of these offsets
9
+ * @param {number} cursorOffset - The requested amount the cursor should be offset. Chords use this when a note is close and offsetted to the left.
10
+ */
11
+ export type RenderNoteReturn = {
12
+ noteGroup: SVGGElement;
13
+ noteObj: NoteObj;
14
+ noteYPos: number;
15
+ accidentalOffset: number;
16
+ cursorOffset: number;
17
+ };
18
+ export default class NoteRenderer {
19
+ private svgRendererInstance;
20
+ private strategyInstance;
21
+ constructor(svgRenderer: SVGRenderer, strategy: StaffStrategy);
22
+ private drawStem;
23
+ private chordOffsetConsecutiveAccidentals;
24
+ private chordOffsetCloseNotes;
25
+ renderNote(noteString: string): RenderNoteReturn;
26
+ renderChord(notes: string[]): RenderNoteReturn;
27
+ }
@@ -0,0 +1,118 @@
1
+ export type RhythmStaffOptions = {
2
+ width?: number;
3
+ scale?: number;
4
+ topNumber?: number;
5
+ barsCount?: number;
6
+ spaceAbove?: number;
7
+ spaceBelow?: number;
8
+ staffColor?: string;
9
+ staffBackgroundColor?: string;
10
+ currentBeatUIColor?: string;
11
+ };
12
+ export default class RhythmStaff {
13
+ private rendererInstance;
14
+ private options;
15
+ private barSpacing;
16
+ private quarterNoteSpacing;
17
+ private noteCursorX;
18
+ private noteEntries;
19
+ private maxBeatCount;
20
+ private currentBeatCount;
21
+ private currentBeatUICount;
22
+ private currentBeatUIElement;
23
+ private currentBeatUIXPos;
24
+ /**
25
+ * Creates an instance of a RhythmStaff, A single staff that will automatically apply positioning of elements based on the duration of a note.
26
+ *
27
+ * @param rootElementCtx - The element (div) reference that will append the music staff elements to.
28
+ * @param options - Optional configuration settings. All config options are in the type RhythmStaffOptions
29
+ * @throws {Error} - If top number is not 3 or 4 OR if bars count is not between 1 - 3. These are the currently only supported values.
30
+ */
31
+ constructor(rootElementCtx: HTMLElement, options?: RhythmStaffOptions);
32
+ private createBeatUIElement;
33
+ private handleNewBar;
34
+ private translateGroupByDuration;
35
+ private drawStem;
36
+ private renderNote;
37
+ private renderRest;
38
+ private checkAndCreateNewBar;
39
+ private checkAndFillBarWithRests;
40
+ private createRemainingRests;
41
+ private renderBeamRect;
42
+ /**
43
+ * Draws a note duration on the staff.
44
+ * @param notes - A single string OR array of note strings in the format `[Duration]`.
45
+ * If an array is passed, it will draw each individual note duration on the staff.
46
+ * If a duration exceeds the remaining value on the bar, rests will fill the empty space.
47
+ *
48
+ * * **Duration**: `w` (whole) `h` (half) `q` (quarter) `e` (eighth)
49
+ * @returns void
50
+ * @throws {Error} If a note string is not correct format. If an array was passed, it will still draw whatever correctly formatted notes before it.
51
+ *
52
+ * * @example
53
+ * // Draws the specified note durations individually on the staff
54
+ * drawNote(["q", "q", "q", "q", "w"]);
55
+ *
56
+ * * @example
57
+ * // Draws the specified single note duration on the staff
58
+ * drawNote("w");
59
+ */
60
+ drawNote(notes: string | string[]): void;
61
+ /**
62
+ * Draws a rest duration on the staff.
63
+ * @param rests - A single string OR array of rest strings in the format `[Duration]`.
64
+ * If an array is passed, it will draw each individual rest duration on the staff.
65
+ * If a duration exceeds the remaining value on the bar, rests will fill the empty space.
66
+ *
67
+ * * **Duration**: `w` (whole) `h` (half) `q` (quarter) `e` (eighth)
68
+ * @returns void
69
+ * @throws {Error} If a rest string is not correct format. If an array was passed, it will still draw whatever correctly formatted rests before it.
70
+ *
71
+ * * @example
72
+ * // Draws the specified rest durations individually on the staff
73
+ * drawRest(["q", "q", "q", "q", "w"]);
74
+ *
75
+ * * @example
76
+ * // Draws the specified single rest duration on the staff
77
+ * drawRest("w");
78
+ */
79
+ drawRest(rests: string | string[]): void;
80
+ /**
81
+ * Draws a beamed note of specified duration/count on the staff.
82
+ * Will stop beam early if bar line is reached / if beat count is over max limit
83
+ * @param note - A duration string of either 'e' (eighth) or 's' (sixth).
84
+ * @param noteCount - The amount of notes in the beam
85
+ *
86
+ * @returns void
87
+ * @throws {Error} If a rest string is not correct format. If an array was passed, it will still draw whatever correctly formatted rests before it.
88
+ *
89
+ * * @example
90
+ * // Draws a 4 beamed eighth note
91
+ * drawBeamedNotes("e", 4);
92
+ *
93
+ * * @example
94
+ * // Draws a 8 beamed sixth note
95
+ * drawBeamedNotes("s", 8);
96
+ */
97
+ drawBeamedNotes(note: "e" | "s", noteCount: number): void;
98
+ /**
99
+ * Will increment the UI showing the current beat in quarters. Once exceeded, must be reset with `resetCurrentBeatUI()`
100
+ * @returns void
101
+ */
102
+ incrementCurrentBeatUI(): void;
103
+ /**
104
+ * Resets the ui showing the current beat value.
105
+ * @returns void
106
+ */
107
+ resetCurrentBeatUI(): void;
108
+ /**
109
+ * Clears staff of notes and resets internal positioning.
110
+ * @returns void
111
+ */
112
+ clearAllNotes(): void;
113
+ /**
114
+ * Removes the root svg element and cleans up arrays.
115
+ * @returns void
116
+ */
117
+ destroy(): void;
118
+ }
@@ -0,0 +1,47 @@
1
+ import { GlyphNames } from '../glyphs';
2
+ export declare const SVG_HREF = "http://www.w3.org/2000/svg";
3
+ type SVGRendererOptions = {
4
+ width: number;
5
+ height: number;
6
+ scale: number;
7
+ staffColor: string;
8
+ staffBackgroundColor: string;
9
+ useGlyphs: GlyphNames[];
10
+ };
11
+ type LayerNames = 'staff' | 'notes' | 'ui';
12
+ type DrawGlyphOptions = {
13
+ yOffset?: number;
14
+ xOffset?: number;
15
+ };
16
+ type DrawRectOptions = {
17
+ x?: number;
18
+ y?: number;
19
+ fill?: string;
20
+ };
21
+ export default class SVGRenderer {
22
+ private rootElementRef;
23
+ private svgElementRef;
24
+ private parentGroupContainer;
25
+ private musicStaffLayer;
26
+ private musicNotesLayer;
27
+ private musicUILayer;
28
+ private width;
29
+ private scale;
30
+ private totalYOffset;
31
+ private totalHeight;
32
+ constructor(rootElementCtx: HTMLElement, options: SVGRendererOptions);
33
+ private makeGlyphDefs;
34
+ createGroup(className?: string): SVGGElement;
35
+ commitElementsToDOM(elements: SVGElement[] | SVGElement, parent?: HTMLElement | SVGElement): void;
36
+ getLayerByName(name: LayerNames): SVGGElement;
37
+ addTotalRootSvgHeight(amount: number): void;
38
+ addTotalRootSvgYOffset(amount: number): void;
39
+ applySizingToRootSvg(): void;
40
+ get rootSvgElement(): SVGElement;
41
+ get parentGroupElement(): SVGElement;
42
+ drawLine(x1: number, y1: number, x2: number, y2: number, parent: SVGElement): void;
43
+ drawRect(width: number, height: number, parent: SVGElement, options?: DrawRectOptions): SVGRectElement;
44
+ drawGlyph(glyphName: GlyphNames, parent: SVGElement, options?: DrawGlyphOptions): void;
45
+ destroy(): void;
46
+ }
47
+ export {};
@@ -0,0 +1,67 @@
1
+ import { StaffTypes } from '../types';
2
+ export type ScrollingStaffOptions = {
3
+ width?: number;
4
+ scale?: number;
5
+ staffType?: StaffTypes;
6
+ spaceAbove?: number;
7
+ spaceBelow?: number;
8
+ staffColor?: string;
9
+ staffBackgroundColor?: string;
10
+ onNotesOut?: () => void;
11
+ };
12
+ export type NoteSequence = (string | string[])[];
13
+ export default class ScrollingStaff {
14
+ private svgRendererInstance;
15
+ private strategyInstance;
16
+ private noteRendererInstance;
17
+ private options;
18
+ private activeEntries;
19
+ private noteBuffer;
20
+ private notesLayer;
21
+ private noteCursorX;
22
+ /**
23
+ * Creates an instance of a ScrollingStaff, A single staff that takes in a queue of notes that can be advanced with in a 'endless' style of staff.
24
+ *
25
+ * @param rootElementCtx - The element (div) reference that will append the music staff elements to.
26
+ * @param options - Optional configuration settings. All config options are in the type ScrollingStaffOptions
27
+ */
28
+ constructor(rootElementCtx: HTMLElement, options?: ScrollingStaffOptions);
29
+ private renderFirstNoteGroups;
30
+ private renderNextNote;
31
+ /**
32
+ * Adds notes to the queue for scrolling staff. Clears any previously added notes.
33
+ * @param notes - A array of note strings or sub-arrays of strings.
34
+ * * A single string will draw a single note `C#4w`
35
+ * * A sub-array will draw a chord `["C4w", "E4w", "G4w"]`
36
+ *
37
+ * Note string format
38
+ * * **Root**: (A-G)
39
+ * * **Accidental** (Optional): `#` (sharp) `b` (flat) `n` (natural) `##` (double sharp) or `bb` (double flat).
40
+ * * **Octave**: The octave number (e.g., `4`).
41
+ * * **Duration** (Optional): `w` (whole) `h` (half) `q` (quarter) or `e` (eighth). Defaults to `w` if duration is omitted
42
+ * @param noteIndex The index of the note that will replaced by the specified note.
43
+ * @returns void
44
+ * @throws {Error} If the index provided is out of bounds, or if a note string is not correct format.
45
+ *
46
+ * * @example
47
+ * // Queues a few single notes, followed by a C chord
48
+ * queueNotes("Bb3q", "C4w", "G4q", ["C4w", "E4w", "G4w"]);
49
+ */
50
+ queueNotes(notes: NoteSequence): void;
51
+ /**
52
+ * Advances to the next note in sequence, if theres any remaining notes left.
53
+ * @returns void
54
+ * @callback onNotesOut passed in from the constructor options once notes are out.
55
+ */
56
+ advanceNotes(): void;
57
+ /**
58
+ * Clears staff of notes and resets internal positioning.
59
+ * @returns void
60
+ */
61
+ clearAllNotes(): void;
62
+ /**
63
+ * Removes the root svg element and cleans up arrays.
64
+ * @returns void
65
+ */
66
+ destroy(): void;
67
+ }
@@ -0,0 +1,19 @@
1
+ import { StaffParams } from './strategies/StrategyInterface';
2
+ import { Durations, StaffTypes } from './types';
3
+ export declare const NAMESPACE = "vs";
4
+ export declare const STAFF_LINE_COUNT = 5;
5
+ export declare const STAFF_LINE_SPACING = 10;
6
+ export declare const NOTE_LAYER_START_X = 38;
7
+ export declare const GRAND_STAFF_SPACING = 30;
8
+ export declare const ACCIDENTAL_OFFSET_X = -8;
9
+ export declare const DOUBLE_SHARP_ACCIDENTAL_OFFSET_X = -2;
10
+ export declare const DOUBLE_FLAT_ACCIDENTAL_OFFSET_X = -6;
11
+ export declare const HALF_NOTEHEAD_WIDTH = 10;
12
+ export declare const NOTEHEAD_STEM_HEIGHT = 28;
13
+ export declare const NOTE_SPACING = 28;
14
+ export declare const START_LEDGER_LINE_X = -2;
15
+ export declare const WHOLE_NOTE_LEDGER_LINE_WIDTH = 17;
16
+ export declare const HALF_NOTE_LEDGER_LINE_WIDTH = 12.5;
17
+ export declare const CHORD_MAX_CONSECUTIVE_ACCIDENTALS = 3;
18
+ export declare const staffParams: Record<StaffTypes, StaffParams>;
19
+ export declare const durationBeatValueMap: Record<Durations, number>;
@@ -0,0 +1,7 @@
1
+ export type GlyphEntry = {
2
+ path: string;
3
+ xOffset: number;
4
+ yOffset: number;
5
+ };
6
+ export type GlyphNames = "CLEF_TREBLE" | "CLEF_BASS" | "CLEF_ALTO" | "NOTE_HEAD_WHOLE" | "NOTE_HEAD_HALF" | "NOTE_HEAD_QUARTER" | "EIGHTH_NOTE" | "EIGHTH_NOTE_FLIPPED" | "REST_WHOLE" | "REST_HALF" | "REST_QUARTER" | "REST_EIGHTH" | "ACCIDENTAL_SHARP" | "ACCIDENTAL_FLAT" | "ACCIDENTAL_DOUBLE_SHARP" | "ACCIDENTAL_DOUBLE_FLAT" | "ACCIDENTAL_NATURAL" | "TIME_4" | "TIME_3";
7
+ export declare const GLPYH_ENTRIES: Record<GlyphNames, GlyphEntry>;