@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,691 @@
1
+ import { css as b, LitElement as v, html as l } from "lit";
2
+ import { customElement as y } from "./node_modules/@lit/reactive-element/decorators/custom-element.js";
3
+ import { property as m } from "./node_modules/@lit/reactive-element/decorators/property.js";
4
+ import { state as c } from "./node_modules/@lit/reactive-element/decorators/state.js";
5
+ import { query as w } from "./node_modules/@lit/reactive-element/decorators/query.js";
6
+ import { SVGuitarChord as x } from "svguitar";
7
+ import { instruments as g, chordToNotes as F, chordOnInstrument as k } from "./music-utils.js";
8
+ import { chordDataService as f } from "./chord-data-service.js";
9
+ var M = Object.defineProperty, C = Object.getOwnPropertyDescriptor, d = (t, i, e, r) => {
10
+ for (var s = r > 1 ? void 0 : r ? C(i, e) : i, o = t.length - 1, n; o >= 0; o--)
11
+ (n = t[o]) && (s = (r ? n(i, e, s) : n(s)) || s);
12
+ return r && s && M(i, e, s), s;
13
+ };
14
+ let a = class extends v {
15
+ constructor() {
16
+ super(...arguments), this.instrument = "Standard Ukulele", this.chord = "", this.fingers = [], this.barres = [], this.viewPosition = 1, this.isLoading = !1, this.isModified = !1, this.editMode = "finger";
17
+ }
18
+ get numStrings() {
19
+ const t = g.find(({ name: i }) => i === this.instrument);
20
+ return (t == null ? void 0 : t.strings.length) || 4;
21
+ }
22
+ get calculatedPosition() {
23
+ const t = [
24
+ ...this.fingers.map(([, r]) => typeof r == "number" ? r : 0),
25
+ ...this.barres.map((r) => typeof r.fret == "number" ? r.fret : 0)
26
+ ];
27
+ if (t.length === 0) return 1;
28
+ const i = Math.min(...t.filter((r) => r > 0));
29
+ return Math.max(...t, 0) <= 4 ? 1 : Math.max(1, i);
30
+ }
31
+ get maxFrets() {
32
+ const t = [
33
+ ...this.fingers.map(([, s]) => typeof s == "number" ? s : 0),
34
+ ...this.barres.map((s) => typeof s.fret == "number" ? s.fret : 0)
35
+ ], i = Math.max(...t, 0), e = 5, r = Math.max(i - this.viewPosition + 1, 4);
36
+ return Math.max(e, r);
37
+ }
38
+ async connectedCallback() {
39
+ super.connectedCallback(), await this.loadChordData();
40
+ }
41
+ async updated(t) {
42
+ super.updated(t), (t.has("instrument") || t.has("chord")) && await this.loadChordData(), (t.has("fingers") || t.has("barres") || t.has("viewPosition")) && this.renderDiagram();
43
+ }
44
+ async loadChordData() {
45
+ if (this.chord) {
46
+ this.isLoading = !0;
47
+ try {
48
+ const t = await f.getChord(this.instrument, this.chord, !0);
49
+ if (t)
50
+ this.fingers = [...t.fingers], this.barres = [...t.barres], this.viewPosition = this.calculatedPosition, this.isModified = !1;
51
+ else {
52
+ const i = await f.getChord(this.instrument, this.chord, !1);
53
+ i ? (this.fingers = [...i.fingers], this.barres = [...i.barres], this.viewPosition = this.calculatedPosition, this.isModified = !1) : this.generateDefaultChord();
54
+ }
55
+ } catch (t) {
56
+ console.error("Failed to load chord data:", t), this.fingers = [], this.barres = [];
57
+ } finally {
58
+ this.isLoading = !1;
59
+ }
60
+ }
61
+ }
62
+ generateDefaultChord() {
63
+ const t = g.find(({ name: r }) => r === this.instrument);
64
+ if (!t) return;
65
+ const i = k(t), e = F(this.chord);
66
+ e && e.notes && e.notes.length > 0 && (this.fingers = i(e) || [], this.barres = [], this.viewPosition = this.calculatedPosition, this.isModified = !1);
67
+ }
68
+ renderDiagram() {
69
+ if (!this.diagramContainer) return;
70
+ const t = g.find(({ name: e }) => e === this.instrument);
71
+ if (!t) return;
72
+ this.diagramContainer.innerHTML = "";
73
+ const i = document.createElement("div");
74
+ try {
75
+ const e = this.fingers.map(([o, n]) => {
76
+ if (typeof n == "number") {
77
+ const h = n - this.viewPosition + 1;
78
+ if (h >= 0 && h <= this.maxFrets)
79
+ return [o, h];
80
+ } else
81
+ return [o, n];
82
+ return null;
83
+ }).filter((o) => o !== null), r = this.barres.map((o) => {
84
+ if (typeof o.fret == "number") {
85
+ const n = o.fret - this.viewPosition + 1;
86
+ if (n >= 0 && n <= this.maxFrets)
87
+ return {
88
+ ...o,
89
+ fret: n
90
+ };
91
+ }
92
+ return null;
93
+ }).filter((o) => o !== null);
94
+ new x(i).configure({
95
+ strings: t.strings.length,
96
+ frets: this.maxFrets,
97
+ position: this.viewPosition,
98
+ tuning: [...t.strings]
99
+ }).chord({
100
+ fingers: e,
101
+ barres: r
102
+ }).draw(), i.firstChild && (this.diagramContainer.appendChild(i.firstChild), this.setupInteraction());
103
+ } catch (e) {
104
+ console.error("Error rendering diagram:", e);
105
+ }
106
+ }
107
+ setupInteraction() {
108
+ var i;
109
+ const t = (i = this.diagramContainer) == null ? void 0 : i.querySelector("svg");
110
+ t && t.addEventListener("click", (e) => this.handleDiagramClick(e));
111
+ }
112
+ handleDiagramClick(t) {
113
+ const e = t.currentTarget.getBoundingClientRect(), r = t.clientX - e.left, s = t.clientY - e.top, o = e.width / (this.numStrings + 1), n = e.height / (this.maxFrets + 2), h = Math.round((e.width - r) / o);
114
+ let u = Math.round((s - n) / n);
115
+ u = u + this.viewPosition - 1;
116
+ const p = this.viewPosition + this.maxFrets - 1;
117
+ h >= 1 && h <= this.numStrings && u >= 0 && u <= p && this.handlePositionClick(h, u);
118
+ }
119
+ handlePositionClick(t, i) {
120
+ this.editMode === "finger" ? this.addOrUpdateFinger(t, i) : this.editMode === "remove" && this.removeFinger(t);
121
+ }
122
+ addOrUpdateFinger(t, i) {
123
+ const e = this.fingers.findIndex(([r]) => r === t);
124
+ e >= 0 ? this.fingers[e] = [t, i] : this.fingers.push([t, i]), this.fingers = [...this.fingers], this.isModified = !0, this.requestUpdate();
125
+ }
126
+ removeFinger(t) {
127
+ this.fingers = this.fingers.filter(([i]) => i !== t), this.isModified = !0, this.requestUpdate();
128
+ }
129
+ removeFingerByIndex(t) {
130
+ this.fingers.splice(t, 1), this.fingers = [...this.fingers], this.isModified = !0, this.requestUpdate();
131
+ }
132
+ async saveChord() {
133
+ if (this.chord)
134
+ try {
135
+ await f.saveUserChord(
136
+ this.instrument,
137
+ this.chord,
138
+ {
139
+ fingers: this.fingers,
140
+ barres: this.barres
141
+ // position is NOT saved - it's auto-calculated
142
+ }
143
+ ), this.isModified = !1, this.dispatchEvent(new CustomEvent("chord-saved", {
144
+ detail: {
145
+ instrument: this.instrument,
146
+ chord: this.chord,
147
+ data: { fingers: this.fingers, barres: this.barres }
148
+ },
149
+ bubbles: !0,
150
+ composed: !0
151
+ })), this.requestUpdate();
152
+ } catch (t) {
153
+ console.error("Failed to save chord:", t), alert("Failed to save chord. Please try again.");
154
+ }
155
+ }
156
+ async resetToDefault() {
157
+ if (confirm("Reset to default chord? This will discard your changes."))
158
+ try {
159
+ await f.deleteUserChord(this.instrument, this.chord), await this.loadChordData(), this.dispatchEvent(new CustomEvent("chord-reset", {
160
+ detail: {
161
+ instrument: this.instrument,
162
+ chord: this.chord
163
+ },
164
+ bubbles: !0,
165
+ composed: !0
166
+ }));
167
+ } catch (t) {
168
+ console.error("Failed to reset chord:", t);
169
+ }
170
+ }
171
+ clearAll() {
172
+ this.fingers = [], this.barres = [], this.isModified = !0, this.requestUpdate();
173
+ }
174
+ shiftViewPosition(t) {
175
+ const i = Math.max(1, this.viewPosition + t);
176
+ i !== this.viewPosition && (this.viewPosition = i, this.requestUpdate());
177
+ }
178
+ resetViewPosition() {
179
+ this.viewPosition = this.calculatedPosition, this.requestUpdate();
180
+ }
181
+ updateFingerString(t, i) {
182
+ const e = parseInt(i);
183
+ !isNaN(e) && e >= 1 && e <= this.numStrings && (this.fingers[t] = [e, this.fingers[t][1]], this.fingers = [...this.fingers], this.isModified = !0, this.requestUpdate());
184
+ }
185
+ updateFingerFret(t, i) {
186
+ const e = parseInt(i);
187
+ !isNaN(e) && e >= 0 && (this.fingers[t] = [this.fingers[t][0], e], this.fingers = [...this.fingers], this.isModified = !0, this.requestUpdate());
188
+ }
189
+ addNewFinger() {
190
+ this.fingers.push([1, 0]), this.fingers = [...this.fingers], this.isModified = !0, this.requestUpdate();
191
+ }
192
+ addBarre() {
193
+ this.barres.push({
194
+ fromString: this.numStrings,
195
+ toString: 1,
196
+ fret: this.viewPosition,
197
+ text: "1"
198
+ }), this.barres = [...this.barres], this.isModified = !0, this.requestUpdate();
199
+ }
200
+ updateBarreFromString(t, i) {
201
+ const e = parseInt(i);
202
+ !isNaN(e) && e >= 1 && e <= this.numStrings && (this.barres[t].fromString = e, this.barres = [...this.barres], this.isModified = !0, this.requestUpdate());
203
+ }
204
+ updateBarreToString(t, i) {
205
+ const e = parseInt(i);
206
+ !isNaN(e) && e >= 1 && e <= this.numStrings && (this.barres[t].toString = e, this.barres = [...this.barres], this.isModified = !0, this.requestUpdate());
207
+ }
208
+ updateBarreFret(t, i) {
209
+ const e = parseInt(i);
210
+ !isNaN(e) && e >= 0 && (this.barres[t].fret = e, this.barres = [...this.barres], this.isModified = !0, this.requestUpdate());
211
+ }
212
+ removeBarreByIndex(t) {
213
+ this.barres.splice(t, 1), this.barres = [...this.barres], this.isModified = !0, this.requestUpdate();
214
+ }
215
+ render() {
216
+ return this.isLoading ? l`
217
+ <div class='editor'>
218
+ <div class='info'>Loading...</div>
219
+ </div>
220
+ ` : this.chord ? l`
221
+ <div class='editor'>
222
+ <div class='header'>
223
+ <h3>${this.chord} - ${this.instrument}</h3>
224
+ ${this.isModified ? l`<span class='badge modified'>Modified</span>` : l`<span class='badge'>Saved</span>`}
225
+ </div>
226
+
227
+ <div class='diagram-container'></div>
228
+
229
+ <div class='controls'>
230
+ <div class='control-group'>
231
+ <label>View Position (Display Window: Fret ${this.viewPosition})</label>
232
+ <div class='info' style="margin-bottom: 0.5rem;">
233
+ Adjust which frets are shown. The chord itself stays the same.
234
+ </div>
235
+ <div class='button-group'>
236
+ <button @click=${() => this.shiftViewPosition(-1)}>
237
+ ← View Lower
238
+ </button>
239
+ <button @click=${() => this.shiftViewPosition(1)}>
240
+ View Higher →
241
+ </button>
242
+ <button @click=${this.resetViewPosition}>
243
+ Auto Position
244
+ </button>
245
+ </div>
246
+ </div>
247
+
248
+ <div class='control-group'>
249
+ <label>Edit Mode</label>
250
+ <div class='mode-selector'>
251
+ <button
252
+ class='mode-button ${this.editMode === "finger" ? "active" : ""}'
253
+ @click=${() => this.editMode = "finger"}
254
+ >
255
+ Add/Edit
256
+ </button>
257
+ <button
258
+ class='mode-button ${this.editMode === "remove" ? "active" : ""}'
259
+ @click=${() => this.editMode = "remove"}
260
+ >
261
+ Remove
262
+ </button>
263
+ </div>
264
+ </div>
265
+
266
+ <div class='control-group'>
267
+ <label>Finger Positions (${this.fingers.length})</label>
268
+ <div class='finger-list'>
269
+ ${this.fingers.length === 0 ? l`
270
+ <div class='info'>No finger positions. Click the diagram or use "Add Finger" below.</div>
271
+ ` : this.fingers.map((t, i) => l`
272
+ <div class='finger-item'>
273
+ <div class='finger-inputs'>
274
+ <label style="color: #a0aec0; font-size: 0.75rem;">String:</label>
275
+ <input
276
+ type="number"
277
+ min="1"
278
+ max="${this.numStrings}"
279
+ .value="${t[0]}"
280
+ @input=${(e) => this.updateFingerString(i, e.target.value)}
281
+ />
282
+ <label style="color: #a0aec0; font-size: 0.75rem;">Fret:</label>
283
+ <input
284
+ type="number"
285
+ min="0"
286
+ .value="${t[1]}"
287
+ @input=${(e) => this.updateFingerFret(i, e.target.value)}
288
+ />
289
+ </div>
290
+ <button
291
+ class='danger'
292
+ @click=${() => this.removeFingerByIndex(i)}
293
+ >
294
+ ×
295
+ </button>
296
+ </div>
297
+ `)}
298
+ <button class='add-button' @click=${this.addNewFinger}>
299
+ + Add Finger Position
300
+ </button>
301
+ </div>
302
+ </div>
303
+
304
+ <div class='control-group'>
305
+ <label>Barre Positions (${this.barres.length})</label>
306
+ <div class='finger-list'>
307
+ ${this.barres.length === 0 ? l`
308
+ <div class='info'>No barres. Use "Add Barre" below to create one.</div>
309
+ ` : this.barres.map((t, i) => l`
310
+ <div class='finger-item'>
311
+ <div class='finger-inputs'>
312
+ <label style="color: #a0aec0; font-size: 0.75rem;">From:</label>
313
+ <input
314
+ type="number"
315
+ min="1"
316
+ max="${this.numStrings}"
317
+ .value="${t.fromString}"
318
+ @input=${(e) => this.updateBarreFromString(i, e.target.value)}
319
+ />
320
+ <label style="color: #a0aec0; font-size: 0.75rem;">To:</label>
321
+ <input
322
+ type="number"
323
+ min="1"
324
+ max="${this.numStrings}"
325
+ .value="${t.toString}"
326
+ @input=${(e) => this.updateBarreToString(i, e.target.value)}
327
+ />
328
+ <label style="color: #a0aec0; font-size: 0.75rem;">Fret:</label>
329
+ <input
330
+ type="number"
331
+ min="0"
332
+ .value="${t.fret}"
333
+ @input=${(e) => this.updateBarreFret(i, e.target.value)}
334
+ />
335
+ </div>
336
+ <button
337
+ class='danger'
338
+ @click=${() => this.removeBarreByIndex(i)}
339
+ >
340
+ ×
341
+ </button>
342
+ </div>
343
+ `)}
344
+ <button class='add-button' @click=${this.addBarre}>
345
+ + Add Barre
346
+ </button>
347
+ </div>
348
+ </div>
349
+
350
+ <div class='button-group'>
351
+ <button
352
+ class='primary'
353
+ @click=${this.saveChord}
354
+ ?disabled=${!this.isModified}
355
+ >
356
+ Save Custom Chord
357
+ </button>
358
+ <button
359
+ class='secondary'
360
+ @click=${this.resetToDefault}
361
+ >
362
+ Reset to Default
363
+ </button>
364
+ <button
365
+ class='danger'
366
+ @click=${this.clearAll}
367
+ >
368
+ Clear All
369
+ </button>
370
+ </div>
371
+ </div>
372
+
373
+ <div class='info'>
374
+ ${this.editMode === "finger" ? "Click on the diagram to add or update finger positions." : "Click on a finger position to remove it."}
375
+ </div>
376
+ </div>
377
+ ` : l`
378
+ <div class='editor'>
379
+ <div class='error'>No chord specified</div>
380
+ </div>
381
+ `;
382
+ }
383
+ };
384
+ a.styles = b`
385
+ :host {
386
+ display: block;
387
+ width: 100%;
388
+ max-width: 400px;
389
+ border: 1px solid #4a5568;
390
+ border-radius: 8px;
391
+ background: #2d3748;
392
+ padding: 1rem;
393
+ box-sizing: border-box;
394
+ }
395
+
396
+ .editor {
397
+ display: flex;
398
+ flex-direction: column;
399
+ gap: 1rem;
400
+ }
401
+
402
+ .header {
403
+ display: flex;
404
+ justify-content: space-between;
405
+ align-items: center;
406
+ border-bottom: 2px solid #4a5568;
407
+ padding-bottom: 0.5rem;
408
+ }
409
+
410
+ .header h3 {
411
+ color: #90cdf4;
412
+ margin: 0;
413
+ font-size: 1.1rem;
414
+ }
415
+
416
+ .badge {
417
+ background: #3182ce;
418
+ color: white;
419
+ padding: 0.25rem 0.5rem;
420
+ border-radius: 4px;
421
+ font-size: 0.75rem;
422
+ font-weight: 600;
423
+ }
424
+
425
+ .badge.modified {
426
+ background: #f6ad55;
427
+ }
428
+
429
+ .diagram-container {
430
+ position: relative;
431
+ width: 100%;
432
+ display: flex;
433
+ justify-content: center;
434
+ background: #1a202c;
435
+ border-radius: 4px;
436
+ padding: 1rem;
437
+ cursor: crosshair;
438
+ }
439
+
440
+ .diagram-container :global(svg) {
441
+ max-width: 100%;
442
+ height: auto;
443
+ }
444
+
445
+ .controls {
446
+ display: flex;
447
+ flex-direction: column;
448
+ gap: 0.75rem;
449
+ }
450
+
451
+ .control-group {
452
+ display: flex;
453
+ flex-direction: column;
454
+ gap: 0.5rem;
455
+ }
456
+
457
+ .control-group label {
458
+ color: #e2e8f0;
459
+ font-size: 0.9rem;
460
+ font-weight: 500;
461
+ }
462
+
463
+ .button-group {
464
+ display: flex;
465
+ gap: 0.5rem;
466
+ flex-wrap: wrap;
467
+ }
468
+
469
+ button {
470
+ padding: 0.5rem 1rem;
471
+ border-radius: 4px;
472
+ border: 1px solid #4a5568;
473
+ background: #1a202c;
474
+ color: #f8f8f8;
475
+ font-size: 0.9rem;
476
+ cursor: pointer;
477
+ transition: all 0.2s;
478
+ }
479
+
480
+ button:hover {
481
+ background: #2d3748;
482
+ border-color: #63b3ed;
483
+ }
484
+
485
+ button.primary {
486
+ background: #3182ce;
487
+ border-color: #3182ce;
488
+ font-weight: 600;
489
+ }
490
+
491
+ button.primary:hover {
492
+ background: #2c5282;
493
+ }
494
+
495
+ button.secondary {
496
+ background: #718096;
497
+ border-color: #718096;
498
+ }
499
+
500
+ button.secondary:hover {
501
+ background: #4a5568;
502
+ }
503
+
504
+ button.danger {
505
+ background: #e53e3e;
506
+ border-color: #e53e3e;
507
+ }
508
+
509
+ button.danger:hover {
510
+ background: #c53030;
511
+ }
512
+
513
+ button:disabled {
514
+ opacity: 0.5;
515
+ cursor: not-allowed;
516
+ }
517
+
518
+ .mode-selector {
519
+ display: flex;
520
+ gap: 0.5rem;
521
+ background: #1a202c;
522
+ padding: 0.25rem;
523
+ border-radius: 4px;
524
+ }
525
+
526
+ .mode-button {
527
+ flex: 1;
528
+ padding: 0.5rem;
529
+ background: transparent;
530
+ border: none;
531
+ color: #a0aec0;
532
+ font-size: 0.85rem;
533
+ font-weight: 500;
534
+ cursor: pointer;
535
+ border-radius: 4px;
536
+ transition: all 0.2s;
537
+ }
538
+
539
+ .mode-button:hover {
540
+ color: #e2e8f0;
541
+ background: #2d3748;
542
+ }
543
+
544
+ .mode-button.active {
545
+ background: #3182ce;
546
+ color: white;
547
+ }
548
+
549
+ .finger-list {
550
+ display: flex;
551
+ flex-direction: column;
552
+ gap: 0.25rem;
553
+ max-height: 150px;
554
+ overflow-y: auto;
555
+ background: #1a202c;
556
+ padding: 0.5rem;
557
+ border-radius: 4px;
558
+ font-family: monospace;
559
+ font-size: 0.85rem;
560
+ color: #e2e8f0;
561
+ }
562
+
563
+ .finger-item {
564
+ display: flex;
565
+ justify-content: space-between;
566
+ align-items: center;
567
+ gap: 0.5rem;
568
+ padding: 0.25rem 0.5rem;
569
+ background: #2d3748;
570
+ border-radius: 4px;
571
+ }
572
+
573
+ .finger-item button {
574
+ padding: 0.25rem 0.5rem;
575
+ font-size: 0.75rem;
576
+ min-width: 60px;
577
+ }
578
+
579
+ .finger-inputs {
580
+ display: flex;
581
+ gap: 0.5rem;
582
+ align-items: center;
583
+ flex: 1;
584
+ }
585
+
586
+ .finger-inputs input {
587
+ width: 50px;
588
+ padding: 0.25rem 0.5rem;
589
+ background: #1a202c;
590
+ border: 1px solid #4a5568;
591
+ border-radius: 4px;
592
+ color: #f8f8f8;
593
+ font-size: 0.85rem;
594
+ font-family: monospace;
595
+ }
596
+
597
+ .finger-inputs input:focus {
598
+ outline: none;
599
+ border-color: #63b3ed;
600
+ }
601
+
602
+ .add-button {
603
+ width: 100%;
604
+ background: #2d5282 !important;
605
+ border-color: #2d5282 !important;
606
+ display: flex;
607
+ align-items: center;
608
+ justify-content: center;
609
+ gap: 0.5rem;
610
+ }
611
+
612
+ .add-button:hover {
613
+ background: #3182ce !important;
614
+ }
615
+
616
+ .shift-toggle {
617
+ display: flex;
618
+ align-items: center;
619
+ gap: 0.5rem;
620
+ padding: 0.5rem;
621
+ background: #1a202c;
622
+ border-radius: 4px;
623
+ cursor: pointer;
624
+ user-select: none;
625
+ }
626
+
627
+ .shift-toggle:hover {
628
+ background: #2d3748;
629
+ }
630
+
631
+ .shift-toggle input[type="checkbox"] {
632
+ cursor: pointer;
633
+ width: auto;
634
+ padding: 0;
635
+ }
636
+
637
+ .shift-toggle label {
638
+ cursor: pointer;
639
+ margin: 0;
640
+ color: #e2e8f0;
641
+ font-size: 0.85rem;
642
+ }
643
+
644
+ .error {
645
+ color: #fc8181;
646
+ font-size: 0.8rem;
647
+ text-align: center;
648
+ padding: 0.5rem;
649
+ }
650
+
651
+ .info {
652
+ color: #90cdf4;
653
+ font-size: 0.8rem;
654
+ text-align: center;
655
+ padding: 0.5rem;
656
+ font-style: italic;
657
+ }
658
+ `;
659
+ d([
660
+ m({ type: String })
661
+ ], a.prototype, "instrument", 2);
662
+ d([
663
+ m({ type: String })
664
+ ], a.prototype, "chord", 2);
665
+ d([
666
+ c()
667
+ ], a.prototype, "fingers", 2);
668
+ d([
669
+ c()
670
+ ], a.prototype, "barres", 2);
671
+ d([
672
+ c()
673
+ ], a.prototype, "viewPosition", 2);
674
+ d([
675
+ c()
676
+ ], a.prototype, "isLoading", 2);
677
+ d([
678
+ c()
679
+ ], a.prototype, "isModified", 2);
680
+ d([
681
+ c()
682
+ ], a.prototype, "editMode", 2);
683
+ d([
684
+ w(".diagram-container")
685
+ ], a.prototype, "diagramContainer", 2);
686
+ a = d([
687
+ y("chord-editor")
688
+ ], a);
689
+ export {
690
+ a as ChordEditor
691
+ };