@parent-tobias/chord-component 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.
@@ -0,0 +1,119 @@
1
+ import { css as p, LitElement as c, html as m } from "lit";
2
+ import { customElement as l } from "./node_modules/@lit/reactive-element/decorators/custom-element.js";
3
+ import { property as d } from "./node_modules/@lit/reactive-element/decorators/property.js";
4
+ import { state as u } from "./node_modules/@lit/reactive-element/decorators/state.js";
5
+ import "./chord-diagram.js";
6
+ var f = Object.defineProperty, g = Object.getOwnPropertyDescriptor, o = (t, e, n, i) => {
7
+ for (var r = i > 1 ? void 0 : i ? g(e, n) : e, a = t.length - 1, h; a >= 0; a--)
8
+ (h = t[a]) && (r = (i ? h(e, n, r) : h(r)) || r);
9
+ return i && r && f(e, n, r), r;
10
+ };
11
+ let s = class extends c {
12
+ constructor() {
13
+ super(...arguments), this.instrument = "Standard Ukulele", this.chords = "[]", this.numChords = 0;
14
+ }
15
+ /**
16
+ * Parsed chord names from the chords property
17
+ */
18
+ get parsedChords() {
19
+ try {
20
+ return Array.isArray(this.chords) ? this.chords : typeof this.chords == "string" ? JSON.parse(this.chords) : [];
21
+ } catch {
22
+ return [];
23
+ }
24
+ }
25
+ updated(t) {
26
+ t.has("chords") && (this.numChords = this.parsedChords.length);
27
+ }
28
+ render() {
29
+ const t = this.parsedChords;
30
+ return t.length === 0 ? m`
31
+ <header>
32
+ <h3>${this.instrument}</h3>
33
+ </header>
34
+ <div class='empty-state'>
35
+ No chords to display
36
+ </div>
37
+ ` : m`
38
+ <header>
39
+ <h3>${this.instrument} (${this.numChords} chord${this.numChords !== 1 ? "s" : ""})</h3>
40
+ </header>
41
+ <div class='list'>
42
+ ${t.map(
43
+ (e) => m`<chord-diagram chord=${e} instrument='${this.instrument}'></chord-diagram>`
44
+ )}
45
+ </div>
46
+ `;
47
+ }
48
+ };
49
+ s.styles = p`
50
+ :host {
51
+ display: block;
52
+ width: 100%;
53
+ height: fit-content;
54
+ container-type: inline-size;
55
+ }
56
+
57
+ header {
58
+ margin-bottom: 0.5rem;
59
+ }
60
+
61
+ header h3 {
62
+ margin: 0;
63
+ font-size: 1rem;
64
+ color: #f8f8f8;
65
+ font-weight: 600;
66
+ }
67
+
68
+ .list {
69
+ display: grid;
70
+ grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
71
+ gap: 0.5rem;
72
+ align-items: start;
73
+ }
74
+
75
+ .empty-state {
76
+ color: #a0aec0;
77
+ font-size: 0.9rem;
78
+ text-align: center;
79
+ padding: 1rem;
80
+ font-style: italic;
81
+ }
82
+
83
+ /* Responsive adjustments for different container widths */
84
+ @container (max-width: 400px) {
85
+ .list {
86
+ grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
87
+ gap: 0.3rem;
88
+ }
89
+ }
90
+
91
+ @container (min-width: 600px) {
92
+ .list {
93
+ grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
94
+ }
95
+ }
96
+
97
+ @container (min-width: 800px) {
98
+ .list {
99
+ grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
100
+ }
101
+ }
102
+ `;
103
+ o([
104
+ d({
105
+ type: String
106
+ })
107
+ ], s.prototype, "instrument", 2);
108
+ o([
109
+ d()
110
+ ], s.prototype, "chords", 2);
111
+ o([
112
+ u()
113
+ ], s.prototype, "numChords", 2);
114
+ s = o([
115
+ l("chord-list")
116
+ ], s);
117
+ export {
118
+ s as ChordList
119
+ };
@@ -0,0 +1,322 @@
1
+ const r = {
2
+ "Standard Ukulele": {
3
+ Cm: {
4
+ barres: [],
5
+ fingers: [
6
+ [3, 3],
7
+ [2, 3],
8
+ [1, 3]
9
+ ]
10
+ },
11
+ Cm7: {
12
+ barres: [{
13
+ fromString: 4,
14
+ toString: 1,
15
+ fret: 3,
16
+ text: "1"
17
+ }],
18
+ fingers: []
19
+ },
20
+ Cdim: {
21
+ barres: [],
22
+ fingers: [
23
+ [4, 2],
24
+ [3, 3],
25
+ [2, 2],
26
+ [1, 3]
27
+ ]
28
+ },
29
+ C: {
30
+ barres: [],
31
+ fingers: [
32
+ [4, 0],
33
+ [3, 0],
34
+ [2, 0],
35
+ [1, 3]
36
+ ]
37
+ },
38
+ C7: {
39
+ barres: [],
40
+ fingers: [
41
+ [4, 0],
42
+ [3, 0],
43
+ [2, 0],
44
+ [1, 1]
45
+ ]
46
+ },
47
+ Cmaj7: {
48
+ barres: [],
49
+ fingers: [
50
+ [4, 0],
51
+ [3, 0],
52
+ [2, 0],
53
+ [1, 2]
54
+ ]
55
+ },
56
+ Dm: {
57
+ barres: [],
58
+ fingers: [
59
+ [4, 2],
60
+ [3, 2],
61
+ [2, 1],
62
+ [1, 0]
63
+ ]
64
+ },
65
+ Dm7: {
66
+ barres: [],
67
+ fingers: [
68
+ [4, 2],
69
+ [3, 2],
70
+ [2, 1],
71
+ [1, 3]
72
+ ]
73
+ },
74
+ D: {
75
+ barres: [],
76
+ fingers: [
77
+ [4, 2],
78
+ [3, 2],
79
+ [2, 2],
80
+ [1, 0]
81
+ ]
82
+ },
83
+ D7: {
84
+ barres: [],
85
+ fingers: [
86
+ [4, 2],
87
+ [3, 2],
88
+ [2, 2],
89
+ [1, 3]
90
+ ]
91
+ },
92
+ Em: {
93
+ barres: [],
94
+ fingers: [
95
+ [4, 0],
96
+ [3, 4],
97
+ [2, 3],
98
+ [1, 2]
99
+ ]
100
+ },
101
+ E: {
102
+ barres: [],
103
+ fingers: [
104
+ [4, 4],
105
+ [3, 4],
106
+ [2, 4],
107
+ [1, 2]
108
+ ]
109
+ },
110
+ E7: {
111
+ barres: [],
112
+ fingers: [
113
+ [4, 2],
114
+ [3, 4],
115
+ [2, 4],
116
+ [1, 2]
117
+ ]
118
+ },
119
+ F: {
120
+ barres: [],
121
+ fingers: [
122
+ [4, 2],
123
+ [3, 0],
124
+ [2, 1],
125
+ [1, 0]
126
+ ]
127
+ },
128
+ F7: {
129
+ barres: [],
130
+ fingers: [
131
+ [4, 2],
132
+ [3, 3],
133
+ [2, 1],
134
+ [1, 3]
135
+ ]
136
+ },
137
+ Fm: {
138
+ barres: [],
139
+ fingers: [
140
+ [4, 1],
141
+ [3, 0],
142
+ [2, 1],
143
+ [1, 3]
144
+ ]
145
+ },
146
+ G: {
147
+ barres: [],
148
+ fingers: [
149
+ [4, 0],
150
+ [3, 2],
151
+ [2, 3],
152
+ [1, 2]
153
+ ]
154
+ },
155
+ G7: {
156
+ barres: [],
157
+ fingers: [
158
+ [4, 0],
159
+ [3, 2],
160
+ [2, 1],
161
+ [1, 2]
162
+ ]
163
+ },
164
+ Gm: {
165
+ barres: [],
166
+ fingers: [
167
+ [4, 0],
168
+ [3, 2],
169
+ [2, 3],
170
+ [1, 1]
171
+ ]
172
+ },
173
+ Am: {
174
+ barres: [],
175
+ fingers: [
176
+ [4, 2],
177
+ [3, 0],
178
+ [2, 0],
179
+ [1, 0]
180
+ ]
181
+ },
182
+ A: {
183
+ barres: [],
184
+ fingers: [
185
+ [4, 2],
186
+ [3, 1],
187
+ [2, 0],
188
+ [1, 0]
189
+ ]
190
+ },
191
+ A7: {
192
+ barres: [],
193
+ fingers: [
194
+ [4, 0],
195
+ [3, 1],
196
+ [2, 0],
197
+ [1, 0]
198
+ ]
199
+ },
200
+ Bm: {
201
+ barres: [],
202
+ fingers: [
203
+ [4, 4],
204
+ [3, 2],
205
+ [2, 2],
206
+ [1, 2]
207
+ ]
208
+ },
209
+ B: {
210
+ barres: [],
211
+ fingers: [
212
+ [4, 4],
213
+ [3, 3],
214
+ [2, 2],
215
+ [1, 2]
216
+ ]
217
+ },
218
+ B7: {
219
+ barres: [],
220
+ fingers: [
221
+ [4, 2],
222
+ [3, 3],
223
+ [2, 2],
224
+ [1, 2]
225
+ ]
226
+ }
227
+ },
228
+ "Standard Guitar": {
229
+ C: {
230
+ barres: [],
231
+ fingers: [
232
+ [5, 3],
233
+ [4, 2],
234
+ [2, 1]
235
+ ]
236
+ },
237
+ Cm: {
238
+ barres: [{
239
+ fromString: 5,
240
+ toString: 1,
241
+ fret: 3,
242
+ text: "1"
243
+ }],
244
+ fingers: [
245
+ [4, 5],
246
+ [3, 5],
247
+ [2, 4]
248
+ ]
249
+ },
250
+ D: {
251
+ barres: [],
252
+ fingers: [
253
+ [4, 2],
254
+ [3, 3],
255
+ [1, 2]
256
+ ]
257
+ },
258
+ Dm: {
259
+ barres: [],
260
+ fingers: [
261
+ [4, 2],
262
+ [3, 3],
263
+ [1, 1]
264
+ ]
265
+ },
266
+ E: {
267
+ barres: [],
268
+ fingers: [
269
+ [5, 2],
270
+ [4, 2],
271
+ [3, 1]
272
+ ]
273
+ },
274
+ Em: {
275
+ barres: [],
276
+ fingers: [
277
+ [5, 2],
278
+ [4, 2]
279
+ ]
280
+ },
281
+ F: {
282
+ barres: [{
283
+ fromString: 6,
284
+ toString: 1,
285
+ fret: 1,
286
+ text: "1"
287
+ }],
288
+ fingers: [
289
+ [5, 3],
290
+ [4, 3],
291
+ [3, 2]
292
+ ]
293
+ },
294
+ G: {
295
+ barres: [],
296
+ fingers: [
297
+ [6, 3],
298
+ [1, 3],
299
+ [5, 2]
300
+ ]
301
+ },
302
+ A: {
303
+ barres: [],
304
+ fingers: [
305
+ [4, 2],
306
+ [3, 2],
307
+ [2, 2]
308
+ ]
309
+ },
310
+ Am: {
311
+ barres: [],
312
+ fingers: [
313
+ [4, 2],
314
+ [3, 2],
315
+ [2, 1]
316
+ ]
317
+ }
318
+ }
319
+ };
320
+ export {
321
+ r as systemDefaultChords
322
+ };
package/dist/index.js ADDED
@@ -0,0 +1,26 @@
1
+ import { ChordDiagram as e } from "./chord-diagram.js";
2
+ import { ChordList as t } from "./chord-list.js";
3
+ import { ChordEditor as m } from "./chord-editor.js";
4
+ import { chordOnInstrument as c, chordToNotes as h, chords as f, chordsPerScale as n, findBase as i, instruments as p, keys as x, notes as C, parseChords as l, scaleTones as D, scales as u } from "./music-utils.js";
5
+ import { systemDefaultChords as v } from "./default-chords.js";
6
+ import { chordDataService as B } from "./chord-data-service.js";
7
+ import { indexedDBService as g } from "./indexed-db-service.js";
8
+ export {
9
+ e as ChordDiagram,
10
+ m as ChordEditor,
11
+ t as ChordList,
12
+ B as chordDataService,
13
+ c as chordOnInstrument,
14
+ h as chordToNotes,
15
+ f as chords,
16
+ n as chordsPerScale,
17
+ i as findBase,
18
+ g as indexedDBService,
19
+ p as instruments,
20
+ x as keys,
21
+ C as notes,
22
+ l as parseChords,
23
+ D as scaleTones,
24
+ u as scales,
25
+ v as systemDefaultChords
26
+ };
@@ -0,0 +1,228 @@
1
+ const b = "ChordComponentsDB";
2
+ const d = "chordData", c = "userChords";
3
+ class h {
4
+ constructor() {
5
+ this.dbPromise = null;
6
+ }
7
+ /**
8
+ * Initialize and open the database
9
+ */
10
+ async openDB() {
11
+ return this.dbPromise ? this.dbPromise : (this.dbPromise = new Promise((e, o) => {
12
+ const r = indexedDB.open(b, 2);
13
+ r.onerror = () => {
14
+ o(new Error(`Failed to open IndexedDB: ${r.error}`));
15
+ }, r.onsuccess = () => {
16
+ e(r.result);
17
+ }, r.onupgradeneeded = (n) => {
18
+ const s = n.target.result;
19
+ if (s.objectStoreNames.contains(d) || s.createObjectStore(d, { keyPath: "instrument" }).createIndex("timestamp", "timestamp", { unique: !1 }), !s.objectStoreNames.contains(c)) {
20
+ const t = s.createObjectStore(c, { keyPath: "key" });
21
+ t.createIndex("instrument", "instrument", { unique: !1 }), t.createIndex("timestamp", "timestamp", { unique: !1 });
22
+ }
23
+ };
24
+ }), this.dbPromise);
25
+ }
26
+ /**
27
+ * Get chord data for a specific instrument from IndexedDB
28
+ */
29
+ async getChordData(e) {
30
+ try {
31
+ const o = await this.openDB();
32
+ return new Promise((r, n) => {
33
+ const i = o.transaction([d], "readonly").objectStore(d).get(e);
34
+ i.onsuccess = () => {
35
+ r(i.result || null);
36
+ }, i.onerror = () => {
37
+ n(new Error(`Failed to get chord data: ${i.error}`));
38
+ };
39
+ });
40
+ } catch (o) {
41
+ return console.error("IndexedDB error:", o), null;
42
+ }
43
+ }
44
+ /**
45
+ * Store chord data for a specific instrument in IndexedDB
46
+ */
47
+ async setChordData(e, o) {
48
+ try {
49
+ const r = await this.openDB(), n = {
50
+ instrument: e,
51
+ chords: o,
52
+ timestamp: Date.now()
53
+ };
54
+ return new Promise((s, t) => {
55
+ const a = r.transaction([d], "readwrite").objectStore(d).put(n);
56
+ a.onsuccess = () => {
57
+ s();
58
+ }, a.onerror = () => {
59
+ t(new Error(`Failed to store chord data: ${a.error}`));
60
+ };
61
+ });
62
+ } catch (r) {
63
+ throw console.error("IndexedDB error:", r), r;
64
+ }
65
+ }
66
+ /**
67
+ * Get all stored instruments
68
+ */
69
+ async getAllInstruments() {
70
+ try {
71
+ const e = await this.openDB();
72
+ return new Promise((o, r) => {
73
+ const t = e.transaction([d], "readonly").objectStore(d).getAllKeys();
74
+ t.onsuccess = () => {
75
+ o(t.result);
76
+ }, t.onerror = () => {
77
+ r(new Error(`Failed to get instruments: ${t.error}`));
78
+ };
79
+ });
80
+ } catch (e) {
81
+ return console.error("IndexedDB error:", e), [];
82
+ }
83
+ }
84
+ /**
85
+ * Clear all chord data from IndexedDB
86
+ */
87
+ async clearAll() {
88
+ try {
89
+ const e = await this.openDB();
90
+ return new Promise((o, r) => {
91
+ const t = e.transaction([d], "readwrite").objectStore(d).clear();
92
+ t.onsuccess = () => {
93
+ o();
94
+ }, t.onerror = () => {
95
+ r(new Error(`Failed to clear data: ${t.error}`));
96
+ };
97
+ });
98
+ } catch (e) {
99
+ throw console.error("IndexedDB error:", e), e;
100
+ }
101
+ }
102
+ /**
103
+ * Check if IndexedDB is available
104
+ */
105
+ isAvailable() {
106
+ return typeof indexedDB < "u";
107
+ }
108
+ /**
109
+ * Save a user-defined chord
110
+ */
111
+ async saveUserChord(e, o, r) {
112
+ try {
113
+ const n = await this.openDB(), s = {
114
+ key: `${e}:${o}`,
115
+ instrument: e,
116
+ chordName: o,
117
+ fingers: r.fingers,
118
+ barres: r.barres,
119
+ position: r.position,
120
+ timestamp: Date.now()
121
+ };
122
+ return new Promise((t, i) => {
123
+ const l = n.transaction([c], "readwrite").objectStore(c).put(s);
124
+ l.onsuccess = () => {
125
+ t();
126
+ }, l.onerror = () => {
127
+ i(new Error(`Failed to save user chord: ${l.error}`));
128
+ };
129
+ });
130
+ } catch (n) {
131
+ throw console.error("IndexedDB error:", n), n;
132
+ }
133
+ }
134
+ /**
135
+ * Get a user-defined chord
136
+ */
137
+ async getUserChord(e, o) {
138
+ try {
139
+ const r = await this.openDB(), n = `${e}:${o}`;
140
+ return new Promise((s, t) => {
141
+ const a = r.transaction([c], "readonly").objectStore(c).get(n);
142
+ a.onsuccess = () => {
143
+ s(a.result || null);
144
+ }, a.onerror = () => {
145
+ t(new Error(`Failed to get user chord: ${a.error}`));
146
+ };
147
+ });
148
+ } catch (r) {
149
+ return console.error("IndexedDB error:", r), null;
150
+ }
151
+ }
152
+ /**
153
+ * Delete a user-defined chord
154
+ */
155
+ async deleteUserChord(e, o) {
156
+ try {
157
+ const r = await this.openDB(), n = `${e}:${o}`;
158
+ return new Promise((s, t) => {
159
+ const a = r.transaction([c], "readwrite").objectStore(c).delete(n);
160
+ a.onsuccess = () => {
161
+ s();
162
+ }, a.onerror = () => {
163
+ t(new Error(`Failed to delete user chord: ${a.error}`));
164
+ };
165
+ });
166
+ } catch (r) {
167
+ throw console.error("IndexedDB error:", r), r;
168
+ }
169
+ }
170
+ /**
171
+ * Get all user-defined chords for an instrument
172
+ */
173
+ async getUserChordsByInstrument(e) {
174
+ try {
175
+ const o = await this.openDB();
176
+ return new Promise((r, n) => {
177
+ const u = o.transaction([c], "readonly").objectStore(c).index("instrument").getAll(e);
178
+ u.onsuccess = () => {
179
+ r(u.result || []);
180
+ }, u.onerror = () => {
181
+ n(new Error(`Failed to get user chords: ${u.error}`));
182
+ };
183
+ });
184
+ } catch (o) {
185
+ return console.error("IndexedDB error:", o), [];
186
+ }
187
+ }
188
+ /**
189
+ * Get all user-defined chords
190
+ */
191
+ async getAllUserChords() {
192
+ try {
193
+ const e = await this.openDB();
194
+ return new Promise((o, r) => {
195
+ const t = e.transaction([c], "readonly").objectStore(c).getAll();
196
+ t.onsuccess = () => {
197
+ o(t.result || []);
198
+ }, t.onerror = () => {
199
+ r(new Error(`Failed to get all user chords: ${t.error}`));
200
+ };
201
+ });
202
+ } catch (e) {
203
+ return console.error("IndexedDB error:", e), [];
204
+ }
205
+ }
206
+ /**
207
+ * Clear all user-defined chords
208
+ */
209
+ async clearUserChords() {
210
+ try {
211
+ const e = await this.openDB();
212
+ return new Promise((o, r) => {
213
+ const t = e.transaction([c], "readwrite").objectStore(c).clear();
214
+ t.onsuccess = () => {
215
+ o();
216
+ }, t.onerror = () => {
217
+ r(new Error(`Failed to clear user chords: ${t.error}`));
218
+ };
219
+ });
220
+ } catch (e) {
221
+ throw console.error("IndexedDB error:", e), e;
222
+ }
223
+ }
224
+ }
225
+ const S = new h();
226
+ export {
227
+ S as indexedDBService
228
+ };