@musodojo/music-theory-data 20.1.3 → 20.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -9
- package/package.json +8 -3
- package/src/utils/colors.ts +57 -0
- package/src/utils/mod.ts +1 -0
package/README.md
CHANGED
|
@@ -6,15 +6,14 @@ more.**
|
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/@musodojo/music-theory-data)
|
|
8
8
|
[](https://www.npmjs.com/package/@musodojo/music-theory-data)
|
|
9
|
-
|
|
10
9
|
[](https://jsr.io/@musodojo/music-theory-data)
|
|
11
10
|
|
|
12
11
|
## Community & Support
|
|
13
12
|
|
|
14
13
|
Have a question, a suggestion, or want to report a bug? Get in touch!
|
|
15
14
|
|
|
16
|
-
- **💬 Discord Server:** Connect with other developers and music
|
|
17
|
-
|
|
15
|
+
- **💬 Discord Server:** Connect with other developers and music enthusiasts in
|
|
16
|
+
the [`#music-theory-data` channel.](https://discord.gg/3Tt4SXG5QC)
|
|
18
17
|
- **📢 Ask a Question or Share an Idea:** Use
|
|
19
18
|
[GitHub Discussions](https://github.com/conor-dowdall/music-theory-data/discussions).
|
|
20
19
|
- **🐞 Report a Bug or Flaw in the Data:** Open a
|
|
@@ -47,6 +46,7 @@ intervals, integer notations, and common names.
|
|
|
47
46
|
|
|
48
47
|
```ts
|
|
49
48
|
// src/data/note-collections/diatonic-modes.ts
|
|
49
|
+
// @ts-ignore
|
|
50
50
|
const ionian: ModalScaleCollection = {
|
|
51
51
|
category: "scale",
|
|
52
52
|
rotation: 0,
|
|
@@ -87,16 +87,18 @@ const ionian: ModalScaleCollection = {
|
|
|
87
87
|
### Practical Utility Functions
|
|
88
88
|
|
|
89
89
|
Helpers for common tasks like generating note names from a root note and a set
|
|
90
|
-
of intervals.
|
|
90
|
+
of intervals. For the full implementation details, refer to the source file.
|
|
91
91
|
|
|
92
92
|
```ts
|
|
93
|
-
// src/utils/note-names.ts
|
|
94
93
|
export function getNoteNamesFromRootAndIntervals(
|
|
94
|
+
// @ts-ignore
|
|
95
95
|
rootNote: RootNote,
|
|
96
96
|
intervals: readonly Interval[],
|
|
97
|
-
options: TransformIntervalsOptions = {}
|
|
97
|
+
options: TransformIntervalsOptions = {},
|
|
98
98
|
): NoteName[] {
|
|
99
|
-
|
|
99
|
+
// This is a simplified representation for documentation purposes.
|
|
100
|
+
// The actual implementation is in src/utils/note-names.ts
|
|
101
|
+
return [];
|
|
100
102
|
}
|
|
101
103
|
```
|
|
102
104
|
|
|
@@ -142,7 +144,7 @@ import * as music_theory_data from "jsr:@musodojo/music-theory-data";
|
|
|
142
144
|
// Get the notes of A Harmonic Minor
|
|
143
145
|
const notes1 = music_theory_data.getNoteNamesFromRootAndCollectionKey(
|
|
144
146
|
"A",
|
|
145
|
-
"harmonicMinor"
|
|
147
|
+
"harmonicMinor",
|
|
146
148
|
);
|
|
147
149
|
console.log(notes1);
|
|
148
150
|
// ["A", "B", "C", "D", "E", "F", "G♯", "A"]
|
|
@@ -150,7 +152,7 @@ console.log(notes1);
|
|
|
150
152
|
// Automatically knows whether to use flats or sharps
|
|
151
153
|
const notes2 = music_theory_data.getNoteNamesFromRootAndCollectionKey(
|
|
152
154
|
"F",
|
|
153
|
-
"ionian"
|
|
155
|
+
"ionian",
|
|
154
156
|
);
|
|
155
157
|
console.log(notes2);
|
|
156
158
|
// ["F", "G", "A", "B♭", "C", "D", "E", "F"];
|
package/package.json
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@musodojo/music-theory-data",
|
|
3
|
-
"version": "20.
|
|
4
|
-
"description": "The musician-friendly TypeScript library for
|
|
3
|
+
"version": "20.2.0",
|
|
4
|
+
"description": "The musician-friendly TypeScript library for scales, modes, chords, and arpeggios.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"music",
|
|
7
|
-
"theory"
|
|
7
|
+
"theory",
|
|
8
|
+
"enharmonic",
|
|
9
|
+
"scale",
|
|
10
|
+
"mode",
|
|
11
|
+
"chord",
|
|
12
|
+
"arpeggio"
|
|
8
13
|
],
|
|
9
14
|
"license": "CC0-1.0",
|
|
10
15
|
"author": "Conor Dowdall",
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses a hex color string and returns its RGB components.
|
|
3
|
+
* Supports 3-digit (#RGB) and 6-digit (#RRGGBB) formats.
|
|
4
|
+
* @param hex The hex color string.
|
|
5
|
+
* @returns An array [r, g, b] or null if the format is invalid.
|
|
6
|
+
*/
|
|
7
|
+
export function parseHexColor(hex: string): [number, number, number] | null {
|
|
8
|
+
const hexRegex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;
|
|
9
|
+
const shorthandHexRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
|
10
|
+
|
|
11
|
+
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
|
|
12
|
+
const fullHex = hex.replace(
|
|
13
|
+
shorthandHexRegex,
|
|
14
|
+
(_, r, g, b) => r + r + g + g + b + b,
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
const result = hexRegex.exec(fullHex);
|
|
18
|
+
return result
|
|
19
|
+
? [
|
|
20
|
+
parseInt(result[1], 16),
|
|
21
|
+
parseInt(result[2], 16),
|
|
22
|
+
parseInt(result[3], 16),
|
|
23
|
+
]
|
|
24
|
+
: null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Calculates whether black or white text has a better contrast ratio against a given background color.
|
|
29
|
+
* @param {string} color - The background color in hex format, e.g. "#E21C48"
|
|
30
|
+
* @returns {'black' | 'white'} - The color that provides better contrast.
|
|
31
|
+
*/
|
|
32
|
+
export function getContrastColor(color: string): "black" | "white" {
|
|
33
|
+
// For now, we only support hex colors as that's what's in the library.
|
|
34
|
+
// This can be expanded to support rgb(), hsl(), and color keywords if needed.
|
|
35
|
+
const rgb = parseHexColor(color);
|
|
36
|
+
if (!rgb) {
|
|
37
|
+
return "black"; // Default to black if color parsing fails
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const [r, g, b] = rgb;
|
|
41
|
+
|
|
42
|
+
// Formula for relative luminance (from WCAG)
|
|
43
|
+
// https://www.w3.org/TR/WCAG20/#relativeluminancedef
|
|
44
|
+
const getLuminance = (c: number) => {
|
|
45
|
+
const sRGB = c / 255;
|
|
46
|
+
return sRGB <= 0.03928
|
|
47
|
+
? sRGB / 12.92
|
|
48
|
+
: Math.pow((sRGB + 0.055) / 1.055, 2.4);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const luminance = 0.2126 * getLuminance(r) +
|
|
52
|
+
0.7152 * getLuminance(g) +
|
|
53
|
+
0.0722 * getLuminance(b);
|
|
54
|
+
|
|
55
|
+
// Use a threshold of 0.179 as recommended by WCAG for contrast
|
|
56
|
+
return luminance > 0.179 ? "black" : "white";
|
|
57
|
+
}
|
package/src/utils/mod.ts
CHANGED