@medyll/idae-cadenzia 0.78.0 → 0.80.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,252 +1,252 @@
1
- <!-- components/ChordTable.svelte -->
2
- <script lang="ts">
3
- import {
4
- qualities,
5
- armorOptions,
6
- modes,
7
- rootNotes,
8
- modifiers
9
- } from '$lib/constants/constants.js';
10
- import { getScaleNotes, isChordInScale } from '$lib/functions/rules.js';
11
-
12
- import type { ChordEntry } from '$lib/types/types.js';
13
- import { chordEntries, updateCadences, toggleModifier, handleChordChange } from '../functions/functions.svelte.js';
14
-
15
- function addChordEntry() {
16
- chordEntries.push({
17
- chord: { root: 'C', quality: qualities.mode[0], modifier: undefined, duration: '1' },
18
- timeSignature: chordEntries.length === 0 ? { numerator: 4, denominator: 4 } : undefined,
19
- armor: '',
20
- mode: undefined,
21
- measureInfo: { start: 1, end: 1, beatStart: 0 }
22
- });
23
- updateCadences();
24
- }
25
-
26
- function removeChordEntry(index: number) {
27
- chordEntries.splice(index, 1);
28
- updateCadences();
29
- }
30
-
31
-
32
-
33
- function toggleTimeSignature(index: number) {
34
- if (chordEntries[index].timeSignature) {
35
- chordEntries[index].timeSignature = undefined;
36
- } else {
37
- chordEntries[index].timeSignature = { numerator: 4, denominator: 4 };
38
- }
39
- }
40
-
41
- function isNoteInScale(note: string, entry: ChordEntry): boolean {
42
- const scaleNotes = getScaleNotes(entry.armor);
43
- return scaleNotes.includes(note);
44
- }
45
-
46
- function isChordValid(entry: ChordEntry): boolean {
47
- return isChordInScale(entry);
48
- }
49
- </script>
50
-
51
- <table>
52
- <thead>
53
- <tr>
54
- <th>Measure</th>
55
- <th>Time Signature</th>
56
- <th>Armor</th>
57
- <th>Root</th>
58
- <th>Quality</th>
59
- <th>Modifier</th>
60
- <th>Duration</th>
61
- <th>Action</th>
62
- </tr>
63
- </thead>
64
- <tbody>
65
- {#each chordEntries as entry, i}
66
- <tr>
67
- <td>
68
- {#if entry.measureInfo.start === entry.measureInfo.end}
69
- {entry.measureInfo.start}
70
- {:else}
71
- {entry.measureInfo.start} - {entry.measureInfo.end}
72
- {/if}
73
- </td>
74
- <td class="timeSignature">
75
- {#if entry.timeSignature}
76
- <input
77
- type="number"
78
- bind:value={entry.timeSignature.numerator}
79
- min="1"
80
- max="32"
81
- onchange={() => handleChordChange(i, { timeSignature: entry.timeSignature })}
82
- />
83
- /
84
- <input
85
- type="number"
86
- bind:value={entry.timeSignature.denominator}
87
- min="1"
88
- max="32"
89
- onchange={() => handleChordChange(i, { timeSignature: entry.timeSignature })}
90
- />
91
- {:else}
92
- <button onclick={() => toggleTimeSignature(i)}>Add Time Signature</button>
93
- {/if}
94
- </td>
95
- <td>
96
- <div>
97
- <label for="armor-{i}">Armor:</label>
98
- <select
99
- id="armor-{i}"
100
- bind:value={entry.armor}
101
- onchange={() => handleChordChange(i, { armor: entry.armor })}
102
- >
103
- {#each armorOptions as armor}
104
- <option value={armor.name}>
105
- {armor.name}
106
- {armor.value ? `(${armor.value})` : ''}
107
- </option>
108
- {/each}
109
- </select>
110
- </div>
111
- <div>
112
- <label for="mode-{i}">Mode:</label>
113
- <select
114
- id="mode-{i}"
115
- bind:value={entry.mode}
116
- onchange={() => handleChordChange(i, { mode: entry.mode })}
117
- >
118
- <option value={undefined}>Select mode</option>
119
- {#each modes as mode}
120
- <option value={mode}>{mode}</option>
121
- {/each}
122
- </select>
123
- </div>
124
- </td>
125
- <td>
126
- <select
127
- bind:value={entry.chord.root}
128
- onchange={() => handleChordChange(i, { chord: { ...entry.chord } })}
129
- >
130
- {#each rootNotes as note}
131
- <option
132
- value={note}
133
- class:not-in-scale={!isChordValid({
134
- ...entry,
135
- chord: { ...entry.chord, root: note }
136
- })}
137
- >
138
- {note}
139
- </option>
140
- {/each}
141
- </select>
142
- </td>
143
- <td>
144
- {#each Object.entries(qualities) as [group, qualityOptions]}
145
- <div>
146
- {#each qualityOptions as quality}
147
- <label
148
- class:not-in-scale={!isChordValid({
149
- ...entry,
150
- chord: { ...entry.chord, quality }
151
- })}
152
- >
153
- <input
154
- type="radio"
155
- name={`quality-${group}-${i}`}
156
- value={quality}
157
- checked={entry.chord[group] === quality}
158
- onchange={() => {
159
- const updatedChord = { ...entry.chord, [group]: quality, quality };
160
- handleChordChange(i, { chord: updatedChord });
161
- }}
162
- />
163
- {quality}
164
- </label>
165
- {/each}
166
- </div>
167
- <hr />
168
- {/each}
169
- </td>
170
- <td>
171
- {#each modifiers as modifier}
172
- <label
173
- class:not-in-scale={!isChordValid({ ...entry, chord: { ...entry.chord, modifier } })}
174
- >
175
- <input
176
- type="radio"
177
- name={`modifier-${i}`}
178
- value={modifier}
179
- checked={entry.chord.modifier === modifier}
180
- onchange={() => toggleModifier(i, modifier)}
181
- />
182
- {modifier}
183
- </label>
184
- {/each}
185
- </td>
186
- <td class="duration">
187
- <input
188
- type="text"
189
- bind:value={entry.chord.duration}
190
- onchange={() => handleChordChange(i, { chord: { ...entry.chord } })}
191
- placeholder="e.g., 1, 1/2, 3/4"
192
- />
193
- </td>
194
- <td>
195
- <button onclick={() => removeChordEntry(i)}>Remove</button>
196
- </td>
197
- </tr>
198
- {/each}
199
- </tbody>
200
- </table>
201
-
202
- <button onclick={addChordEntry}>Add Chord</button>
203
-
204
- <style>
205
- table {
206
- width: 100%;
207
- border-collapse: collapse;
208
- margin-bottom: 1em;
209
- }
210
- th,
211
- td {
212
- border: 1px solid #ddd;
213
- padding: 8px;
214
- text-align: center;
215
- }
216
- td.timeSignature {
217
- & input[type='number'] {
218
- width: 40px;
219
- text-align: center;
220
- }
221
-
222
- & button {
223
- padding: 5px 10px;
224
- background-color: #f0f0f0;
225
- border: 1px solid #ccc;
226
- border-radius: 3px;
227
- }
228
- }
229
-
230
- td.duration {
231
- & input[type='text'] {
232
- width: 60px;
233
- text-align: center;
234
- }
235
- }
236
- th {
237
- background-color: #f2f2f2;
238
- }
239
- select,
240
- input[type='text'],
241
- input[type='number'] {
242
- width: 100%;
243
- }
244
-
245
- option.not-in-scale {
246
- color: red;
247
- }
248
-
249
- label.not-in-scale {
250
- color: red;
251
- }
252
- </style>
1
+ <!-- components/ChordTable.svelte -->
2
+ <script lang="ts">
3
+ import {
4
+ qualities,
5
+ armorOptions,
6
+ modes,
7
+ rootNotes,
8
+ modifiers
9
+ } from '$lib/constants/constants.js';
10
+ import { getScaleNotes, isChordInScale } from '$lib/functions/rules.js';
11
+
12
+ import type { ChordEntry } from '$lib/types/types.js';
13
+ import { chordEntries, updateCadences, toggleModifier, handleChordChange } from '../functions/functions.svelte.js';
14
+
15
+ function addChordEntry() {
16
+ chordEntries.push({
17
+ chord: { root: 'C', quality: qualities.mode[0], modifier: undefined, duration: '1' },
18
+ timeSignature: chordEntries.length === 0 ? { numerator: 4, denominator: 4 } : undefined,
19
+ armor: '',
20
+ mode: undefined,
21
+ measureInfo: { start: 1, end: 1, beatStart: 0 }
22
+ });
23
+ updateCadences();
24
+ }
25
+
26
+ function removeChordEntry(index: number) {
27
+ chordEntries.splice(index, 1);
28
+ updateCadences();
29
+ }
30
+
31
+
32
+
33
+ function toggleTimeSignature(index: number) {
34
+ if (chordEntries[index].timeSignature) {
35
+ chordEntries[index].timeSignature = undefined;
36
+ } else {
37
+ chordEntries[index].timeSignature = { numerator: 4, denominator: 4 };
38
+ }
39
+ }
40
+
41
+ function isNoteInScale(note: string, entry: ChordEntry): boolean {
42
+ const scaleNotes = getScaleNotes(entry.armor);
43
+ return scaleNotes.includes(note);
44
+ }
45
+
46
+ function isChordValid(entry: ChordEntry): boolean {
47
+ return isChordInScale(entry);
48
+ }
49
+ </script>
50
+
51
+ <table>
52
+ <thead>
53
+ <tr>
54
+ <th>Measure</th>
55
+ <th>Time Signature</th>
56
+ <th>Armor</th>
57
+ <th>Root</th>
58
+ <th>Quality</th>
59
+ <th>Modifier</th>
60
+ <th>Duration</th>
61
+ <th>Action</th>
62
+ </tr>
63
+ </thead>
64
+ <tbody>
65
+ {#each chordEntries as entry, i}
66
+ <tr>
67
+ <td>
68
+ {#if entry.measureInfo.start === entry.measureInfo.end}
69
+ {entry.measureInfo.start}
70
+ {:else}
71
+ {entry.measureInfo.start} - {entry.measureInfo.end}
72
+ {/if}
73
+ </td>
74
+ <td class="timeSignature">
75
+ {#if entry.timeSignature}
76
+ <input
77
+ type="number"
78
+ bind:value={entry.timeSignature.numerator}
79
+ min="1"
80
+ max="32"
81
+ onchange={() => handleChordChange(i, { timeSignature: entry.timeSignature })}
82
+ />
83
+ /
84
+ <input
85
+ type="number"
86
+ bind:value={entry.timeSignature.denominator}
87
+ min="1"
88
+ max="32"
89
+ onchange={() => handleChordChange(i, { timeSignature: entry.timeSignature })}
90
+ />
91
+ {:else}
92
+ <button onclick={() => toggleTimeSignature(i)}>Add Time Signature</button>
93
+ {/if}
94
+ </td>
95
+ <td>
96
+ <div>
97
+ <label for="armor-{i}">Armor:</label>
98
+ <select
99
+ id="armor-{i}"
100
+ bind:value={entry.armor}
101
+ onchange={() => handleChordChange(i, { armor: entry.armor })}
102
+ >
103
+ {#each armorOptions as armor}
104
+ <option value={armor.name}>
105
+ {armor.name}
106
+ {armor.value ? `(${armor.value})` : ''}
107
+ </option>
108
+ {/each}
109
+ </select>
110
+ </div>
111
+ <div>
112
+ <label for="mode-{i}">Mode:</label>
113
+ <select
114
+ id="mode-{i}"
115
+ bind:value={entry.mode}
116
+ onchange={() => handleChordChange(i, { mode: entry.mode })}
117
+ >
118
+ <option value={undefined}>Select mode</option>
119
+ {#each modes as mode}
120
+ <option value={mode}>{mode}</option>
121
+ {/each}
122
+ </select>
123
+ </div>
124
+ </td>
125
+ <td>
126
+ <select
127
+ bind:value={entry.chord.root}
128
+ onchange={() => handleChordChange(i, { chord: { ...entry.chord } })}
129
+ >
130
+ {#each rootNotes as note}
131
+ <option
132
+ value={note}
133
+ class:not-in-scale={!isChordValid({
134
+ ...entry,
135
+ chord: { ...entry.chord, root: note }
136
+ })}
137
+ >
138
+ {note}
139
+ </option>
140
+ {/each}
141
+ </select>
142
+ </td>
143
+ <td>
144
+ {#each Object.entries(qualities) as [group, qualityOptions]}
145
+ <div>
146
+ {#each qualityOptions as quality}
147
+ <label
148
+ class:not-in-scale={!isChordValid({
149
+ ...entry,
150
+ chord: { ...entry.chord, quality }
151
+ })}
152
+ >
153
+ <input
154
+ type="radio"
155
+ name={`quality-${group}-${i}`}
156
+ value={quality}
157
+ checked={entry.chord[group] === quality}
158
+ onchange={() => {
159
+ const updatedChord = { ...entry.chord, [group]: quality, quality };
160
+ handleChordChange(i, { chord: updatedChord });
161
+ }}
162
+ />
163
+ {quality}
164
+ </label>
165
+ {/each}
166
+ </div>
167
+ <hr />
168
+ {/each}
169
+ </td>
170
+ <td>
171
+ {#each modifiers as modifier}
172
+ <label
173
+ class:not-in-scale={!isChordValid({ ...entry, chord: { ...entry.chord, modifier } })}
174
+ >
175
+ <input
176
+ type="radio"
177
+ name={`modifier-${i}`}
178
+ value={modifier}
179
+ checked={entry.chord.modifier === modifier}
180
+ onchange={() => toggleModifier(i, modifier)}
181
+ />
182
+ {modifier}
183
+ </label>
184
+ {/each}
185
+ </td>
186
+ <td class="duration">
187
+ <input
188
+ type="text"
189
+ bind:value={entry.chord.duration}
190
+ onchange={() => handleChordChange(i, { chord: { ...entry.chord } })}
191
+ placeholder="e.g., 1, 1/2, 3/4"
192
+ />
193
+ </td>
194
+ <td>
195
+ <button onclick={() => removeChordEntry(i)}>Remove</button>
196
+ </td>
197
+ </tr>
198
+ {/each}
199
+ </tbody>
200
+ </table>
201
+
202
+ <button onclick={addChordEntry}>Add Chord</button>
203
+
204
+ <style>
205
+ table {
206
+ width: 100%;
207
+ border-collapse: collapse;
208
+ margin-bottom: 1em;
209
+ }
210
+ th,
211
+ td {
212
+ border: 1px solid #ddd;
213
+ padding: 8px;
214
+ text-align: center;
215
+ }
216
+ td.timeSignature {
217
+ & input[type='number'] {
218
+ width: 40px;
219
+ text-align: center;
220
+ }
221
+
222
+ & button {
223
+ padding: 5px 10px;
224
+ background-color: #f0f0f0;
225
+ border: 1px solid #ccc;
226
+ border-radius: 3px;
227
+ }
228
+ }
229
+
230
+ td.duration {
231
+ & input[type='text'] {
232
+ width: 60px;
233
+ text-align: center;
234
+ }
235
+ }
236
+ th {
237
+ background-color: #f2f2f2;
238
+ }
239
+ select,
240
+ input[type='text'],
241
+ input[type='number'] {
242
+ width: 100%;
243
+ }
244
+
245
+ option.not-in-scale {
246
+ color: red;
247
+ }
248
+
249
+ label.not-in-scale {
250
+ color: red;
251
+ }
252
+ </style>
@@ -1,82 +1,82 @@
1
- <!-- components/ChordVisualization.svelte -->
2
- <script lang="ts">
3
- import { chordEntries, getArmorInfo } from '$lib/functions/functions.svelte';
4
- import type { ChordEntry } from '$lib/types/types';
5
-
6
- function getChordName(entry: ChordEntry) {
7
- const { chord } = entry;
8
- let name = chord.root;
9
-
10
- name += chord.modifier ?? '';
11
- name += chord.augDim ?? '';
12
- name += chord.sus ?? '';
13
- name += chord.sept ?? '';
14
-
15
- return name;
16
- }
17
-
18
- function getDurationValue(duration: string): number {
19
- if (duration.includes('/')) {
20
- const [numerator, denominator] = duration.split('/').map(Number);
21
- return numerator / denominator;
22
- }
23
- return Number(duration);
24
- }
25
- </script>
26
-
27
- <div class="visualization">
28
- <h3>Chord Visualization</h3>
29
- {#if chordEntries.length === 0}
30
- <p>No chords to visualize.</p>
31
- {:else}
32
- <div class="chord-sequence">
33
- {#each chordEntries as entry, i}
34
- {#if entry.timeSignature || entry.armor || entry.mode}
35
- <div class="signature">
36
- {#if entry.timeSignature}
37
- - Signature: {entry.timeSignature.numerator}/{entry.timeSignature.denominator}
38
- {/if}
39
- {#if entry.armor}
40
- - Armure: {getArmorInfo(entry.armor)}
41
- {/if}
42
- {#if entry.mode}
43
- - Mode: {entry.mode}
44
- {/if}
45
- </div>
46
- {/if}
47
- <div class="chord" style="--baseTime:{getDurationValue(entry.chord.duration)}">
48
- <span>{getChordName(entry)}</span>
49
- <span>{entry.chord.duration}</span>
50
- </div>
51
- {/each}
52
- </div>
53
- {/if}
54
- </div>
55
-
56
- <style>
57
- .visualization {
58
- margin-top: 20px;
59
- padding: 10px;
60
- background-color: #e0e0e0;
61
- }
62
- .signature {
63
- flex-basis: 100%;
64
- width: 100%;
65
- }
66
- .chord-sequence {
67
- display: flex;
68
- flex-wrap: wrap;
69
- gap: 10px; /* Space between chords */
70
- }
71
- .chord {
72
- padding: 10px;
73
- background-color: #fff;
74
- border: 1px solid #ccc;
75
- border-radius: 5px;
76
- box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
77
- text-align: center;
78
- width: calc(200px * var(--baseTime, 1));
79
- min-width: 30px; /* Ensure a minimum width for very short durations */
80
- max-width: 100%; /* Prevent oversized chords */
81
- }
82
- </style>
1
+ <!-- components/ChordVisualization.svelte -->
2
+ <script lang="ts">
3
+ import { chordEntries, getArmorInfo } from '$lib/functions/functions.svelte';
4
+ import type { ChordEntry } from '$lib/types/types';
5
+
6
+ function getChordName(entry: ChordEntry) {
7
+ const { chord } = entry;
8
+ let name = chord.root;
9
+
10
+ name += chord.modifier ?? '';
11
+ name += chord.augDim ?? '';
12
+ name += chord.sus ?? '';
13
+ name += chord.sept ?? '';
14
+
15
+ return name;
16
+ }
17
+
18
+ function getDurationValue(duration: string): number {
19
+ if (duration.includes('/')) {
20
+ const [numerator, denominator] = duration.split('/').map(Number);
21
+ return numerator / denominator;
22
+ }
23
+ return Number(duration);
24
+ }
25
+ </script>
26
+
27
+ <div class="visualization">
28
+ <h3>Chord Visualization</h3>
29
+ {#if chordEntries.length === 0}
30
+ <p>No chords to visualize.</p>
31
+ {:else}
32
+ <div class="chord-sequence">
33
+ {#each chordEntries as entry, i}
34
+ {#if entry.timeSignature || entry.armor || entry.mode}
35
+ <div class="signature">
36
+ {#if entry.timeSignature}
37
+ - Signature: {entry.timeSignature.numerator}/{entry.timeSignature.denominator}
38
+ {/if}
39
+ {#if entry.armor}
40
+ - Armure: {getArmorInfo(entry.armor)}
41
+ {/if}
42
+ {#if entry.mode}
43
+ - Mode: {entry.mode}
44
+ {/if}
45
+ </div>
46
+ {/if}
47
+ <div class="chord" style="--baseTime:{getDurationValue(entry.chord.duration)}">
48
+ <span>{getChordName(entry)}</span>
49
+ <span>{entry.chord.duration}</span>
50
+ </div>
51
+ {/each}
52
+ </div>
53
+ {/if}
54
+ </div>
55
+
56
+ <style>
57
+ .visualization {
58
+ margin-top: 20px;
59
+ padding: 10px;
60
+ background-color: #e0e0e0;
61
+ }
62
+ .signature {
63
+ flex-basis: 100%;
64
+ width: 100%;
65
+ }
66
+ .chord-sequence {
67
+ display: flex;
68
+ flex-wrap: wrap;
69
+ gap: 10px; /* Space between chords */
70
+ }
71
+ .chord {
72
+ padding: 10px;
73
+ background-color: #fff;
74
+ border: 1px solid #ccc;
75
+ border-radius: 5px;
76
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
77
+ text-align: center;
78
+ width: calc(200px * var(--baseTime, 1));
79
+ min-width: 30px; /* Ensure a minimum width for very short durations */
80
+ max-width: 100%; /* Prevent oversized chords */
81
+ }
82
+ </style>