@digitalmeadow/control-panel 1.0.11 → 1.0.12
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/dist/index.js +115 -122
- package/dist/index.umd.cjs +71 -78
- package/dist/styles.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,15 +1,33 @@
|
|
|
1
1
|
const W = `
|
|
2
2
|
.cp-root {
|
|
3
|
+
--cp-scale: 1;
|
|
4
|
+
|
|
5
|
+
/* Computed spacing values */
|
|
6
|
+
--cp-space-1: calc(1px * var(--cp-scale));
|
|
7
|
+
--cp-space-2: calc(2px * var(--cp-scale));
|
|
8
|
+
--cp-space-4: calc(4px * var(--cp-scale));
|
|
9
|
+
--cp-space-6: calc(6px * var(--cp-scale));
|
|
10
|
+
--cp-space-8: calc(8px * var(--cp-scale));
|
|
11
|
+
|
|
12
|
+
/* Computed font sizes */
|
|
13
|
+
--cp-font-size-main: calc(10px * var(--cp-scale));
|
|
14
|
+
--cp-font-size-details: calc(1.0em * var(--cp-scale));
|
|
15
|
+
|
|
16
|
+
/* Computed sizes */
|
|
17
|
+
--cp-swatch-size: calc(14px * var(--cp-scale));
|
|
18
|
+
--cp-controller-min-height: calc(18px * var(--cp-scale));
|
|
19
|
+
--cp-button-delete-width: calc(18px * var(--cp-scale));
|
|
20
|
+
--cp-icon-size: calc(8px * var(--cp-scale));
|
|
21
|
+
--cp-icon-position: calc(4px * var(--cp-scale));
|
|
22
|
+
--cp-select-arrow-space: calc(14px * var(--cp-scale));
|
|
23
|
+
|
|
3
24
|
--cp-color-1: rgba(255, 255, 255, 0.15);
|
|
4
25
|
--cp-color-2: rgba(255, 255, 255, 0.25);
|
|
5
26
|
--cp-color-3: rgba(255, 255, 255, 0.35);
|
|
6
27
|
--cp-color-4: rgba(255, 255, 255, 0.45);
|
|
7
28
|
--cp-border-radius: 0px;
|
|
8
|
-
--cp-swatch-size: 14px;
|
|
9
|
-
--cp-font-size-main: 10px;
|
|
10
|
-
--cp-font-size-details: 1.0em;
|
|
11
29
|
--cp-font-weight-bold: 600;
|
|
12
|
-
--cp-padding-v: 4px;
|
|
30
|
+
--cp-padding-v: calc(4px * var(--cp-scale));
|
|
13
31
|
|
|
14
32
|
position: absolute;
|
|
15
33
|
top: 0;
|
|
@@ -20,14 +38,14 @@ const W = `
|
|
|
20
38
|
background: transparent;
|
|
21
39
|
resize: both;
|
|
22
40
|
color: #fff;
|
|
23
|
-
min-width: 200px;
|
|
24
|
-
min-height: 50px;
|
|
41
|
+
min-width: calc(200px * var(--cp-scale));
|
|
42
|
+
min-height: calc(50px * var(--cp-scale));
|
|
25
43
|
font-family:
|
|
26
44
|
var(--cp-font-family), monospace,
|
|
27
45
|
sans-serif;
|
|
28
46
|
font-size: var(--cp-font-size-main);
|
|
29
47
|
line-height: 1;
|
|
30
|
-
padding:
|
|
48
|
+
padding: var(--cp-space-8);
|
|
31
49
|
}
|
|
32
50
|
|
|
33
51
|
/* Apply blend mode to all children except color inputs */
|
|
@@ -58,8 +76,8 @@ const W = `
|
|
|
58
76
|
}
|
|
59
77
|
|
|
60
78
|
.cp-root::-webkit-scrollbar {
|
|
61
|
-
width:
|
|
62
|
-
height:
|
|
79
|
+
width: var(--cp-space-1);
|
|
80
|
+
height: var(--cp-space-1);
|
|
63
81
|
}
|
|
64
82
|
.cp-root::-webkit-scrollbar-track {
|
|
65
83
|
background: transparent;
|
|
@@ -89,10 +107,10 @@ const W = `
|
|
|
89
107
|
}
|
|
90
108
|
|
|
91
109
|
.cp-content {
|
|
92
|
-
margin-top:
|
|
110
|
+
margin-top: var(--cp-space-4);
|
|
93
111
|
display: flex;
|
|
94
112
|
flex-direction: column;
|
|
95
|
-
gap:
|
|
113
|
+
gap: var(--cp-space-2);
|
|
96
114
|
}
|
|
97
115
|
|
|
98
116
|
.cp-folder {
|
|
@@ -100,12 +118,12 @@ const W = `
|
|
|
100
118
|
}
|
|
101
119
|
|
|
102
120
|
.cp-folder-content {
|
|
103
|
-
margin: 0 0 6px 0;
|
|
104
|
-
padding:
|
|
121
|
+
margin: 0 0 calc(6px * var(--cp-scale)) 0;
|
|
122
|
+
padding: var(--cp-space-4) 0 0 0;
|
|
105
123
|
}
|
|
106
124
|
|
|
107
125
|
.cp-controller {
|
|
108
|
-
min-height:
|
|
126
|
+
min-height: var(--cp-controller-min-height);
|
|
109
127
|
display: grid;
|
|
110
128
|
grid-template-columns: 50% 50%;
|
|
111
129
|
align-items: center;
|
|
@@ -118,7 +136,7 @@ const W = `
|
|
|
118
136
|
text-overflow: ellipsis;
|
|
119
137
|
white-space: nowrap;
|
|
120
138
|
user-select: none;
|
|
121
|
-
padding-right:
|
|
139
|
+
padding-right: var(--cp-space-8);
|
|
122
140
|
opacity: 0.8;
|
|
123
141
|
}
|
|
124
142
|
|
|
@@ -126,14 +144,13 @@ const W = `
|
|
|
126
144
|
background: transparent;
|
|
127
145
|
border: 1px solid var(--cp-color-2);
|
|
128
146
|
color: inherit;
|
|
129
|
-
padding:
|
|
147
|
+
padding: var(--cp-space-2) var(--cp-space-4);
|
|
130
148
|
border-radius: var(--cp-border-radius);
|
|
131
149
|
font-family: inherit;
|
|
132
150
|
font-size: inherit;
|
|
133
151
|
height: 100%;
|
|
134
152
|
box-sizing: border-box;
|
|
135
153
|
}
|
|
136
|
-
}
|
|
137
154
|
|
|
138
155
|
.cp-input-number:focus {
|
|
139
156
|
outline: none;
|
|
@@ -145,8 +162,8 @@ const W = `
|
|
|
145
162
|
color: inherit;
|
|
146
163
|
background: var(--cp-color-1);
|
|
147
164
|
border: none;
|
|
148
|
-
padding: var(--cp-padding-v)
|
|
149
|
-
padding-right:
|
|
165
|
+
padding: var(--cp-padding-v) var(--cp-space-4);
|
|
166
|
+
padding-right: calc(var(--cp-space-4) + var(--cp-select-arrow-space));
|
|
150
167
|
border-radius: var(--cp-border-radius);
|
|
151
168
|
font-size: inherit;
|
|
152
169
|
line-height: inherit;
|
|
@@ -157,32 +174,33 @@ const W = `
|
|
|
157
174
|
-moz-appearance: none;
|
|
158
175
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M1 2h6l-3 4z'/%3E%3C/svg%3E");
|
|
159
176
|
background-repeat: no-repeat;
|
|
160
|
-
background-position: right
|
|
177
|
+
background-position: right var(--cp-icon-position) center;
|
|
178
|
+
background-size: var(--cp-icon-size) var(--cp-icon-size);
|
|
161
179
|
}
|
|
162
180
|
|
|
163
181
|
.cp-checkbox {
|
|
164
182
|
margin: auto 0;
|
|
165
|
-
width:
|
|
166
|
-
height:
|
|
183
|
+
width: var(--cp-controller-min-height);
|
|
184
|
+
height: var(--cp-controller-min-height);
|
|
167
185
|
appearance: none;
|
|
168
186
|
-webkit-appearance: none;
|
|
169
187
|
-moz-appearance: none;
|
|
170
|
-
border:
|
|
188
|
+
border: 1px solid var(--cp-color-1);
|
|
171
189
|
border-radius: var(--cp-border-radius);
|
|
172
|
-
background:
|
|
190
|
+
background: transparent;
|
|
173
191
|
cursor: pointer;
|
|
174
192
|
padding: 0;
|
|
175
193
|
outline: none;
|
|
176
194
|
font-size: 0;
|
|
177
195
|
line-height: 0;
|
|
178
196
|
color: transparent;
|
|
197
|
+
vertical-align: middle;
|
|
198
|
+
display: inline-block;
|
|
199
|
+
box-sizing: border-box;
|
|
179
200
|
}
|
|
180
201
|
|
|
181
202
|
.cp-checkbox:checked {
|
|
182
|
-
background
|
|
183
|
-
background-repeat: no-repeat !important;
|
|
184
|
-
background-position: center !important;
|
|
185
|
-
background-size: 8px 8px !important;
|
|
203
|
+
background: var(--cp-color-1);
|
|
186
204
|
}
|
|
187
205
|
|
|
188
206
|
.cp-button {
|
|
@@ -190,7 +208,7 @@ const W = `
|
|
|
190
208
|
color: inherit;
|
|
191
209
|
background: var(--cp-color-1);
|
|
192
210
|
border: none;
|
|
193
|
-
padding: var(--cp-padding-v)
|
|
211
|
+
padding: var(--cp-padding-v) var(--cp-space-2);
|
|
194
212
|
border-radius: var(--cp-border-radius);
|
|
195
213
|
cursor: pointer;
|
|
196
214
|
text-align: center;
|
|
@@ -205,7 +223,7 @@ const W = `
|
|
|
205
223
|
|
|
206
224
|
.cp-button:active {
|
|
207
225
|
background: var(--cp-color-3);
|
|
208
|
-
transform: translateY(
|
|
226
|
+
transform: translateY(var(--cp-space-1));
|
|
209
227
|
}
|
|
210
228
|
|
|
211
229
|
.cp-controller[data-disabled="true"] {
|
|
@@ -224,9 +242,9 @@ const W = `
|
|
|
224
242
|
.cp-controller-summary-content {
|
|
225
243
|
display: inline-flex;
|
|
226
244
|
align-items: center;
|
|
227
|
-
gap:
|
|
228
|
-
width: calc(100% -
|
|
229
|
-
min-height:
|
|
245
|
+
gap: var(--cp-space-4);
|
|
246
|
+
width: calc(100% - var(--cp-button-delete-width));
|
|
247
|
+
min-height: var(--cp-controller-min-height);
|
|
230
248
|
vertical-align: middle;
|
|
231
249
|
}
|
|
232
250
|
|
|
@@ -234,7 +252,7 @@ const W = `
|
|
|
234
252
|
-webkit-appearance: none;
|
|
235
253
|
flex: 1;
|
|
236
254
|
min-width: 0;
|
|
237
|
-
height: 2px;
|
|
255
|
+
height: calc(2px * var(--cp-scale));
|
|
238
256
|
background: var(--cp-color-1);
|
|
239
257
|
margin: 0;
|
|
240
258
|
vertical-align: middle;
|
|
@@ -242,15 +260,15 @@ const W = `
|
|
|
242
260
|
}
|
|
243
261
|
.cp-input-range::-webkit-slider-thumb {
|
|
244
262
|
-webkit-appearance: none;
|
|
245
|
-
width: 4px;
|
|
246
|
-
height: 8px;
|
|
247
|
-
border-radius:
|
|
263
|
+
width: calc(4px * var(--cp-scale));
|
|
264
|
+
height: calc(8px * var(--cp-scale));
|
|
265
|
+
border-radius: var(--cp-border-radius);
|
|
248
266
|
background: #fff;
|
|
249
267
|
cursor: grab;
|
|
250
268
|
}
|
|
251
269
|
.cp-input-range::-moz-range-thumb {
|
|
252
|
-
width: 4px;
|
|
253
|
-
height: 16px;
|
|
270
|
+
width: calc(4px * var(--cp-scale));
|
|
271
|
+
height: calc(16px * var(--cp-scale));
|
|
254
272
|
background: #fff;
|
|
255
273
|
cursor: grab;
|
|
256
274
|
}
|
|
@@ -260,7 +278,7 @@ const W = `
|
|
|
260
278
|
}
|
|
261
279
|
|
|
262
280
|
.cp-value-display {
|
|
263
|
-
min-width: 24px;
|
|
281
|
+
min-width: calc(24px * var(--cp-scale));
|
|
264
282
|
text-align: right;
|
|
265
283
|
font-variant-numeric: tabular-nums;
|
|
266
284
|
font-size: var(--cp-font-size-details);
|
|
@@ -269,17 +287,17 @@ const W = `
|
|
|
269
287
|
}
|
|
270
288
|
|
|
271
289
|
.cp-number-settings {
|
|
272
|
-
margin-top:
|
|
290
|
+
margin-top: var(--cp-space-4);
|
|
273
291
|
background: transparent;
|
|
274
292
|
display: flex;
|
|
275
293
|
flex-direction: column;
|
|
276
|
-
gap:
|
|
294
|
+
gap: var(--cp-space-4);
|
|
277
295
|
}
|
|
278
296
|
|
|
279
297
|
.cp-separator {
|
|
280
298
|
border: none;
|
|
281
299
|
border-top: 1px solid var(--cp-color-1);
|
|
282
|
-
margin:
|
|
300
|
+
margin: var(--cp-space-4) 0;
|
|
283
301
|
width: 100%;
|
|
284
302
|
}
|
|
285
303
|
|
|
@@ -287,28 +305,28 @@ const W = `
|
|
|
287
305
|
display: grid;
|
|
288
306
|
grid-template-columns: 50% 50%;
|
|
289
307
|
align-items: center;
|
|
290
|
-
gap:
|
|
308
|
+
gap: var(--cp-space-2);
|
|
291
309
|
}
|
|
292
310
|
|
|
293
311
|
.cp-array-row {
|
|
294
312
|
display: grid;
|
|
295
313
|
grid-template-columns: auto 1fr;
|
|
296
314
|
align-items: stretch;
|
|
297
|
-
gap:
|
|
315
|
+
gap: var(--cp-space-2);
|
|
298
316
|
}
|
|
299
317
|
|
|
300
318
|
.cp-gradient-stop {
|
|
301
319
|
display: grid;
|
|
302
320
|
grid-template-columns: 50% 50%;
|
|
303
321
|
align-items: stretch;
|
|
304
|
-
gap:
|
|
322
|
+
gap: var(--cp-space-2);
|
|
305
323
|
}
|
|
306
324
|
|
|
307
325
|
.cp-gradient-stop-row {
|
|
308
326
|
display: grid;
|
|
309
327
|
grid-template-columns: auto 1fr auto;
|
|
310
328
|
align-items: center;
|
|
311
|
-
gap:
|
|
329
|
+
gap: var(--cp-space-2);
|
|
312
330
|
}
|
|
313
331
|
|
|
314
332
|
.cp-setting-label {
|
|
@@ -321,13 +339,13 @@ const W = `
|
|
|
321
339
|
|
|
322
340
|
.cp-radios {
|
|
323
341
|
display: flex;
|
|
324
|
-
gap:
|
|
342
|
+
gap: var(--cp-space-2);
|
|
325
343
|
}
|
|
326
344
|
|
|
327
345
|
.cp-radio {
|
|
328
346
|
flex: 1;
|
|
329
347
|
font-size: var(--cp-font-size-details);
|
|
330
|
-
padding: var(--cp-padding-v)
|
|
348
|
+
padding: var(--cp-padding-v) var(--cp-space-2);
|
|
331
349
|
}
|
|
332
350
|
|
|
333
351
|
.cp-radio[data-active="true"] {
|
|
@@ -339,7 +357,7 @@ const W = `
|
|
|
339
357
|
.cp-button-delete {
|
|
340
358
|
grid-column: auto;
|
|
341
359
|
width: 100%;
|
|
342
|
-
min-width:
|
|
360
|
+
min-width: var(--cp-button-delete-width);
|
|
343
361
|
padding: 0;
|
|
344
362
|
display: flex;
|
|
345
363
|
align-items: center;
|
|
@@ -363,41 +381,16 @@ const W = `
|
|
|
363
381
|
border-radius: var(--cp-border-radius);
|
|
364
382
|
}
|
|
365
383
|
|
|
366
|
-
.cp-checkbox {
|
|
367
|
-
margin: auto 0;
|
|
368
|
-
width: 14px;
|
|
369
|
-
height: 14px;
|
|
370
|
-
appearance: none;
|
|
371
|
-
-webkit-appearance: none;
|
|
372
|
-
-moz-appearance: none;
|
|
373
|
-
border: 1px solid var(--cp-color-1);
|
|
374
|
-
border-radius: var(--cp-border-radius);
|
|
375
|
-
background: transparent;
|
|
376
|
-
cursor: pointer;
|
|
377
|
-
padding: 0;
|
|
378
|
-
outline: none;
|
|
379
|
-
font-size: 0;
|
|
380
|
-
line-height: 0;
|
|
381
|
-
color: transparent;
|
|
382
|
-
vertical-align: middle;
|
|
383
|
-
display: inline-block;
|
|
384
|
-
box-sizing: border-box;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
.cp-checkbox:checked {
|
|
388
|
-
background: var(--cp-color-1);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
384
|
.cp-color-swatch {
|
|
392
385
|
width: var(--cp-swatch-size);
|
|
393
386
|
height: var(--cp-swatch-size);
|
|
394
|
-
margin-right:
|
|
387
|
+
margin-right: var(--cp-space-8);
|
|
395
388
|
}
|
|
396
389
|
|
|
397
390
|
.cp-stops-container {
|
|
398
391
|
display: flex;
|
|
399
392
|
flex-direction: column;
|
|
400
|
-
gap:
|
|
393
|
+
gap: var(--cp-space-2);
|
|
401
394
|
}
|
|
402
395
|
`;
|
|
403
396
|
let B = !1;
|
|
@@ -485,8 +478,8 @@ class X {
|
|
|
485
478
|
if (this.analyser.getByteFrequencyData(this.dataArray), this.analyser.getByteTimeDomainData(this.waveformArray), this.spectrumBoost !== 1) {
|
|
486
479
|
const p = this.dataArray.length;
|
|
487
480
|
for (let h = 0; h < p; h++) {
|
|
488
|
-
const
|
|
489
|
-
this.dataArray[h] = Math.min(255, this.dataArray[h] *
|
|
481
|
+
const y = 1 + h / p * (this.spectrumBoost - 1);
|
|
482
|
+
this.dataArray[h] = Math.min(255, this.dataArray[h] * y);
|
|
490
483
|
}
|
|
491
484
|
}
|
|
492
485
|
const t = [2, 10], e = [10, 150], s = [150, 600], i = this.getAverage(t[0], t[1]), a = this.getAverage(e[0], e[1]), o = this.getAverage(s[0], s[1]), l = this.getAverage(0, s[1]);
|
|
@@ -511,7 +504,7 @@ class X {
|
|
|
511
504
|
return () => this.levels[t];
|
|
512
505
|
}
|
|
513
506
|
}
|
|
514
|
-
const
|
|
507
|
+
const M = new X();
|
|
515
508
|
class G {
|
|
516
509
|
constructor() {
|
|
517
510
|
this.midiAccess = null, this.values = /* @__PURE__ */ new Map(), this.isListening = !1, this.resolveListen = null, this.listeningCallback = null, this.init();
|
|
@@ -687,7 +680,7 @@ const Q = new K(), A = class A {
|
|
|
687
680
|
this.domElement.appendChild(t);
|
|
688
681
|
}
|
|
689
682
|
};
|
|
690
|
-
A.audio =
|
|
683
|
+
A.audio = M, A.midi = Z, A.math = Q;
|
|
691
684
|
let u = A;
|
|
692
685
|
class tt extends u {
|
|
693
686
|
constructor(t, e, s = {}) {
|
|
@@ -867,7 +860,7 @@ class H {
|
|
|
867
860
|
0,
|
|
868
861
|
1,
|
|
869
862
|
0.01,
|
|
870
|
-
(
|
|
863
|
+
(y) => u.math.setConfig(t, { phase: y })
|
|
871
864
|
);
|
|
872
865
|
this.mathParamsContainer.appendChild(d.row);
|
|
873
866
|
}
|
|
@@ -964,8 +957,8 @@ class et extends u {
|
|
|
964
957
|
(f) => this.setStep(f)
|
|
965
958
|
);
|
|
966
959
|
this.stepInput = d.input, l.appendChild(d.row);
|
|
967
|
-
const
|
|
968
|
-
l.appendChild(
|
|
960
|
+
const y = r("hr", { className: "cp-separator" });
|
|
961
|
+
l.appendChild(y), this.signalHandler = new H({
|
|
969
962
|
container: l,
|
|
970
963
|
onChange: (f, b) => this.applySignal(f, b)
|
|
971
964
|
}), i.appendChild(l), this.appendWidget(i);
|
|
@@ -1148,7 +1141,7 @@ function $(n) {
|
|
|
1148
1141
|
function rt(n, t, e) {
|
|
1149
1142
|
return "#" + ((1 << 24) + (Math.round(n) << 16) + (Math.round(t) << 8) + Math.round(e)).toString(16).slice(1);
|
|
1150
1143
|
}
|
|
1151
|
-
function
|
|
1144
|
+
function T(n) {
|
|
1152
1145
|
const t = n / 255;
|
|
1153
1146
|
return t <= 0.04045 ? t / 12.92 : Math.pow((t + 0.055) / 1.055, 2.4);
|
|
1154
1147
|
}
|
|
@@ -1156,8 +1149,8 @@ function F(n) {
|
|
|
1156
1149
|
return n <= 31308e-7 ? n * 12.92 * 255 : (1.055 * Math.pow(n, 1 / 2.4) - 0.055) * 255;
|
|
1157
1150
|
}
|
|
1158
1151
|
function lt(n, t, e) {
|
|
1159
|
-
const [s, i, a] = $(n), [o, l, p] = $(t), h =
|
|
1160
|
-
return rt(c, m,
|
|
1152
|
+
const [s, i, a] = $(n), [o, l, p] = $(t), h = T(s), d = T(i), y = T(a), f = T(o), b = T(l), E = T(p), g = h + e * (f - h), V = d + e * (b - d), S = y + e * (E - y), c = F(g), m = F(V), v = F(S);
|
|
1153
|
+
return rt(c, m, v);
|
|
1161
1154
|
}
|
|
1162
1155
|
class ct extends u {
|
|
1163
1156
|
constructor(t, e, s = {}) {
|
|
@@ -1194,7 +1187,7 @@ class ct extends u {
|
|
|
1194
1187
|
const h = r("hr", { className: "cp-separator" });
|
|
1195
1188
|
l.appendChild(h), this.signalHandler = new H({
|
|
1196
1189
|
container: l,
|
|
1197
|
-
onChange: (d,
|
|
1190
|
+
onChange: (d, y) => this.applySignal(d, y)
|
|
1198
1191
|
}), i.appendChild(l), this.appendWidget(i), this.updateOutput(0);
|
|
1199
1192
|
}
|
|
1200
1193
|
sortStops() {
|
|
@@ -1517,35 +1510,35 @@ class ut extends U {
|
|
|
1517
1510
|
l = m.left, p = m.top, c.preventDefault();
|
|
1518
1511
|
}), document.addEventListener("mousemove", (c) => {
|
|
1519
1512
|
if (!i) return;
|
|
1520
|
-
const m = c.clientX - a,
|
|
1521
|
-
this.domElement.style.left = `${
|
|
1513
|
+
const m = c.clientX - a, v = c.clientY - o, w = l + m, k = p + v;
|
|
1514
|
+
this.domElement.style.left = `${w}px`, this.domElement.style.top = `${k}px`, this.domElement.style.right = "auto", this.domElement.style.bottom = "auto";
|
|
1522
1515
|
}), document.addEventListener("mouseup", () => {
|
|
1523
1516
|
i && (i = !1, this.savePositionAndSize());
|
|
1524
1517
|
}), new ResizeObserver(() => {
|
|
1525
1518
|
i || this.savePositionAndSize();
|
|
1526
1519
|
}).observe(this.domElement), this.restorePositionAndSize(), this.contentElement = r("div", { className: "cp-content" }), this.domElement.appendChild(this.contentElement);
|
|
1527
|
-
const d = this.addFolder("_Signals"),
|
|
1520
|
+
const d = this.addFolder("_Signals"), y = {
|
|
1528
1521
|
audioInput: null,
|
|
1529
1522
|
fftSize: 2048
|
|
1530
1523
|
};
|
|
1531
|
-
d.addRadio(
|
|
1524
|
+
d.addRadio(y, "audioInput", {
|
|
1532
1525
|
label: "Audio Signal",
|
|
1533
1526
|
options: ["microphone", "browser"]
|
|
1534
1527
|
}).onChange((c) => {
|
|
1535
|
-
|
|
1536
|
-
}), d.addSelect(
|
|
1528
|
+
M.setInput(c);
|
|
1529
|
+
}), d.addSelect(y, "fftSize", {
|
|
1537
1530
|
label: "FFT Size",
|
|
1538
1531
|
options: [256, 512, 1024, 2048]
|
|
1539
1532
|
}).onChange((c) => {
|
|
1540
|
-
|
|
1541
|
-
}), d.addRange(
|
|
1533
|
+
M.setFFTSize(c);
|
|
1534
|
+
}), d.addRange(M, "smoothingTimeConstant", {
|
|
1542
1535
|
min: 0,
|
|
1543
1536
|
max: 0.99,
|
|
1544
1537
|
step: 0.01,
|
|
1545
1538
|
label: "Smoothing"
|
|
1546
1539
|
}).onChange((c) => {
|
|
1547
|
-
|
|
1548
|
-
}), d.addRange(
|
|
1540
|
+
M.analyser.smoothingTimeConstant = c;
|
|
1541
|
+
}), d.addRange(M, "spectrumBoost", {
|
|
1549
1542
|
min: 1,
|
|
1550
1543
|
max: 5,
|
|
1551
1544
|
step: 0.1,
|
|
@@ -1557,10 +1550,10 @@ class ut extends U {
|
|
|
1557
1550
|
const c = ["Default"];
|
|
1558
1551
|
if (typeof localStorage > "u") return c;
|
|
1559
1552
|
for (let m = 0; m < localStorage.length; m++) {
|
|
1560
|
-
const
|
|
1561
|
-
if (
|
|
1562
|
-
const
|
|
1563
|
-
|
|
1553
|
+
const v = localStorage.key(m);
|
|
1554
|
+
if (v && v.startsWith(this.presetStoragePrefix)) {
|
|
1555
|
+
const w = v.substring(this.presetStoragePrefix.length);
|
|
1556
|
+
w !== "Default" && !c.includes(w) && c.push(w);
|
|
1564
1557
|
}
|
|
1565
1558
|
}
|
|
1566
1559
|
return c.sort();
|
|
@@ -1575,13 +1568,13 @@ class ut extends U {
|
|
|
1575
1568
|
}
|
|
1576
1569
|
const m = this.presetStoragePrefix + c;
|
|
1577
1570
|
this.saveToLocalStorage(m);
|
|
1578
|
-
const
|
|
1579
|
-
|
|
1571
|
+
const v = E();
|
|
1572
|
+
S.setOptions(v), g.selected = c, S.setValue(c);
|
|
1580
1573
|
}
|
|
1581
1574
|
},
|
|
1582
1575
|
load: () => {
|
|
1583
1576
|
const c = g.selected, m = this.presetStoragePrefix + c;
|
|
1584
|
-
this.loadFromLocalStorage(m), g.selected = c,
|
|
1577
|
+
this.loadFromLocalStorage(m), g.selected = c, S.setValue(c);
|
|
1585
1578
|
},
|
|
1586
1579
|
delete: () => {
|
|
1587
1580
|
if (g.selected === "Default") {
|
|
@@ -1592,7 +1585,7 @@ class ut extends U {
|
|
|
1592
1585
|
const c = this.presetStoragePrefix + g.selected;
|
|
1593
1586
|
localStorage.removeItem(c);
|
|
1594
1587
|
const m = E();
|
|
1595
|
-
|
|
1588
|
+
S.setOptions(m), g.selected = "Default", S.setValue("Default"), this.reset();
|
|
1596
1589
|
}
|
|
1597
1590
|
},
|
|
1598
1591
|
export: () => {
|
|
@@ -1608,35 +1601,35 @@ class ut extends U {
|
|
|
1608
1601
|
))
|
|
1609
1602
|
z.startsWith("_") || (L.folders[z] = m(O));
|
|
1610
1603
|
return L;
|
|
1611
|
-
},
|
|
1604
|
+
}, v = m(c), w = {
|
|
1612
1605
|
_presetName: g.selected || "CustomPreset",
|
|
1613
1606
|
_exportDate: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1614
1607
|
_instructions: "To add as factory preset: Copy 'controllers' and 'folders' fields into the presets.json file",
|
|
1615
|
-
...
|
|
1616
|
-
},
|
|
1617
|
-
|
|
1608
|
+
...v
|
|
1609
|
+
}, k = JSON.stringify(w, null, 2), C = new Blob([k], { type: "application/json" }), I = URL.createObjectURL(C), x = document.createElement("a");
|
|
1610
|
+
x.href = I;
|
|
1618
1611
|
const N = (/* @__PURE__ */ new Date()).toISOString().split("T")[0], D = g.selected.replace(/[^a-z0-9]/gi, "-").toLowerCase();
|
|
1619
|
-
|
|
1612
|
+
x.download = `${f.toLowerCase()}-preset-${D}-${N}.json`, document.body.appendChild(x), x.click(), document.body.removeChild(x), URL.revokeObjectURL(I);
|
|
1620
1613
|
},
|
|
1621
1614
|
import: () => {
|
|
1622
1615
|
const c = document.createElement("input");
|
|
1623
1616
|
c.type = "file", c.accept = ".json", c.onchange = (m) => {
|
|
1624
|
-
const
|
|
1625
|
-
if (!
|
|
1626
|
-
const
|
|
1627
|
-
|
|
1617
|
+
const v = m.target.files?.[0];
|
|
1618
|
+
if (!v) return;
|
|
1619
|
+
const w = new FileReader();
|
|
1620
|
+
w.onload = (k) => {
|
|
1628
1621
|
try {
|
|
1629
|
-
const C =
|
|
1622
|
+
const C = k.target?.result, I = JSON.parse(C), x = {
|
|
1630
1623
|
controllers: I.controllers || {},
|
|
1631
1624
|
folders: I.folders || {}
|
|
1632
1625
|
};
|
|
1633
|
-
if (!
|
|
1626
|
+
if (!x.controllers || !x.folders) {
|
|
1634
1627
|
alert(
|
|
1635
1628
|
"Invalid preset file: missing 'controllers' or 'folders'"
|
|
1636
1629
|
);
|
|
1637
1630
|
return;
|
|
1638
1631
|
}
|
|
1639
|
-
this.load(
|
|
1632
|
+
this.load(x);
|
|
1640
1633
|
const N = I._presetName || "ImportedPreset";
|
|
1641
1634
|
if (confirm(
|
|
1642
1635
|
`Preset loaded! Save as "${N}" to User Presets?`
|
|
@@ -1644,17 +1637,17 @@ class ut extends U {
|
|
|
1644
1637
|
const P = this.presetStoragePrefix + N;
|
|
1645
1638
|
this.saveToLocalStorage(P);
|
|
1646
1639
|
const L = E();
|
|
1647
|
-
|
|
1640
|
+
S.setOptions(L), g.selected = N, S.setValue(N);
|
|
1648
1641
|
}
|
|
1649
1642
|
} catch (C) {
|
|
1650
1643
|
alert(
|
|
1651
1644
|
`Failed to import preset: ${C instanceof Error ? C.message : "Invalid JSON"}`
|
|
1652
1645
|
), console.error("Import error:", C);
|
|
1653
1646
|
}
|
|
1654
|
-
},
|
|
1647
|
+
}, w.readAsText(v);
|
|
1655
1648
|
}, c.click();
|
|
1656
1649
|
}
|
|
1657
|
-
}, V = E(),
|
|
1650
|
+
}, V = E(), S = b.addSelect(g, "selected", {
|
|
1658
1651
|
label: "Preset",
|
|
1659
1652
|
options: V
|
|
1660
1653
|
});
|
|
@@ -1729,7 +1722,7 @@ export {
|
|
|
1729
1722
|
at as RadioController,
|
|
1730
1723
|
et as RangeController,
|
|
1731
1724
|
st as SelectController,
|
|
1732
|
-
|
|
1725
|
+
M as audioSignals,
|
|
1733
1726
|
Q as mathSignals,
|
|
1734
1727
|
Z as midiSignals
|
|
1735
1728
|
};
|
package/dist/index.umd.cjs
CHANGED
|
@@ -1,15 +1,33 @@
|
|
|
1
1
|
(function(h,L){typeof exports=="object"&&typeof module<"u"?L(exports):typeof define=="function"&&define.amd?define(["exports"],L):(h=typeof globalThis<"u"?globalThis:h||self,L(h.ControlPanel={}))})(this,(function(h){"use strict";const L=`
|
|
2
2
|
.cp-root {
|
|
3
|
+
--cp-scale: 1;
|
|
4
|
+
|
|
5
|
+
/* Computed spacing values */
|
|
6
|
+
--cp-space-1: calc(1px * var(--cp-scale));
|
|
7
|
+
--cp-space-2: calc(2px * var(--cp-scale));
|
|
8
|
+
--cp-space-4: calc(4px * var(--cp-scale));
|
|
9
|
+
--cp-space-6: calc(6px * var(--cp-scale));
|
|
10
|
+
--cp-space-8: calc(8px * var(--cp-scale));
|
|
11
|
+
|
|
12
|
+
/* Computed font sizes */
|
|
13
|
+
--cp-font-size-main: calc(10px * var(--cp-scale));
|
|
14
|
+
--cp-font-size-details: calc(1.0em * var(--cp-scale));
|
|
15
|
+
|
|
16
|
+
/* Computed sizes */
|
|
17
|
+
--cp-swatch-size: calc(14px * var(--cp-scale));
|
|
18
|
+
--cp-controller-min-height: calc(18px * var(--cp-scale));
|
|
19
|
+
--cp-button-delete-width: calc(18px * var(--cp-scale));
|
|
20
|
+
--cp-icon-size: calc(8px * var(--cp-scale));
|
|
21
|
+
--cp-icon-position: calc(4px * var(--cp-scale));
|
|
22
|
+
--cp-select-arrow-space: calc(14px * var(--cp-scale));
|
|
23
|
+
|
|
3
24
|
--cp-color-1: rgba(255, 255, 255, 0.15);
|
|
4
25
|
--cp-color-2: rgba(255, 255, 255, 0.25);
|
|
5
26
|
--cp-color-3: rgba(255, 255, 255, 0.35);
|
|
6
27
|
--cp-color-4: rgba(255, 255, 255, 0.45);
|
|
7
28
|
--cp-border-radius: 0px;
|
|
8
|
-
--cp-swatch-size: 14px;
|
|
9
|
-
--cp-font-size-main: 10px;
|
|
10
|
-
--cp-font-size-details: 1.0em;
|
|
11
29
|
--cp-font-weight-bold: 600;
|
|
12
|
-
--cp-padding-v: 4px;
|
|
30
|
+
--cp-padding-v: calc(4px * var(--cp-scale));
|
|
13
31
|
|
|
14
32
|
position: absolute;
|
|
15
33
|
top: 0;
|
|
@@ -20,14 +38,14 @@
|
|
|
20
38
|
background: transparent;
|
|
21
39
|
resize: both;
|
|
22
40
|
color: #fff;
|
|
23
|
-
min-width: 200px;
|
|
24
|
-
min-height: 50px;
|
|
41
|
+
min-width: calc(200px * var(--cp-scale));
|
|
42
|
+
min-height: calc(50px * var(--cp-scale));
|
|
25
43
|
font-family:
|
|
26
44
|
var(--cp-font-family), monospace,
|
|
27
45
|
sans-serif;
|
|
28
46
|
font-size: var(--cp-font-size-main);
|
|
29
47
|
line-height: 1;
|
|
30
|
-
padding:
|
|
48
|
+
padding: var(--cp-space-8);
|
|
31
49
|
}
|
|
32
50
|
|
|
33
51
|
/* Apply blend mode to all children except color inputs */
|
|
@@ -58,8 +76,8 @@
|
|
|
58
76
|
}
|
|
59
77
|
|
|
60
78
|
.cp-root::-webkit-scrollbar {
|
|
61
|
-
width:
|
|
62
|
-
height:
|
|
79
|
+
width: var(--cp-space-1);
|
|
80
|
+
height: var(--cp-space-1);
|
|
63
81
|
}
|
|
64
82
|
.cp-root::-webkit-scrollbar-track {
|
|
65
83
|
background: transparent;
|
|
@@ -89,10 +107,10 @@
|
|
|
89
107
|
}
|
|
90
108
|
|
|
91
109
|
.cp-content {
|
|
92
|
-
margin-top:
|
|
110
|
+
margin-top: var(--cp-space-4);
|
|
93
111
|
display: flex;
|
|
94
112
|
flex-direction: column;
|
|
95
|
-
gap:
|
|
113
|
+
gap: var(--cp-space-2);
|
|
96
114
|
}
|
|
97
115
|
|
|
98
116
|
.cp-folder {
|
|
@@ -100,12 +118,12 @@
|
|
|
100
118
|
}
|
|
101
119
|
|
|
102
120
|
.cp-folder-content {
|
|
103
|
-
margin: 0 0 6px 0;
|
|
104
|
-
padding:
|
|
121
|
+
margin: 0 0 calc(6px * var(--cp-scale)) 0;
|
|
122
|
+
padding: var(--cp-space-4) 0 0 0;
|
|
105
123
|
}
|
|
106
124
|
|
|
107
125
|
.cp-controller {
|
|
108
|
-
min-height:
|
|
126
|
+
min-height: var(--cp-controller-min-height);
|
|
109
127
|
display: grid;
|
|
110
128
|
grid-template-columns: 50% 50%;
|
|
111
129
|
align-items: center;
|
|
@@ -118,7 +136,7 @@
|
|
|
118
136
|
text-overflow: ellipsis;
|
|
119
137
|
white-space: nowrap;
|
|
120
138
|
user-select: none;
|
|
121
|
-
padding-right:
|
|
139
|
+
padding-right: var(--cp-space-8);
|
|
122
140
|
opacity: 0.8;
|
|
123
141
|
}
|
|
124
142
|
|
|
@@ -126,14 +144,13 @@
|
|
|
126
144
|
background: transparent;
|
|
127
145
|
border: 1px solid var(--cp-color-2);
|
|
128
146
|
color: inherit;
|
|
129
|
-
padding:
|
|
147
|
+
padding: var(--cp-space-2) var(--cp-space-4);
|
|
130
148
|
border-radius: var(--cp-border-radius);
|
|
131
149
|
font-family: inherit;
|
|
132
150
|
font-size: inherit;
|
|
133
151
|
height: 100%;
|
|
134
152
|
box-sizing: border-box;
|
|
135
153
|
}
|
|
136
|
-
}
|
|
137
154
|
|
|
138
155
|
.cp-input-number:focus {
|
|
139
156
|
outline: none;
|
|
@@ -145,8 +162,8 @@
|
|
|
145
162
|
color: inherit;
|
|
146
163
|
background: var(--cp-color-1);
|
|
147
164
|
border: none;
|
|
148
|
-
padding: var(--cp-padding-v)
|
|
149
|
-
padding-right:
|
|
165
|
+
padding: var(--cp-padding-v) var(--cp-space-4);
|
|
166
|
+
padding-right: calc(var(--cp-space-4) + var(--cp-select-arrow-space));
|
|
150
167
|
border-radius: var(--cp-border-radius);
|
|
151
168
|
font-size: inherit;
|
|
152
169
|
line-height: inherit;
|
|
@@ -157,32 +174,33 @@
|
|
|
157
174
|
-moz-appearance: none;
|
|
158
175
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M1 2h6l-3 4z'/%3E%3C/svg%3E");
|
|
159
176
|
background-repeat: no-repeat;
|
|
160
|
-
background-position: right
|
|
177
|
+
background-position: right var(--cp-icon-position) center;
|
|
178
|
+
background-size: var(--cp-icon-size) var(--cp-icon-size);
|
|
161
179
|
}
|
|
162
180
|
|
|
163
181
|
.cp-checkbox {
|
|
164
182
|
margin: auto 0;
|
|
165
|
-
width:
|
|
166
|
-
height:
|
|
183
|
+
width: var(--cp-controller-min-height);
|
|
184
|
+
height: var(--cp-controller-min-height);
|
|
167
185
|
appearance: none;
|
|
168
186
|
-webkit-appearance: none;
|
|
169
187
|
-moz-appearance: none;
|
|
170
|
-
border:
|
|
188
|
+
border: 1px solid var(--cp-color-1);
|
|
171
189
|
border-radius: var(--cp-border-radius);
|
|
172
|
-
background:
|
|
190
|
+
background: transparent;
|
|
173
191
|
cursor: pointer;
|
|
174
192
|
padding: 0;
|
|
175
193
|
outline: none;
|
|
176
194
|
font-size: 0;
|
|
177
195
|
line-height: 0;
|
|
178
196
|
color: transparent;
|
|
197
|
+
vertical-align: middle;
|
|
198
|
+
display: inline-block;
|
|
199
|
+
box-sizing: border-box;
|
|
179
200
|
}
|
|
180
201
|
|
|
181
202
|
.cp-checkbox:checked {
|
|
182
|
-
background
|
|
183
|
-
background-repeat: no-repeat !important;
|
|
184
|
-
background-position: center !important;
|
|
185
|
-
background-size: 8px 8px !important;
|
|
203
|
+
background: var(--cp-color-1);
|
|
186
204
|
}
|
|
187
205
|
|
|
188
206
|
.cp-button {
|
|
@@ -190,7 +208,7 @@
|
|
|
190
208
|
color: inherit;
|
|
191
209
|
background: var(--cp-color-1);
|
|
192
210
|
border: none;
|
|
193
|
-
padding: var(--cp-padding-v)
|
|
211
|
+
padding: var(--cp-padding-v) var(--cp-space-2);
|
|
194
212
|
border-radius: var(--cp-border-radius);
|
|
195
213
|
cursor: pointer;
|
|
196
214
|
text-align: center;
|
|
@@ -205,7 +223,7 @@
|
|
|
205
223
|
|
|
206
224
|
.cp-button:active {
|
|
207
225
|
background: var(--cp-color-3);
|
|
208
|
-
transform: translateY(
|
|
226
|
+
transform: translateY(var(--cp-space-1));
|
|
209
227
|
}
|
|
210
228
|
|
|
211
229
|
.cp-controller[data-disabled="true"] {
|
|
@@ -224,9 +242,9 @@
|
|
|
224
242
|
.cp-controller-summary-content {
|
|
225
243
|
display: inline-flex;
|
|
226
244
|
align-items: center;
|
|
227
|
-
gap:
|
|
228
|
-
width: calc(100% -
|
|
229
|
-
min-height:
|
|
245
|
+
gap: var(--cp-space-4);
|
|
246
|
+
width: calc(100% - var(--cp-button-delete-width));
|
|
247
|
+
min-height: var(--cp-controller-min-height);
|
|
230
248
|
vertical-align: middle;
|
|
231
249
|
}
|
|
232
250
|
|
|
@@ -234,7 +252,7 @@
|
|
|
234
252
|
-webkit-appearance: none;
|
|
235
253
|
flex: 1;
|
|
236
254
|
min-width: 0;
|
|
237
|
-
height: 2px;
|
|
255
|
+
height: calc(2px * var(--cp-scale));
|
|
238
256
|
background: var(--cp-color-1);
|
|
239
257
|
margin: 0;
|
|
240
258
|
vertical-align: middle;
|
|
@@ -242,15 +260,15 @@
|
|
|
242
260
|
}
|
|
243
261
|
.cp-input-range::-webkit-slider-thumb {
|
|
244
262
|
-webkit-appearance: none;
|
|
245
|
-
width: 4px;
|
|
246
|
-
height: 8px;
|
|
247
|
-
border-radius:
|
|
263
|
+
width: calc(4px * var(--cp-scale));
|
|
264
|
+
height: calc(8px * var(--cp-scale));
|
|
265
|
+
border-radius: var(--cp-border-radius);
|
|
248
266
|
background: #fff;
|
|
249
267
|
cursor: grab;
|
|
250
268
|
}
|
|
251
269
|
.cp-input-range::-moz-range-thumb {
|
|
252
|
-
width: 4px;
|
|
253
|
-
height: 16px;
|
|
270
|
+
width: calc(4px * var(--cp-scale));
|
|
271
|
+
height: calc(16px * var(--cp-scale));
|
|
254
272
|
background: #fff;
|
|
255
273
|
cursor: grab;
|
|
256
274
|
}
|
|
@@ -260,7 +278,7 @@
|
|
|
260
278
|
}
|
|
261
279
|
|
|
262
280
|
.cp-value-display {
|
|
263
|
-
min-width: 24px;
|
|
281
|
+
min-width: calc(24px * var(--cp-scale));
|
|
264
282
|
text-align: right;
|
|
265
283
|
font-variant-numeric: tabular-nums;
|
|
266
284
|
font-size: var(--cp-font-size-details);
|
|
@@ -269,17 +287,17 @@
|
|
|
269
287
|
}
|
|
270
288
|
|
|
271
289
|
.cp-number-settings {
|
|
272
|
-
margin-top:
|
|
290
|
+
margin-top: var(--cp-space-4);
|
|
273
291
|
background: transparent;
|
|
274
292
|
display: flex;
|
|
275
293
|
flex-direction: column;
|
|
276
|
-
gap:
|
|
294
|
+
gap: var(--cp-space-4);
|
|
277
295
|
}
|
|
278
296
|
|
|
279
297
|
.cp-separator {
|
|
280
298
|
border: none;
|
|
281
299
|
border-top: 1px solid var(--cp-color-1);
|
|
282
|
-
margin:
|
|
300
|
+
margin: var(--cp-space-4) 0;
|
|
283
301
|
width: 100%;
|
|
284
302
|
}
|
|
285
303
|
|
|
@@ -287,28 +305,28 @@
|
|
|
287
305
|
display: grid;
|
|
288
306
|
grid-template-columns: 50% 50%;
|
|
289
307
|
align-items: center;
|
|
290
|
-
gap:
|
|
308
|
+
gap: var(--cp-space-2);
|
|
291
309
|
}
|
|
292
310
|
|
|
293
311
|
.cp-array-row {
|
|
294
312
|
display: grid;
|
|
295
313
|
grid-template-columns: auto 1fr;
|
|
296
314
|
align-items: stretch;
|
|
297
|
-
gap:
|
|
315
|
+
gap: var(--cp-space-2);
|
|
298
316
|
}
|
|
299
317
|
|
|
300
318
|
.cp-gradient-stop {
|
|
301
319
|
display: grid;
|
|
302
320
|
grid-template-columns: 50% 50%;
|
|
303
321
|
align-items: stretch;
|
|
304
|
-
gap:
|
|
322
|
+
gap: var(--cp-space-2);
|
|
305
323
|
}
|
|
306
324
|
|
|
307
325
|
.cp-gradient-stop-row {
|
|
308
326
|
display: grid;
|
|
309
327
|
grid-template-columns: auto 1fr auto;
|
|
310
328
|
align-items: center;
|
|
311
|
-
gap:
|
|
329
|
+
gap: var(--cp-space-2);
|
|
312
330
|
}
|
|
313
331
|
|
|
314
332
|
.cp-setting-label {
|
|
@@ -321,13 +339,13 @@
|
|
|
321
339
|
|
|
322
340
|
.cp-radios {
|
|
323
341
|
display: flex;
|
|
324
|
-
gap:
|
|
342
|
+
gap: var(--cp-space-2);
|
|
325
343
|
}
|
|
326
344
|
|
|
327
345
|
.cp-radio {
|
|
328
346
|
flex: 1;
|
|
329
347
|
font-size: var(--cp-font-size-details);
|
|
330
|
-
padding: var(--cp-padding-v)
|
|
348
|
+
padding: var(--cp-padding-v) var(--cp-space-2);
|
|
331
349
|
}
|
|
332
350
|
|
|
333
351
|
.cp-radio[data-active="true"] {
|
|
@@ -339,7 +357,7 @@
|
|
|
339
357
|
.cp-button-delete {
|
|
340
358
|
grid-column: auto;
|
|
341
359
|
width: 100%;
|
|
342
|
-
min-width:
|
|
360
|
+
min-width: var(--cp-button-delete-width);
|
|
343
361
|
padding: 0;
|
|
344
362
|
display: flex;
|
|
345
363
|
align-items: center;
|
|
@@ -363,40 +381,15 @@
|
|
|
363
381
|
border-radius: var(--cp-border-radius);
|
|
364
382
|
}
|
|
365
383
|
|
|
366
|
-
.cp-checkbox {
|
|
367
|
-
margin: auto 0;
|
|
368
|
-
width: 14px;
|
|
369
|
-
height: 14px;
|
|
370
|
-
appearance: none;
|
|
371
|
-
-webkit-appearance: none;
|
|
372
|
-
-moz-appearance: none;
|
|
373
|
-
border: 1px solid var(--cp-color-1);
|
|
374
|
-
border-radius: var(--cp-border-radius);
|
|
375
|
-
background: transparent;
|
|
376
|
-
cursor: pointer;
|
|
377
|
-
padding: 0;
|
|
378
|
-
outline: none;
|
|
379
|
-
font-size: 0;
|
|
380
|
-
line-height: 0;
|
|
381
|
-
color: transparent;
|
|
382
|
-
vertical-align: middle;
|
|
383
|
-
display: inline-block;
|
|
384
|
-
box-sizing: border-box;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
.cp-checkbox:checked {
|
|
388
|
-
background: var(--cp-color-1);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
384
|
.cp-color-swatch {
|
|
392
385
|
width: var(--cp-swatch-size);
|
|
393
386
|
height: var(--cp-swatch-size);
|
|
394
|
-
margin-right:
|
|
387
|
+
margin-right: var(--cp-space-8);
|
|
395
388
|
}
|
|
396
389
|
|
|
397
390
|
.cp-stops-container {
|
|
398
391
|
display: flex;
|
|
399
392
|
flex-direction: column;
|
|
400
|
-
gap:
|
|
393
|
+
gap: var(--cp-space-2);
|
|
401
394
|
}
|
|
402
|
-
`;let R=!1;function lt(){if(R)return;const n=document.createElement("style");n.id="control-panel-styles",n.textContent=L,document.head.appendChild(n),R=!0}function o(n,t={},e=[]){const s=document.createElement(n);for(const[i,a]of Object.entries(t))i==="className"?s.className=String(a):i==="style"&&typeof a=="object"?Object.assign(s.style,a):i==="open"&&typeof a=="boolean"?a?s.setAttribute("open",""):s.removeAttribute("open"):typeof a!="object"&&s.setAttribute(i,String(a));for(const i of e)typeof i=="string"?s.appendChild(document.createTextNode(i)):s.appendChild(i);return s}function j(n){const t=o("button",{className:"cp-button cp-button-delete"},["×"]);return t.addEventListener("click",n),t}function ct(n){return n.replace(/([A-Z])/g," $1").replace(/^./,t=>t.toUpperCase()).trim()}function $(n,t,e){return Math.min(Math.max(n,t),e)}function pt(n,t,e){if(t.length!==e.length)throw new Error("Input and output ranges must have the same length");if(t.length<2)throw new Error("Input and output ranges must have at least two values");let s=0;for(;s<t.length-1&&n>t[s+1];)s++;if(s===t.length-1)return e[e.length-1];if(s===0&&n<t[0])return e[0];const i=t[s],a=t[s+1],r=e[s],l=e[s+1];return(n-i)/(a-i)*(l-r)+r}class H{constructor(){this.source=null,this.stream=null,this.fftSize=2048,this.smoothingTimeConstant=.82,this.spectrumBoost=3,this.levels={volume:0,bass:0,mids:0,highs:0},this.peaks={volume:0,bass:0,mids:0,highs:0},this._isAnalyzing=!1,this.loop=()=>{this._isAnalyzing&&(requestAnimationFrame(this.loop),this.update())};const t=window.AudioContext||window.webkitAudioContext;this.ctx=new t,this.analyser=this.ctx.createAnalyser(),this.analyser.fftSize=this.fftSize,this.analyser.smoothingTimeConstant=this.smoothingTimeConstant,this.dataArray=new Uint8Array(this.analyser.frequencyBinCount),this.waveformArray=new Uint8Array(this.analyser.frequencyBinCount)}setFFTSize(t){this.fftSize=t,this.analyser.fftSize=t,this.dataArray=new Uint8Array(this.analyser.frequencyBinCount),this.waveformArray=new Uint8Array(this.analyser.frequencyBinCount)}async setInput(t){try{let e;t==="browser"?e=navigator.mediaDevices.getDisplayMedia({audio:!0,video:!0}):e=navigator.mediaDevices.getUserMedia({audio:!0});const s=await e;this.ctx.state==="suspended"&&this.ctx.resume(),this.source&&this.source.disconnect(),this.stream&&this.stream.getTracks().forEach(i=>i.stop()),this.stream=s,this.source=this.ctx.createMediaStreamSource(this.stream),this.source.connect(this.analyser),this._isAnalyzing=!0,this.loop()}catch(e){console.error("Error accessing audio input:",e),this._isAnalyzing=!1}}update(){if(this.analyser.getByteFrequencyData(this.dataArray),this.analyser.getByteTimeDomainData(this.waveformArray),this.spectrumBoost!==1){const p=this.dataArray.length;for(let u=0;u<p;u++){const b=1+u/p*(this.spectrumBoost-1);this.dataArray[u]=Math.min(255,this.dataArray[u]*b)}}const t=[2,10],e=[10,150],s=[150,600],i=this.getAverage(t[0],t[1]),a=this.getAverage(e[0],e[1]),r=this.getAverage(s[0],s[1]),l=this.getAverage(0,s[1]);this.processLevel("bass",i),this.processLevel("mids",a),this.processLevel("highs",r),this.processLevel("volume",l)}processLevel(t,e){this.peaks[t]-=5e-4,this.peaks[t]=$(this.peaks[t],.1,1),e>this.peaks[t]&&(this.peaks[t]=e),this.levels[t]=$(pt(e,[0,this.peaks[t]],[0,1]),0,1)}getAverage(t,e){let s=0;const i=e-t;if(i<=0)return 0;for(let a=t;a<e;a++)s+=this.dataArray[a];return s/i/255}getSignal(t){return()=>this.levels[t]}}const E=new H;class U{constructor(){this.midiAccess=null,this.values=new Map,this.isListening=!1,this.resolveListen=null,this.listeningCallback=null,this.init()}async init(){if(typeof navigator<"u"&&navigator.requestMIDIAccess)try{this.midiAccess=await navigator.requestMIDIAccess(),this.setupInputs(),this.midiAccess.onstatechange=t=>{t.port.type==="input"&&t.port.state==="connected"&&this.setupInputs()}}catch(t){console.warn("MIDI Access failed",t)}}setupInputs(){if(!this.midiAccess)return;const t=this.midiAccess.inputs.values();for(const e of t)e.onmidimessage=this.handleMessage.bind(this)}handleMessage(t){const e=t.data,[s]=e;if((s&240)>=240)return;const a=this.getIdFromMessage(t),r=this.normalizeValue(e);this.values.set(a,r),this.isListening&&this.resolveListen&&r>0&&(this.resolveListen(a),this.isListening=!1,this.resolveListen=null,this.listeningCallback&&this.listeningCallback())}getIdFromMessage(t){const e=t.data,[s,i]=e,a=s&240,r=t.currentTarget.name||"unknown",l=a===144||a===128?"note":"ctrl",p=r.replace(/[^a-zA-Z0-9]/g,"");return`${i}_${l}_${p}`}normalizeValue(t){const[e,s,i]=t,a=e&240;return a===144?i>0?1:0:a===128?0:a===176?i/127:0}listen(){return this.isListening=!0,new Promise(t=>{this.resolveListen=t})}cancelListen(){this.isListening=!1,this.resolveListen=null}getSignal(t){return()=>this.values.get(t)??0}}const W=new U;class _{constructor(){this.configs=new Map,this.lastRandomUpdateTime=0,this.currentRandomValue=0,this.startTime=performance.now(),this.configs.set("constant",{frequency:.1,amplitude:1,offset:0,phase:0}),this.configs.set("sine",{frequency:.1,amplitude:1,offset:0,phase:0}),this.configs.set("sawtooth",{frequency:.1,amplitude:1,offset:0,phase:0}),this.configs.set("triangle",{frequency:.1,amplitude:1,offset:0,phase:0}),this.configs.set("square",{frequency:.1,amplitude:1,offset:0,phase:0}),this.configs.set("random",{frequency:10,amplitude:1,offset:0,phase:0})}setConfig(t,e){const s=this.configs.get(t);this.configs.set(t,{...s,...e})}getConfig(t){return{...this.configs.get(t)}}getTime(){return(performance.now()-this.startTime)/1e3}normalizeOutput(t,e){const s=t*e.amplitude+e.offset;return Math.max(0,Math.min(1,s))}constant(t){const e=t?{...this.configs.get("constant"),...t}:this.configs.get("constant"),i=this.getTime()*e.frequency%1;return this.normalizeOutput(i,e)}sine(t){const e=t?{...this.configs.get("sine"),...t}:this.configs.get("sine"),s=this.getTime(),i=e.phase*Math.PI*2,r=(Math.sin(s*e.frequency*Math.PI*2+i)+1)/2;return this.normalizeOutput(r,e)}sawtooth(t){const e=t?{...this.configs.get("sawtooth"),...t}:this.configs.get("sawtooth"),s=this.getTime(),i=e.phase,a=(s*e.frequency+i)%1+i%1;return this.normalizeOutput(a%1,e)}triangle(t){const e=t?{...this.configs.get("triangle"),...t}:this.configs.get("triangle"),s=this.getTime(),i=e.phase,a=(s*e.frequency+i)%1,r=a<.5?a*2:2-a*2;return this.normalizeOutput(r,e)}square(t){const e=t?{...this.configs.get("square"),...t}:this.configs.get("square"),s=this.getTime(),i=e.phase,r=(s*e.frequency+i)%1<.5?0:1;return this.normalizeOutput(r,e)}random(t){const e=t?{...this.configs.get("random"),...t}:this.configs.get("random"),s=performance.now(),i=1e3/e.frequency;return s-this.lastRandomUpdateTime>i&&(this.currentRandomValue=Math.random(),this.lastRandomUpdateTime=s),this.normalizeOutput(this.currentRandomValue,e)}getSignal(t){switch(t){case"constant":return()=>this.constant();case"sine":return()=>this.sine();case"sawtooth":return()=>this.sawtooth();case"triangle":return()=>this.triangle();case"square":return()=>this.square();case"random":return()=>this.random()}}reset(){this.startTime=performance.now(),this.lastRandomUpdateTime=0,this.currentRandomValue=0}}const J=new _,A=class A{constructor(t,e,s={}){this.changeFns=new Set,this.object=t,this.property=e,this.key=s.id??e,this.initialValue=this.object[this.property],this.domElement=o("div",{className:"cp-controller"});const i=s.label??ct(e),a=o("label",{className:"cp-label"},[String(i)]);a.setAttribute("title",String(i)),this.domElement.appendChild(a),s.disabled&&this.domElement.setAttribute("data-disabled","true")}get value(){return this.object[this.property]}setValue(t,e=!0){this.object[this.property]=t,e&&this.emitChange(t),this.updateDisplay()}save(){return this.value}load(t){this.setValue(t)}reset(){this.setValue(this.initialValue)}onChange(t){return this.changeFns.add(t),this}emitChange(t){for(const e of this.changeFns)e(t)}appendWidget(t){this.domElement.appendChild(t)}};A.audio=E,A.midi=W,A.math=J;let d=A;class Y extends d{constructor(t,e,s={}){super(t,e,s),this.input=o("input",{type:"number",className:"cp-input-number",value:String(this.value)}),this.input.addEventListener("input",()=>{}),this.input.addEventListener("blur",()=>{const i=parseFloat(this.input.value);isNaN(i)?this.input.value=String(this.value):this.setValue(i)}),this.input.addEventListener("keydown",i=>{i.key==="Enter"&&this.input.blur()}),this.appendWidget(this.input)}updateDisplay(){this.input.value=String(this.value)}}const X={linear:n=>n,quadIn:n=>n*n,quadOut:n=>n*(2-n),quadInOut:n=>n<.5?2*n*n:-1+(4-2*n)*n,cubicIn:n=>n*n*n,cubicOut:n=>--n*n*n+1,cubicInOut:n=>n<.5?4*n*n*n:(n-1)*(2*n-2)*(2*n-2)+1,expoIn:n=>n===0?0:Math.pow(2,10*(n-1)),expoOut:n=>n===1?1:-Math.pow(2,-10*n)+1,expoInOut:n=>n===0||n===1?n:(n*=2)<1?.5*Math.pow(2,10*(n-1)):.5*(-Math.pow(2,-10*--n)+2),sineIn:n=>1-Math.cos(n*Math.PI/2),sineOut:n=>Math.sin(n*Math.PI/2),sineInOut:n=>-(Math.cos(Math.PI*n)-1)/2};class G{constructor(t){this.rafId=null,this.currentSignalType=null,this.currentMidiId=null,this.currentEase="linear",this.currentBehaviour="forward",this.loop=()=>{if(this.currentSignalType){let e=0;this.currentSignalType==="midi"?this.currentMidiId&&(e=d.midi.getSignal(this.currentMidiId)()):["constant","sine","sawtooth","triangle","square","random"].includes(this.currentSignalType)?e=d.math.getSignal(this.currentSignalType)():["volume","bass","mids","highs"].includes(this.currentSignalType)&&(e=d.audio.getSignal(this.currentSignalType)());const s=X[this.currentEase](e);this.onChange(s,this.currentBehaviour),this.rafId=requestAnimationFrame(this.loop)}},this.onChange=t.onChange,this.setupControllers(t.container)}setupControllers(t){const e=this.createSettingSelect("signal",["none","volume","bass","mids","highs","constant","sine","sawtooth","triangle","square","random","midi"],l=>this.setSignalType(l));this.signalSelect=e.select,t.appendChild(e.row),this.midiRow=o("div",{className:"cp-setting-row",style:"display: none;"});const s=o("label",{className:"cp-setting-label"},["Midi"]);this.midiBtn=o("button",{className:"cp-button cp-input-small"},["Learn"]),this.midiBtn.addEventListener("click",async()=>{if(this.midiBtn.textContent==="Listening..."){d.midi.cancelListen(),this.setMidiId(null);return}this.midiBtn.textContent="Listening...";const l=await d.midi.listen();this.setMidiId(l)}),this.midiRow.appendChild(s),this.midiRow.appendChild(this.midiBtn),t.appendChild(this.midiRow),this.mathParamsContainer=o("div",{style:"display: none; flex-direction: column; gap: 4px;"}),t.appendChild(this.mathParamsContainer);const i=this.createSettingSelect("behaviour",["forward","backward","loopForward","loopBackward","pingpong"],l=>this.setBehaviour(l));this.behaviourRow=i.row,this.behaviourSelect=i.select,this.behaviourRow.style.display="none",this.behaviourSelect.value=this.currentBehaviour,t.appendChild(this.behaviourRow);const a=this.createSettingSelect("ease",Object.keys(X),l=>this.setEase(l));this.easeRow=a.row,this.easeSelect=a.select,this.easeRow.style.display="none",this.easeSelect.value=this.currentEase,t.appendChild(this.easeRow);const r=o("hr",{className:"cp-separator"});t.appendChild(r)}createSettingSelect(t,e,s){const i=o("div",{className:"cp-setting-row"}),a=o("label",{className:"cp-setting-label"},[t]),r=o("select",{className:"cp-select cp-input-small"});return e.forEach(l=>{const p=o("option",{value:l},[l]);r.appendChild(p)}),r.addEventListener("change",()=>s(r.value)),i.appendChild(a),i.appendChild(r),{row:i,select:r}}createNumberInput(t,e,s,i,a,r){const l=o("div",{className:"cp-setting-row"}),p=o("label",{className:"cp-setting-label"},[t]),u=o("input",{className:"cp-input-number cp-input-small",type:"number",value:String(e),min:String(s),max:String(i),step:String(a)});return u.addEventListener("input",()=>{const m=parseFloat(u.value);isNaN(m)||r(m)}),l.appendChild(p),l.appendChild(u),{row:l,input:u}}updateMathParams(t){this.mathParamsContainer.innerHTML="";const e=d.math.getConfig(t);let s="Frequency",i=.1,a=10,r=.1;t==="random"?a=30:t==="constant"&&(s="Speed",i=.01,a=2,r=.01);const l=this.createNumberInput(s,e.frequency,i,a,r,m=>d.math.setConfig(t,{frequency:m}));this.mathParamsContainer.appendChild(l.row);const p=this.createNumberInput("Amplitude",e.amplitude,0,2,.1,m=>d.math.setConfig(t,{amplitude:m}));this.mathParamsContainer.appendChild(p.row);const u=this.createNumberInput("Offset",e.offset,0,1,.1,m=>d.math.setConfig(t,{offset:m}));if(this.mathParamsContainer.appendChild(u.row),["sine","sawtooth","triangle","square"].includes(t)){const m=this.createNumberInput("Phase",e.phase,0,1,.01,b=>d.math.setConfig(t,{phase:b}));this.mathParamsContainer.appendChild(m.row)}}setSignalType(t){if(!t||t==="none")this.currentSignalType=null,this.currentMidiId=null,this.midiRow.style.display="none",this.mathParamsContainer.style.display="none",this.easeRow.style.display="none",this.behaviourRow.style.display="none",this.stop(),this.signalSelect.value!=="none"&&(this.signalSelect.value="none");else{this.currentSignalType=t;const e=t==="midi",s=["constant","sine","sawtooth","triangle","square","random"].includes(t),i=["volume","bass","mids","highs"].includes(t);this.midiRow.style.display=e?"grid":"none",this.mathParamsContainer.style.display=s?"grid":"none",s&&this.updateMathParams(t),this.easeRow.style.display="grid",this.behaviourRow.style.display="grid",i?(this.currentMidiId=null,d.audio.ctx.state==="suspended"&&d.audio.setInput("microphone")):e||(this.currentMidiId=null),this.start(),this.signalSelect.value!==t&&(this.signalSelect.value=t)}}setMidiId(t){this.currentMidiId=t,this.midiBtn.textContent=t??"Learn"}setEase(t){this.currentEase=t,this.easeSelect.value!==t&&(this.easeSelect.value=t)}setBehaviour(t){this.currentBehaviour=t,this.behaviourSelect.value!==t&&(this.behaviourSelect.value=t)}start(){!this.rafId&&this.currentSignalType&&this.loop()}stop(){this.rafId&&(cancelAnimationFrame(this.rafId),this.rafId=null)}save(){return{type:this.currentSignalType,midiId:this.currentMidiId,ease:this.currentEase,behaviour:this.currentBehaviour}}load(t){t&&(this.setSignalType(t.type),this.setMidiId(t.midiId||null),this.setEase(t.ease||"linear"),this.setBehaviour(t.behaviour||"forward"))}reset(){this.setSignalType("none"),this.setEase("linear"),this.setBehaviour("forward"),this.setMidiId(null)}}class Z extends d{constructor(t,e,s={}){super(t,e,s),this.pingPongDirection=1,this.min=0,this.max=100,this.initialOptions=s,this.min=s.min??0,this.max=s.max??100;const i=o("details",{className:"cp-controller-details"}),a=o("summary",{className:"cp-controller-summary"});this.input=o("input",{type:"range",className:"cp-input-range",step:s.step??"any"}),s.min!==void 0&&(this.input.min=String(s.min)),s.max!==void 0&&(this.input.max=String(s.max)),this.input.value=String(this.value),this.display=o("span",{className:"cp-value-display"},[String(this.value.toFixed(1))]),this.input.addEventListener("input",()=>{const y=parseFloat(this.input.value);isNaN(y)||(this.setValue(y),this.display.textContent=String(y.toFixed(1)))}),this.input.addEventListener("click",y=>{y.stopPropagation()});const r=o("div",{className:"cp-controller-summary-content"});r.appendChild(this.input),r.appendChild(this.display),a.appendChild(r),i.appendChild(a);const l=o("div",{className:"cp-number-settings"}),p=this.createSetting("min",s.min,y=>this.setMin(y));this.minInput=p.input,l.appendChild(p.row);const u=this.createSetting("max",s.max,y=>this.setMax(y));this.maxInput=u.input,l.appendChild(u.row);const m=this.createSetting("step",s.step,y=>this.setStep(y));this.stepInput=m.input,l.appendChild(m.row);const b=o("hr",{className:"cp-separator"});l.appendChild(b),this.signalHandler=new G({container:l,onChange:(y,S)=>this.applySignal(y,S)}),i.appendChild(l),this.appendWidget(i)}setMin(t){typeof t=="number"&&(t=String(t)),t===""||isNaN(parseFloat(t))?this.input.removeAttribute("min"):(this.input.min=t,this.min=parseFloat(t)),this.minInput&&this.minInput.value!==t&&(this.minInput.value=t)}setMax(t){typeof t=="number"&&(t=String(t)),t===""||isNaN(parseFloat(t))?this.input.removeAttribute("max"):(this.input.max=t,this.max=parseFloat(t)),this.maxInput&&this.maxInput.value!==t&&(this.maxInput.value=t)}setStep(t){t===void 0&&(t=""),typeof t=="number"&&(t=String(t)),t===""||t==="any"||isNaN(parseFloat(t))?this.input.step="any":this.input.step=t,this.stepInput&&(t==="any"||t===""?this.stepInput.value="":this.stepInput.value!==t&&(this.stepInput.value=t))}applySignal(t,e){const s=this.max-this.min;let i;if(e==="forward")i=this.min+t*s;else if(e==="backward")i=this.max-t*s;else{const a=t*(s*.01);i=this.value,e==="loopForward"?(i+=a,i>this.max&&(i=this.min+(i-this.min)%s)):e==="loopBackward"?(i-=a,i<this.min&&(i=this.max-(this.max-i)%s)):e==="pingpong"&&(i+=a*this.pingPongDirection,i>=this.max?(i=this.max,this.pingPongDirection=-1):i<=this.min&&(i=this.min,this.pingPongDirection=1))}i=this.roundToStep(i),this.setValue(i),this.input.value=String(i),this.display.textContent=String(i.toFixed(1))}roundToStep(t){const e=this.input.step;if(e==="any"||e===""||isNaN(parseFloat(e)))return t;const s=parseFloat(e),i=this.min;return i+Math.round((t-i)/s)*s}createSetting(t,e,s){const i=o("div",{className:"cp-setting-row"}),a=o("label",{className:"cp-setting-label"},[t]),r=o("input",{type:"number",className:"cp-input-number cp-input-small",step:"any"});return e!==void 0&&(r.value=String(e)),r.addEventListener("input",()=>s(r.value)),i.appendChild(a),i.appendChild(r),{row:i,input:r}}updateDisplay(){this.input.value=String(this.value),this.display.textContent=String(this.value.toFixed(1))}save(){return{value:this.value,settings:{min:this.min,max:this.max,step:this.input.step,signal:this.signalHandler.save()}}}load(t){if(typeof t=="number")this.setValue(t),this.resetSettings();else if(typeof t=="object"&&t!==null&&"value"in t){const e=t.settings||{};e.min!==void 0?this.setMin(e.min):this.setMin(this.initialOptions.min!==void 0?this.initialOptions.min:""),e.max!==void 0?this.setMax(e.max):this.setMax(this.initialOptions.max!==void 0?this.initialOptions.max:""),e.step!==void 0?this.setStep(e.step):this.setStep(this.initialOptions.step);let s=t.value;!isNaN(this.min)&&s<this.min&&(s=this.min),!isNaN(this.max)&&s>this.max&&(s=this.max),this.setValue(s),this.signalHandler?.load(e.signal)}}reset(){this.setValue(this.initialValue),this.resetSettings()}resetSettings(){this.setMin(this.initialOptions.min!==void 0?this.initialOptions.min:""),this.setMax(this.initialOptions.max!==void 0?this.initialOptions.max:""),this.setStep(this.initialOptions.step),this.signalHandler?.reset()}}class K extends d{constructor(t,e,s){super(t,e,s),this.optionValues=[],this.select=o("select",{className:"cp-select"}),this.optionValues=s.options||[],this.optionValues.forEach((i,a)=>{const r=o("option",{value:String(a)},[String(i)]);this.select.appendChild(r)}),this.updateDisplay(),this.select.addEventListener("change",()=>{const i=parseInt(this.select.value),a=this.optionValues[i];this.setValue(a)}),this.appendWidget(this.select)}setOptions(t){this.select.innerHTML="",this.optionValues=t,this.optionValues.forEach((e,s)=>{const i=o("option",{value:String(s)},[String(e)]);this.select.appendChild(i)}),this.updateDisplay(),this.select.value===""&&this.optionValues.length>0&&this.setValue(this.optionValues[0])}updateDisplay(){const t=this.optionValues.indexOf(this.value);t!==-1&&(this.select.value=String(t))}}class Q extends d{constructor(t,e,s={}){const i={action:e};super(i,"action",s),this.domElement.querySelector(".cp-label")?.remove();const a=s.label??t;this.button=o("button",{className:"cp-button"},[String(a)]),this.button.addEventListener("click",()=>{const r=this.value;typeof r=="function"&&r(),this.emitChange(r)}),this.appendWidget(this.button)}updateDisplay(){}}class tt extends d{constructor(t,e,s={}){super(t,e,s),this.input=o("input",{type:"checkbox",className:"cp-checkbox"}),this.input.checked=this.value,this.input.addEventListener("change",()=>{this.setValue(this.input.checked)}),this.appendWidget(this.input)}updateDisplay(){this.input.checked=this.value}}class et extends d{constructor(t,e,s){super(t,e,s),this.buttons=[],this.optionValues=[],this.container=o("div",{className:"cp-radios"}),this.optionValues=s.options||[],this.optionValues.forEach(i=>{const a=o("button",{className:"cp-button cp-radio"},[String(i)]);a.addEventListener("click",()=>{this.setValue(i)}),this.container.appendChild(a),this.buttons.push(a)}),this.updateDisplay(),this.appendWidget(this.container)}updateDisplay(){const t=this.value;this.buttons.forEach((e,s)=>{this.optionValues[s]===t?e.setAttribute("data-active","true"):e.removeAttribute("data-active")})}}class st extends d{constructor(t,e,s={}){super(t,e,s),this.input=o("input",{type:"color",className:"cp-input-color",value:this.value||"#000000"}),this.appendWidget(this.input),this.input.addEventListener("input",i=>{const a=i.target;this.setValue(a.value)}),this.updateDisplay()}updateDisplay(){this.input.value=this.value}}function it(n){const t=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;n=n.replace(t,(s,i,a,r)=>i+i+a+a+r+r);const e=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(n);return e?[parseInt(e[1],16),parseInt(e[2],16),parseInt(e[3],16)]:[0,0,0]}function ht(n,t,e){return"#"+((1<<24)+(Math.round(n)<<16)+(Math.round(t)<<8)+Math.round(e)).toString(16).slice(1)}function N(n){const t=n/255;return t<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function F(n){return n<=.0031308?n*12.92*255:(1.055*Math.pow(n,1/2.4)-.055)*255}function dt(n,t,e){const[s,i,a]=it(n),[r,l,p]=it(t),u=N(s),m=N(i),b=N(a),y=N(r),S=N(l),k=N(p),f=u+e*(y-u),B=m+e*(S-m),x=b+e*(k-b),c=F(f),g=F(B),v=F(x);return ht(c,g,v)}class nt extends d{constructor(t,e,s={}){super(t,e,s),this.stops=[],this.pingPongDirection=1,this.animationT=0,this.manualPosition=0,this.initialOptions=s,this.stops=s.stops||[{color:"#000000",position:0},{color:"#ffffff",position:1}],this.sortStops();const i=o("details",{className:"cp-controller-details"}),a=o("summary",{className:"cp-controller-summary"}),r=o("div",{className:"cp-controller-summary-content"});this.displayText=o("span",{className:"cp-value-display"},[String(this.value)]),r.appendChild(this.displayText),a.appendChild(r),i.appendChild(a);const l=o("div",{className:"cp-number-settings"});this.stopsContainer=o("div",{className:"cp-stops-container"}),this.renderStops(),l.appendChild(this.stopsContainer);const p=o("button",{className:"cp-button"},["+ Add Stop"]);p.addEventListener("click",()=>{this.stops.push({color:"#ffffff",position:.5}),this.sortStops(),this.renderStops(),this.updateOutput()}),l.appendChild(p);const u=o("hr",{className:"cp-separator"});l.appendChild(u),this.signalHandler=new G({container:l,onChange:(m,b)=>this.applySignal(m,b)}),i.appendChild(l),this.appendWidget(i),this.updateOutput(0)}sortStops(){this.stops.sort((t,e)=>t.position-e.position)}renderStops(){this.stopsContainer.innerHTML="",this.stops.forEach((t,e)=>{const s=o("div",{className:"cp-gradient-stop-row"}),i=o("input",{type:"color",className:"cp-input-color",value:t.color});i.addEventListener("input",l=>{t.color=l.target.value,this.updateOutput()});const a=o("input",{type:"number",className:"cp-input-number cp-input-small",min:"0",max:"1",step:"0.01",value:String(t.position)});a.addEventListener("change",l=>{let p=parseFloat(l.target.value);isNaN(p)&&(p=0),t.position=Math.max(0,Math.min(1,p)),this.sortStops(),this.renderStops(),this.updateOutput()});const r=j(()=>{this.stops.splice(e,1),this.renderStops(),this.updateOutput()});s.appendChild(i),s.appendChild(a),s.appendChild(r),this.stopsContainer.appendChild(s)})}updateOutput(t=this.manualPosition){if(this.stops.length===0)return;if(this.stops.length===1){this.setValue(this.stops[0].color),this.updateDisplay();return}let e="#000000";if(t=Math.max(0,Math.min(1,t)),t<=this.stops[0].position)e=this.stops[0].color;else if(t>=this.stops[this.stops.length-1].position)e=this.stops[this.stops.length-1].color;else for(let s=0;s<this.stops.length-1;s++){const i=this.stops[s],a=this.stops[s+1];if(t>=i.position&&t<=a.position){const r=a.position-i.position,l=r===0?0:(t-i.position)/r;e=dt(i.color,a.color,l);break}}this.setValue(e),this.updateDisplay()}updateDisplay(){this.displayText&&(this.displayText.textContent=this.value)}applySignal(t,e){let s=t;if(e==="forward")s=t;else if(e==="backward")s=1-t;else{const i=t*.05;e==="loopForward"?(this.animationT=(this.animationT+i)%1,s=this.animationT):e==="loopBackward"?(this.animationT=(this.animationT-i+1)%1,s=this.animationT):e==="pingpong"&&(this.animationT+=i*this.pingPongDirection,this.animationT>=1?(this.animationT=1,this.pingPongDirection=-1):this.animationT<=0&&(this.animationT=0,this.pingPongDirection=1),s=this.animationT)}this.updateOutput(s),this.manualPosition=s}save(){return{stops:this.stops,settings:{signal:this.signalHandler.save()}}}load(t){t&&t.stops&&(this.stops=t.stops,this.sortStops(),this.renderStops()),t&&t.settings&&this.signalHandler?.load(t.settings.signal)}reset(){this.stops=this.initialOptions.stops||[{color:"#000000",position:0},{color:"#ffffff",position:1}],this.sortStops(),this.renderStops(),this.signalHandler?.reset(),this.updateOutput(0)}}class at extends d{constructor(t,e,s={}){super(t,e,s),this.items=[],this.initialOptions=s,this.itemType=s.itemType||"string",this.items=this.parseValue(this.value);const i=o("details",{className:"cp-controller-details"}),a=o("summary",{className:"cp-controller-summary"}),r=o("div",{className:"cp-controller-summary-content"}),l=o("span",{className:"cp-value-display"},[`${this.items.length} items`]);r.appendChild(l),a.appendChild(r),i.appendChild(a);const p=o("div",{className:"cp-number-settings"});this.itemsContainer=o("div",{className:"cp-stops-container"}),this.renderItems(),p.appendChild(this.itemsContainer);const u=o("button",{className:"cp-button cp-input-small",style:"margin-top: 8px; width: 100%;"},["+ Add Item"]);u.addEventListener("click",()=>{this.addItem()}),p.appendChild(u),i.appendChild(p),this.appendWidget(i)}parseValue(t){return!t||t.trim()===""?[]:t.split(",").map(e=>e.trim())}serializeValue(){return this.items.join(",")}getDefaultItemValue(){switch(this.itemType){case"color":return"#ffffff";case"number":return"0";default:return""}}addItem(t){const e=t!==void 0?t:this.getDefaultItemValue();this.items.push(e),this.renderItems(),this.updateValue()}updateValue(){const t=this.serializeValue();this.setValue(t),this.updateSummary()}updateSummary(){const t=this.domElement.querySelector(".cp-value-display");t&&(t.textContent=`${this.items.length} items`)}renderItems(){this.itemsContainer.innerHTML="",this.items.forEach((t,e)=>{const s=o("div",{className:"cp-array-row"});let i;this.itemType==="color"?i=o("input",{type:"color",className:"cp-input-color",value:t}):this.itemType==="number"?i=o("input",{type:"number",className:"cp-input-number cp-input-small",step:"any",value:t}):i=o("input",{type:"text",className:"cp-input-number cp-input-small",value:t}),i.addEventListener("input",r=>{this.items[e]=r.target.value,this.updateValue()});const a=j(()=>{this.items.splice(e,1),this.renderItems(),this.updateValue()});s.appendChild(i),s.appendChild(a),this.itemsContainer.appendChild(s)})}updateDisplay(){}save(){return[...this.items]}load(t){Array.isArray(t)?this.items=[...t]:typeof t=="string"&&(this.items=this.parseValue(t)),this.renderItems(),this.updateValue()}reset(){const t=this.initialValue||"";this.items=this.parseValue(t),this.renderItems(),this.updateValue()}}class ut{constructor(){this.frames=0,this.pollingInterval=1e3,this.prevTime=performance.now(),this.render=()=>{this.frames++;const t=performance.now();if(t>=this.prevTime+this.pollingInterval){const e=Math.round(this.frames*1e3/(t-this.prevTime));let s="";const i=performance.memory;i&&(s=` / ${Math.round(i.usedJSHeapSize/1048576)}MB`),this.domElement.textContent=`${e} FPS${s}`,this.prevTime=t,this.frames=0}this.rafId=requestAnimationFrame(this.render)},this.domElement=o("span",{className:"cp-stats"}),this.rafId=requestAnimationFrame(this.render)}destroy(){cancelAnimationFrame(this.rafId)}}class D{constructor(){this.controllers=[],this.folders=[]}addNumber(t,e,s={}){const i=new Y(t,e,s);return this.contentElement.appendChild(i.domElement),this.controllers.push(i),i}addRange(t,e,s={}){const i=new Z(t,e,s);return this.contentElement.appendChild(i.domElement),this.controllers.push(i),i}addSelect(t,e,s={}){const i=new K(t,e,s);return this.contentElement.appendChild(i.domElement),this.controllers.push(i),i}addBoolean(t,e,s={}){const i=new tt(t,e,s);return this.contentElement.appendChild(i.domElement),this.controllers.push(i),i}addButton(t,e,s={}){const i=new Q(t,e,s);return this.contentElement.appendChild(i.domElement),this.controllers.push(i),i}addRadio(t,e,s={}){const i=new et(t,e,s);return this.contentElement.appendChild(i.domElement),this.controllers.push(i),i}addColor(t,e,s={}){const i=new st(t,e,s);return this.contentElement.appendChild(i.domElement),this.controllers.push(i),i}addGradient(t,e,s={}){const i=new nt(t,e,s);return this.contentElement.appendChild(i.domElement),this.controllers.push(i),i}addArray(t,e,s={}){const i=new at(t,e,s);return this.contentElement.appendChild(i.domElement),this.controllers.push(i),i}addFolder(t){const e=new ot(t);return this.addSeparator(),this.contentElement.appendChild(e.domElement),this.folders.push(e),e}addSeparator(){const t=o("hr",{className:"cp-separator"});this.contentElement.appendChild(t)}save(){const t={controllers:{},folders:{}};for(const e of this.controllers)typeof e.value!="function"&&(t.controllers[e.key]=e.save());for(const e of this.folders)t.folders[e.title]=e.save();return t}load(t){if(!t){this.reset();return}for(const e of this.controllers)if(typeof e.value!="function")if(t.controllers&&e.key in t.controllers){const s=t.controllers[e.key];s!==void 0&&e.load(s)}else e.reset();for(const e of this.folders){const s=t.folders?t.folders[e.title]:void 0;e.load(s)}}reset(){for(const t of this.controllers)typeof t.value!="function"&&t.reset();for(const t of this.folders)t.reset()}}class ot extends D{constructor(t){super(),this.title=t,this.domElement=o("details",{className:"cp-folder",open:!0}),this.summaryElement=o("summary",{className:"cp-summary"},[t]),this.domElement.appendChild(this.summaryElement),this.contentElement=o("div",{className:"cp-content cp-folder-content"}),this.domElement.appendChild(this.contentElement)}}class mt extends D{constructor(t,e={}){super(),lt(),this.domElement=o("details",{className:"cp-root",open:!0}),this.summaryElement=o("summary",{className:"cp-summary cp-summary-root"}),this.domElement.appendChild(this.summaryElement);const s=o("span",{},[e.title||"ControlPanel"]);this.summaryElement.appendChild(s),this.stats=new ut,this.summaryElement.appendChild(this.stats.domElement);let i=!1,a=0,r=0,l=0,p=0;this.summaryElement.addEventListener("mousedown",c=>{if(c.target!==this.summaryElement&&c.target!==s)return;i=!0,a=c.clientX,r=c.clientY;const g=this.domElement.getBoundingClientRect();l=g.left,p=g.top,c.preventDefault()}),document.addEventListener("mousemove",c=>{if(!i)return;const g=c.clientX-a,v=c.clientY-r,w=l+g,z=p+v;this.domElement.style.left=`${w}px`,this.domElement.style.top=`${z}px`,this.domElement.style.right="auto",this.domElement.style.bottom="auto"}),document.addEventListener("mouseup",()=>{i&&(i=!1,this.savePositionAndSize())}),new ResizeObserver(()=>{i||this.savePositionAndSize()}).observe(this.domElement),this.restorePositionAndSize(),this.contentElement=o("div",{className:"cp-content"}),this.domElement.appendChild(this.contentElement);const m=this.addFolder("_Signals"),b={audioInput:null,fftSize:2048};m.addRadio(b,"audioInput",{label:"Audio Signal",options:["microphone","browser"]}).onChange(c=>{E.setInput(c)}),m.addSelect(b,"fftSize",{label:"FFT Size",options:[256,512,1024,2048]}).onChange(c=>{E.setFFTSize(c)}),m.addRange(E,"smoothingTimeConstant",{min:0,max:.99,step:.01,label:"Smoothing"}).onChange(c=>{E.analyser.smoothingTimeConstant=c}),m.addRange(E,"spectrumBoost",{min:1,max:5,step:.1,label:"Compression"}),t?t.appendChild(this.domElement):document.body.appendChild(this.domElement);const y=e.title||"ControlPanel";this.presetStoragePrefix=`cp-presets-${y}-`;const S=this.addFolder("_User Presets"),k=()=>{const c=["Default"];if(typeof localStorage>"u")return c;for(let g=0;g<localStorage.length;g++){const v=localStorage.key(g);if(v&&v.startsWith(this.presetStoragePrefix)){const w=v.substring(this.presetStoragePrefix.length);w!=="Default"&&!c.includes(w)&&c.push(w)}}return c.sort()},f={selected:"Default",save:()=>{const c=prompt("Preset Name:",f.selected);if(c){if(c==="Default"){alert("Cannot overwrite Default preset");return}const g=this.presetStoragePrefix+c;this.saveToLocalStorage(g);const v=k();x.setOptions(v),f.selected=c,x.setValue(c)}},load:()=>{const c=f.selected,g=this.presetStoragePrefix+c;this.loadFromLocalStorage(g),f.selected=c,x.setValue(c)},delete:()=>{if(f.selected==="Default"){alert("Cannot delete Default preset");return}if(confirm(`Delete preset "${f.selected}"?`)){const c=this.presetStoragePrefix+f.selected;localStorage.removeItem(c);const g=k();x.setOptions(g),f.selected="Default",x.setValue("Default"),this.reset()}},export:()=>{const c=this.save(),g=O=>{const P={controllers:{},folders:{}};for(const[V,q]of Object.entries(O.controllers))V.startsWith("_")||(P.controllers[V]=q);for(const[V,q]of Object.entries(O.folders))V.startsWith("_")||(P.folders[V]=g(q));return P},v=g(c),w={_presetName:f.selected||"CustomPreset",_exportDate:new Date().toISOString(),_instructions:"To add as factory preset: Copy 'controllers' and 'folders' fields into the presets.json file",...v},z=JSON.stringify(w,null,2),I=new Blob([z],{type:"application/json"}),T=URL.createObjectURL(I),C=document.createElement("a");C.href=T;const M=new Date().toISOString().split("T")[0],rt=f.selected.replace(/[^a-z0-9]/gi,"-").toLowerCase();C.download=`${y.toLowerCase()}-preset-${rt}-${M}.json`,document.body.appendChild(C),C.click(),document.body.removeChild(C),URL.revokeObjectURL(T)},import:()=>{const c=document.createElement("input");c.type="file",c.accept=".json",c.onchange=g=>{const v=g.target.files?.[0];if(!v)return;const w=new FileReader;w.onload=z=>{try{const I=z.target?.result,T=JSON.parse(I),C={controllers:T.controllers||{},folders:T.folders||{}};if(!C.controllers||!C.folders){alert("Invalid preset file: missing 'controllers' or 'folders'");return}this.load(C);const M=T._presetName||"ImportedPreset";if(confirm(`Preset loaded! Save as "${M}" to User Presets?`)){const O=this.presetStoragePrefix+M;this.saveToLocalStorage(O);const P=k();x.setOptions(P),f.selected=M,x.setValue(M)}}catch(I){alert(`Failed to import preset: ${I instanceof Error?I.message:"Invalid JSON"}`),console.error("Import error:",I)}},w.readAsText(v)},c.click()}},B=k(),x=S.addSelect(f,"selected",{label:"Preset",options:B});S.addButton("Load",()=>f.load()),S.addButton("Save",()=>f.save()),S.addButton("Delete",()=>f.delete()),S.addButton("Export",()=>f.export()),S.addButton("Import",()=>f.import())}saveToLocalStorage(t){const e=this.save();try{localStorage.setItem(t,JSON.stringify(e))}catch(s){console.warn("ControlPanel: Failed to save to localStorage",s)}}loadFromLocalStorage(t){try{const e=localStorage.getItem(t);if(e){const s=JSON.parse(e);this.load(s)}}catch(e){console.warn("ControlPanel: Failed to load from localStorage",e)}}saveDefaultPreset(){const t=this.presetStoragePrefix+"Default";this.save(),this.saveToLocalStorage(t)}savePositionAndSize(){const t=this.domElement.getBoundingClientRect(),e=`cp-position-${this.presetStoragePrefix}`,s={left:t.left,top:t.top,width:this.domElement.offsetWidth,height:this.domElement.offsetHeight};try{sessionStorage.setItem(e,JSON.stringify(s))}catch(i){console.warn("Failed to save panel position/size",i)}}restorePositionAndSize(){const t=`cp-position-${this.presetStoragePrefix}`;try{const e=sessionStorage.getItem(t);if(e){const s=JSON.parse(e);this.domElement.style.left=`${s.left}px`,this.domElement.style.top=`${s.top}px`,this.domElement.style.right="auto",this.domElement.style.bottom="auto",this.domElement.style.width=`${s.width}px`,this.domElement.style.height=`${s.height}px`}}catch(e){console.warn("Failed to restore panel position/size",e)}}destroy(){this.stats.destroy(),this.domElement.remove(),this.controllers=[],this.folders=[]}}h.ArrayController=at,h.AudioSignals=H,h.BooleanController=tt,h.ButtonController=Q,h.ColorController=st,h.ControlPanel=mt,h.ControlPanelContainer=D,h.Controller=d,h.Folder=ot,h.GradientController=nt,h.MathSignals=_,h.MidiSignals=U,h.NumberController=Y,h.RadioController=et,h.RangeController=Z,h.SelectController=K,h.audioSignals=E,h.mathSignals=J,h.midiSignals=W,Object.defineProperty(h,Symbol.toStringTag,{value:"Module"})}));
|
|
395
|
+
`;let R=!1;function lt(){if(R)return;const n=document.createElement("style");n.id="control-panel-styles",n.textContent=L,document.head.appendChild(n),R=!0}function o(n,t={},e=[]){const s=document.createElement(n);for(const[i,a]of Object.entries(t))i==="className"?s.className=String(a):i==="style"&&typeof a=="object"?Object.assign(s.style,a):i==="open"&&typeof a=="boolean"?a?s.setAttribute("open",""):s.removeAttribute("open"):typeof a!="object"&&s.setAttribute(i,String(a));for(const i of e)typeof i=="string"?s.appendChild(document.createTextNode(i)):s.appendChild(i);return s}function j(n){const t=o("button",{className:"cp-button cp-button-delete"},["×"]);return t.addEventListener("click",n),t}function ct(n){return n.replace(/([A-Z])/g," $1").replace(/^./,t=>t.toUpperCase()).trim()}function $(n,t,e){return Math.min(Math.max(n,t),e)}function pt(n,t,e){if(t.length!==e.length)throw new Error("Input and output ranges must have the same length");if(t.length<2)throw new Error("Input and output ranges must have at least two values");let s=0;for(;s<t.length-1&&n>t[s+1];)s++;if(s===t.length-1)return e[e.length-1];if(s===0&&n<t[0])return e[0];const i=t[s],a=t[s+1],r=e[s],l=e[s+1];return(n-i)/(a-i)*(l-r)+r}class H{constructor(){this.source=null,this.stream=null,this.fftSize=2048,this.smoothingTimeConstant=.82,this.spectrumBoost=3,this.levels={volume:0,bass:0,mids:0,highs:0},this.peaks={volume:0,bass:0,mids:0,highs:0},this._isAnalyzing=!1,this.loop=()=>{this._isAnalyzing&&(requestAnimationFrame(this.loop),this.update())};const t=window.AudioContext||window.webkitAudioContext;this.ctx=new t,this.analyser=this.ctx.createAnalyser(),this.analyser.fftSize=this.fftSize,this.analyser.smoothingTimeConstant=this.smoothingTimeConstant,this.dataArray=new Uint8Array(this.analyser.frequencyBinCount),this.waveformArray=new Uint8Array(this.analyser.frequencyBinCount)}setFFTSize(t){this.fftSize=t,this.analyser.fftSize=t,this.dataArray=new Uint8Array(this.analyser.frequencyBinCount),this.waveformArray=new Uint8Array(this.analyser.frequencyBinCount)}async setInput(t){try{let e;t==="browser"?e=navigator.mediaDevices.getDisplayMedia({audio:!0,video:!0}):e=navigator.mediaDevices.getUserMedia({audio:!0});const s=await e;this.ctx.state==="suspended"&&this.ctx.resume(),this.source&&this.source.disconnect(),this.stream&&this.stream.getTracks().forEach(i=>i.stop()),this.stream=s,this.source=this.ctx.createMediaStreamSource(this.stream),this.source.connect(this.analyser),this._isAnalyzing=!0,this.loop()}catch(e){console.error("Error accessing audio input:",e),this._isAnalyzing=!1}}update(){if(this.analyser.getByteFrequencyData(this.dataArray),this.analyser.getByteTimeDomainData(this.waveformArray),this.spectrumBoost!==1){const p=this.dataArray.length;for(let u=0;u<p;u++){const b=1+u/p*(this.spectrumBoost-1);this.dataArray[u]=Math.min(255,this.dataArray[u]*b)}}const t=[2,10],e=[10,150],s=[150,600],i=this.getAverage(t[0],t[1]),a=this.getAverage(e[0],e[1]),r=this.getAverage(s[0],s[1]),l=this.getAverage(0,s[1]);this.processLevel("bass",i),this.processLevel("mids",a),this.processLevel("highs",r),this.processLevel("volume",l)}processLevel(t,e){this.peaks[t]-=5e-4,this.peaks[t]=$(this.peaks[t],.1,1),e>this.peaks[t]&&(this.peaks[t]=e),this.levels[t]=$(pt(e,[0,this.peaks[t]],[0,1]),0,1)}getAverage(t,e){let s=0;const i=e-t;if(i<=0)return 0;for(let a=t;a<e;a++)s+=this.dataArray[a];return s/i/255}getSignal(t){return()=>this.levels[t]}}const E=new H;class U{constructor(){this.midiAccess=null,this.values=new Map,this.isListening=!1,this.resolveListen=null,this.listeningCallback=null,this.init()}async init(){if(typeof navigator<"u"&&navigator.requestMIDIAccess)try{this.midiAccess=await navigator.requestMIDIAccess(),this.setupInputs(),this.midiAccess.onstatechange=t=>{t.port.type==="input"&&t.port.state==="connected"&&this.setupInputs()}}catch(t){console.warn("MIDI Access failed",t)}}setupInputs(){if(!this.midiAccess)return;const t=this.midiAccess.inputs.values();for(const e of t)e.onmidimessage=this.handleMessage.bind(this)}handleMessage(t){const e=t.data,[s]=e;if((s&240)>=240)return;const a=this.getIdFromMessage(t),r=this.normalizeValue(e);this.values.set(a,r),this.isListening&&this.resolveListen&&r>0&&(this.resolveListen(a),this.isListening=!1,this.resolveListen=null,this.listeningCallback&&this.listeningCallback())}getIdFromMessage(t){const e=t.data,[s,i]=e,a=s&240,r=t.currentTarget.name||"unknown",l=a===144||a===128?"note":"ctrl",p=r.replace(/[^a-zA-Z0-9]/g,"");return`${i}_${l}_${p}`}normalizeValue(t){const[e,s,i]=t,a=e&240;return a===144?i>0?1:0:a===128?0:a===176?i/127:0}listen(){return this.isListening=!0,new Promise(t=>{this.resolveListen=t})}cancelListen(){this.isListening=!1,this.resolveListen=null}getSignal(t){return()=>this.values.get(t)??0}}const W=new U;class _{constructor(){this.configs=new Map,this.lastRandomUpdateTime=0,this.currentRandomValue=0,this.startTime=performance.now(),this.configs.set("constant",{frequency:.1,amplitude:1,offset:0,phase:0}),this.configs.set("sine",{frequency:.1,amplitude:1,offset:0,phase:0}),this.configs.set("sawtooth",{frequency:.1,amplitude:1,offset:0,phase:0}),this.configs.set("triangle",{frequency:.1,amplitude:1,offset:0,phase:0}),this.configs.set("square",{frequency:.1,amplitude:1,offset:0,phase:0}),this.configs.set("random",{frequency:10,amplitude:1,offset:0,phase:0})}setConfig(t,e){const s=this.configs.get(t);this.configs.set(t,{...s,...e})}getConfig(t){return{...this.configs.get(t)}}getTime(){return(performance.now()-this.startTime)/1e3}normalizeOutput(t,e){const s=t*e.amplitude+e.offset;return Math.max(0,Math.min(1,s))}constant(t){const e=t?{...this.configs.get("constant"),...t}:this.configs.get("constant"),i=this.getTime()*e.frequency%1;return this.normalizeOutput(i,e)}sine(t){const e=t?{...this.configs.get("sine"),...t}:this.configs.get("sine"),s=this.getTime(),i=e.phase*Math.PI*2,r=(Math.sin(s*e.frequency*Math.PI*2+i)+1)/2;return this.normalizeOutput(r,e)}sawtooth(t){const e=t?{...this.configs.get("sawtooth"),...t}:this.configs.get("sawtooth"),s=this.getTime(),i=e.phase,a=(s*e.frequency+i)%1+i%1;return this.normalizeOutput(a%1,e)}triangle(t){const e=t?{...this.configs.get("triangle"),...t}:this.configs.get("triangle"),s=this.getTime(),i=e.phase,a=(s*e.frequency+i)%1,r=a<.5?a*2:2-a*2;return this.normalizeOutput(r,e)}square(t){const e=t?{...this.configs.get("square"),...t}:this.configs.get("square"),s=this.getTime(),i=e.phase,r=(s*e.frequency+i)%1<.5?0:1;return this.normalizeOutput(r,e)}random(t){const e=t?{...this.configs.get("random"),...t}:this.configs.get("random"),s=performance.now(),i=1e3/e.frequency;return s-this.lastRandomUpdateTime>i&&(this.currentRandomValue=Math.random(),this.lastRandomUpdateTime=s),this.normalizeOutput(this.currentRandomValue,e)}getSignal(t){switch(t){case"constant":return()=>this.constant();case"sine":return()=>this.sine();case"sawtooth":return()=>this.sawtooth();case"triangle":return()=>this.triangle();case"square":return()=>this.square();case"random":return()=>this.random()}}reset(){this.startTime=performance.now(),this.lastRandomUpdateTime=0,this.currentRandomValue=0}}const J=new _,z=class z{constructor(t,e,s={}){this.changeFns=new Set,this.object=t,this.property=e,this.key=s.id??e,this.initialValue=this.object[this.property],this.domElement=o("div",{className:"cp-controller"});const i=s.label??ct(e),a=o("label",{className:"cp-label"},[String(i)]);a.setAttribute("title",String(i)),this.domElement.appendChild(a),s.disabled&&this.domElement.setAttribute("data-disabled","true")}get value(){return this.object[this.property]}setValue(t,e=!0){this.object[this.property]=t,e&&this.emitChange(t),this.updateDisplay()}save(){return this.value}load(t){this.setValue(t)}reset(){this.setValue(this.initialValue)}onChange(t){return this.changeFns.add(t),this}emitChange(t){for(const e of this.changeFns)e(t)}appendWidget(t){this.domElement.appendChild(t)}};z.audio=E,z.midi=W,z.math=J;let d=z;class Y extends d{constructor(t,e,s={}){super(t,e,s),this.input=o("input",{type:"number",className:"cp-input-number",value:String(this.value)}),this.input.addEventListener("input",()=>{}),this.input.addEventListener("blur",()=>{const i=parseFloat(this.input.value);isNaN(i)?this.input.value=String(this.value):this.setValue(i)}),this.input.addEventListener("keydown",i=>{i.key==="Enter"&&this.input.blur()}),this.appendWidget(this.input)}updateDisplay(){this.input.value=String(this.value)}}const X={linear:n=>n,quadIn:n=>n*n,quadOut:n=>n*(2-n),quadInOut:n=>n<.5?2*n*n:-1+(4-2*n)*n,cubicIn:n=>n*n*n,cubicOut:n=>--n*n*n+1,cubicInOut:n=>n<.5?4*n*n*n:(n-1)*(2*n-2)*(2*n-2)+1,expoIn:n=>n===0?0:Math.pow(2,10*(n-1)),expoOut:n=>n===1?1:-Math.pow(2,-10*n)+1,expoInOut:n=>n===0||n===1?n:(n*=2)<1?.5*Math.pow(2,10*(n-1)):.5*(-Math.pow(2,-10*--n)+2),sineIn:n=>1-Math.cos(n*Math.PI/2),sineOut:n=>Math.sin(n*Math.PI/2),sineInOut:n=>-(Math.cos(Math.PI*n)-1)/2};class G{constructor(t){this.rafId=null,this.currentSignalType=null,this.currentMidiId=null,this.currentEase="linear",this.currentBehaviour="forward",this.loop=()=>{if(this.currentSignalType){let e=0;this.currentSignalType==="midi"?this.currentMidiId&&(e=d.midi.getSignal(this.currentMidiId)()):["constant","sine","sawtooth","triangle","square","random"].includes(this.currentSignalType)?e=d.math.getSignal(this.currentSignalType)():["volume","bass","mids","highs"].includes(this.currentSignalType)&&(e=d.audio.getSignal(this.currentSignalType)());const s=X[this.currentEase](e);this.onChange(s,this.currentBehaviour),this.rafId=requestAnimationFrame(this.loop)}},this.onChange=t.onChange,this.setupControllers(t.container)}setupControllers(t){const e=this.createSettingSelect("signal",["none","volume","bass","mids","highs","constant","sine","sawtooth","triangle","square","random","midi"],l=>this.setSignalType(l));this.signalSelect=e.select,t.appendChild(e.row),this.midiRow=o("div",{className:"cp-setting-row",style:"display: none;"});const s=o("label",{className:"cp-setting-label"},["Midi"]);this.midiBtn=o("button",{className:"cp-button cp-input-small"},["Learn"]),this.midiBtn.addEventListener("click",async()=>{if(this.midiBtn.textContent==="Listening..."){d.midi.cancelListen(),this.setMidiId(null);return}this.midiBtn.textContent="Listening...";const l=await d.midi.listen();this.setMidiId(l)}),this.midiRow.appendChild(s),this.midiRow.appendChild(this.midiBtn),t.appendChild(this.midiRow),this.mathParamsContainer=o("div",{style:"display: none; flex-direction: column; gap: 4px;"}),t.appendChild(this.mathParamsContainer);const i=this.createSettingSelect("behaviour",["forward","backward","loopForward","loopBackward","pingpong"],l=>this.setBehaviour(l));this.behaviourRow=i.row,this.behaviourSelect=i.select,this.behaviourRow.style.display="none",this.behaviourSelect.value=this.currentBehaviour,t.appendChild(this.behaviourRow);const a=this.createSettingSelect("ease",Object.keys(X),l=>this.setEase(l));this.easeRow=a.row,this.easeSelect=a.select,this.easeRow.style.display="none",this.easeSelect.value=this.currentEase,t.appendChild(this.easeRow);const r=o("hr",{className:"cp-separator"});t.appendChild(r)}createSettingSelect(t,e,s){const i=o("div",{className:"cp-setting-row"}),a=o("label",{className:"cp-setting-label"},[t]),r=o("select",{className:"cp-select cp-input-small"});return e.forEach(l=>{const p=o("option",{value:l},[l]);r.appendChild(p)}),r.addEventListener("change",()=>s(r.value)),i.appendChild(a),i.appendChild(r),{row:i,select:r}}createNumberInput(t,e,s,i,a,r){const l=o("div",{className:"cp-setting-row"}),p=o("label",{className:"cp-setting-label"},[t]),u=o("input",{className:"cp-input-number cp-input-small",type:"number",value:String(e),min:String(s),max:String(i),step:String(a)});return u.addEventListener("input",()=>{const m=parseFloat(u.value);isNaN(m)||r(m)}),l.appendChild(p),l.appendChild(u),{row:l,input:u}}updateMathParams(t){this.mathParamsContainer.innerHTML="";const e=d.math.getConfig(t);let s="Frequency",i=.1,a=10,r=.1;t==="random"?a=30:t==="constant"&&(s="Speed",i=.01,a=2,r=.01);const l=this.createNumberInput(s,e.frequency,i,a,r,m=>d.math.setConfig(t,{frequency:m}));this.mathParamsContainer.appendChild(l.row);const p=this.createNumberInput("Amplitude",e.amplitude,0,2,.1,m=>d.math.setConfig(t,{amplitude:m}));this.mathParamsContainer.appendChild(p.row);const u=this.createNumberInput("Offset",e.offset,0,1,.1,m=>d.math.setConfig(t,{offset:m}));if(this.mathParamsContainer.appendChild(u.row),["sine","sawtooth","triangle","square"].includes(t)){const m=this.createNumberInput("Phase",e.phase,0,1,.01,b=>d.math.setConfig(t,{phase:b}));this.mathParamsContainer.appendChild(m.row)}}setSignalType(t){if(!t||t==="none")this.currentSignalType=null,this.currentMidiId=null,this.midiRow.style.display="none",this.mathParamsContainer.style.display="none",this.easeRow.style.display="none",this.behaviourRow.style.display="none",this.stop(),this.signalSelect.value!=="none"&&(this.signalSelect.value="none");else{this.currentSignalType=t;const e=t==="midi",s=["constant","sine","sawtooth","triangle","square","random"].includes(t),i=["volume","bass","mids","highs"].includes(t);this.midiRow.style.display=e?"grid":"none",this.mathParamsContainer.style.display=s?"grid":"none",s&&this.updateMathParams(t),this.easeRow.style.display="grid",this.behaviourRow.style.display="grid",i?(this.currentMidiId=null,d.audio.ctx.state==="suspended"&&d.audio.setInput("microphone")):e||(this.currentMidiId=null),this.start(),this.signalSelect.value!==t&&(this.signalSelect.value=t)}}setMidiId(t){this.currentMidiId=t,this.midiBtn.textContent=t??"Learn"}setEase(t){this.currentEase=t,this.easeSelect.value!==t&&(this.easeSelect.value=t)}setBehaviour(t){this.currentBehaviour=t,this.behaviourSelect.value!==t&&(this.behaviourSelect.value=t)}start(){!this.rafId&&this.currentSignalType&&this.loop()}stop(){this.rafId&&(cancelAnimationFrame(this.rafId),this.rafId=null)}save(){return{type:this.currentSignalType,midiId:this.currentMidiId,ease:this.currentEase,behaviour:this.currentBehaviour}}load(t){t&&(this.setSignalType(t.type),this.setMidiId(t.midiId||null),this.setEase(t.ease||"linear"),this.setBehaviour(t.behaviour||"forward"))}reset(){this.setSignalType("none"),this.setEase("linear"),this.setBehaviour("forward"),this.setMidiId(null)}}class Z extends d{constructor(t,e,s={}){super(t,e,s),this.pingPongDirection=1,this.min=0,this.max=100,this.initialOptions=s,this.min=s.min??0,this.max=s.max??100;const i=o("details",{className:"cp-controller-details"}),a=o("summary",{className:"cp-controller-summary"});this.input=o("input",{type:"range",className:"cp-input-range",step:s.step??"any"}),s.min!==void 0&&(this.input.min=String(s.min)),s.max!==void 0&&(this.input.max=String(s.max)),this.input.value=String(this.value),this.display=o("span",{className:"cp-value-display"},[String(this.value.toFixed(1))]),this.input.addEventListener("input",()=>{const v=parseFloat(this.input.value);isNaN(v)||(this.setValue(v),this.display.textContent=String(v.toFixed(1)))}),this.input.addEventListener("click",v=>{v.stopPropagation()});const r=o("div",{className:"cp-controller-summary-content"});r.appendChild(this.input),r.appendChild(this.display),a.appendChild(r),i.appendChild(a);const l=o("div",{className:"cp-number-settings"}),p=this.createSetting("min",s.min,v=>this.setMin(v));this.minInput=p.input,l.appendChild(p.row);const u=this.createSetting("max",s.max,v=>this.setMax(v));this.maxInput=u.input,l.appendChild(u.row);const m=this.createSetting("step",s.step,v=>this.setStep(v));this.stepInput=m.input,l.appendChild(m.row);const b=o("hr",{className:"cp-separator"});l.appendChild(b),this.signalHandler=new G({container:l,onChange:(v,S)=>this.applySignal(v,S)}),i.appendChild(l),this.appendWidget(i)}setMin(t){typeof t=="number"&&(t=String(t)),t===""||isNaN(parseFloat(t))?this.input.removeAttribute("min"):(this.input.min=t,this.min=parseFloat(t)),this.minInput&&this.minInput.value!==t&&(this.minInput.value=t)}setMax(t){typeof t=="number"&&(t=String(t)),t===""||isNaN(parseFloat(t))?this.input.removeAttribute("max"):(this.input.max=t,this.max=parseFloat(t)),this.maxInput&&this.maxInput.value!==t&&(this.maxInput.value=t)}setStep(t){t===void 0&&(t=""),typeof t=="number"&&(t=String(t)),t===""||t==="any"||isNaN(parseFloat(t))?this.input.step="any":this.input.step=t,this.stepInput&&(t==="any"||t===""?this.stepInput.value="":this.stepInput.value!==t&&(this.stepInput.value=t))}applySignal(t,e){const s=this.max-this.min;let i;if(e==="forward")i=this.min+t*s;else if(e==="backward")i=this.max-t*s;else{const a=t*(s*.01);i=this.value,e==="loopForward"?(i+=a,i>this.max&&(i=this.min+(i-this.min)%s)):e==="loopBackward"?(i-=a,i<this.min&&(i=this.max-(this.max-i)%s)):e==="pingpong"&&(i+=a*this.pingPongDirection,i>=this.max?(i=this.max,this.pingPongDirection=-1):i<=this.min&&(i=this.min,this.pingPongDirection=1))}i=this.roundToStep(i),this.setValue(i),this.input.value=String(i),this.display.textContent=String(i.toFixed(1))}roundToStep(t){const e=this.input.step;if(e==="any"||e===""||isNaN(parseFloat(e)))return t;const s=parseFloat(e),i=this.min;return i+Math.round((t-i)/s)*s}createSetting(t,e,s){const i=o("div",{className:"cp-setting-row"}),a=o("label",{className:"cp-setting-label"},[t]),r=o("input",{type:"number",className:"cp-input-number cp-input-small",step:"any"});return e!==void 0&&(r.value=String(e)),r.addEventListener("input",()=>s(r.value)),i.appendChild(a),i.appendChild(r),{row:i,input:r}}updateDisplay(){this.input.value=String(this.value),this.display.textContent=String(this.value.toFixed(1))}save(){return{value:this.value,settings:{min:this.min,max:this.max,step:this.input.step,signal:this.signalHandler.save()}}}load(t){if(typeof t=="number")this.setValue(t),this.resetSettings();else if(typeof t=="object"&&t!==null&&"value"in t){const e=t.settings||{};e.min!==void 0?this.setMin(e.min):this.setMin(this.initialOptions.min!==void 0?this.initialOptions.min:""),e.max!==void 0?this.setMax(e.max):this.setMax(this.initialOptions.max!==void 0?this.initialOptions.max:""),e.step!==void 0?this.setStep(e.step):this.setStep(this.initialOptions.step);let s=t.value;!isNaN(this.min)&&s<this.min&&(s=this.min),!isNaN(this.max)&&s>this.max&&(s=this.max),this.setValue(s),this.signalHandler?.load(e.signal)}}reset(){this.setValue(this.initialValue),this.resetSettings()}resetSettings(){this.setMin(this.initialOptions.min!==void 0?this.initialOptions.min:""),this.setMax(this.initialOptions.max!==void 0?this.initialOptions.max:""),this.setStep(this.initialOptions.step),this.signalHandler?.reset()}}class K extends d{constructor(t,e,s){super(t,e,s),this.optionValues=[],this.select=o("select",{className:"cp-select"}),this.optionValues=s.options||[],this.optionValues.forEach((i,a)=>{const r=o("option",{value:String(a)},[String(i)]);this.select.appendChild(r)}),this.updateDisplay(),this.select.addEventListener("change",()=>{const i=parseInt(this.select.value),a=this.optionValues[i];this.setValue(a)}),this.appendWidget(this.select)}setOptions(t){this.select.innerHTML="",this.optionValues=t,this.optionValues.forEach((e,s)=>{const i=o("option",{value:String(s)},[String(e)]);this.select.appendChild(i)}),this.updateDisplay(),this.select.value===""&&this.optionValues.length>0&&this.setValue(this.optionValues[0])}updateDisplay(){const t=this.optionValues.indexOf(this.value);t!==-1&&(this.select.value=String(t))}}class Q extends d{constructor(t,e,s={}){const i={action:e};super(i,"action",s),this.domElement.querySelector(".cp-label")?.remove();const a=s.label??t;this.button=o("button",{className:"cp-button"},[String(a)]),this.button.addEventListener("click",()=>{const r=this.value;typeof r=="function"&&r(),this.emitChange(r)}),this.appendWidget(this.button)}updateDisplay(){}}class tt extends d{constructor(t,e,s={}){super(t,e,s),this.input=o("input",{type:"checkbox",className:"cp-checkbox"}),this.input.checked=this.value,this.input.addEventListener("change",()=>{this.setValue(this.input.checked)}),this.appendWidget(this.input)}updateDisplay(){this.input.checked=this.value}}class et extends d{constructor(t,e,s){super(t,e,s),this.buttons=[],this.optionValues=[],this.container=o("div",{className:"cp-radios"}),this.optionValues=s.options||[],this.optionValues.forEach(i=>{const a=o("button",{className:"cp-button cp-radio"},[String(i)]);a.addEventListener("click",()=>{this.setValue(i)}),this.container.appendChild(a),this.buttons.push(a)}),this.updateDisplay(),this.appendWidget(this.container)}updateDisplay(){const t=this.value;this.buttons.forEach((e,s)=>{this.optionValues[s]===t?e.setAttribute("data-active","true"):e.removeAttribute("data-active")})}}class st extends d{constructor(t,e,s={}){super(t,e,s),this.input=o("input",{type:"color",className:"cp-input-color",value:this.value||"#000000"}),this.appendWidget(this.input),this.input.addEventListener("input",i=>{const a=i.target;this.setValue(a.value)}),this.updateDisplay()}updateDisplay(){this.input.value=this.value}}function it(n){const t=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;n=n.replace(t,(s,i,a,r)=>i+i+a+a+r+r);const e=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(n);return e?[parseInt(e[1],16),parseInt(e[2],16),parseInt(e[3],16)]:[0,0,0]}function ht(n,t,e){return"#"+((1<<24)+(Math.round(n)<<16)+(Math.round(t)<<8)+Math.round(e)).toString(16).slice(1)}function N(n){const t=n/255;return t<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function F(n){return n<=.0031308?n*12.92*255:(1.055*Math.pow(n,1/2.4)-.055)*255}function dt(n,t,e){const[s,i,a]=it(n),[r,l,p]=it(t),u=N(s),m=N(i),b=N(a),v=N(r),S=N(l),T=N(p),f=u+e*(v-u),B=m+e*(S-m),C=b+e*(T-b),c=F(f),g=F(B),y=F(C);return ht(c,g,y)}class nt extends d{constructor(t,e,s={}){super(t,e,s),this.stops=[],this.pingPongDirection=1,this.animationT=0,this.manualPosition=0,this.initialOptions=s,this.stops=s.stops||[{color:"#000000",position:0},{color:"#ffffff",position:1}],this.sortStops();const i=o("details",{className:"cp-controller-details"}),a=o("summary",{className:"cp-controller-summary"}),r=o("div",{className:"cp-controller-summary-content"});this.displayText=o("span",{className:"cp-value-display"},[String(this.value)]),r.appendChild(this.displayText),a.appendChild(r),i.appendChild(a);const l=o("div",{className:"cp-number-settings"});this.stopsContainer=o("div",{className:"cp-stops-container"}),this.renderStops(),l.appendChild(this.stopsContainer);const p=o("button",{className:"cp-button"},["+ Add Stop"]);p.addEventListener("click",()=>{this.stops.push({color:"#ffffff",position:.5}),this.sortStops(),this.renderStops(),this.updateOutput()}),l.appendChild(p);const u=o("hr",{className:"cp-separator"});l.appendChild(u),this.signalHandler=new G({container:l,onChange:(m,b)=>this.applySignal(m,b)}),i.appendChild(l),this.appendWidget(i),this.updateOutput(0)}sortStops(){this.stops.sort((t,e)=>t.position-e.position)}renderStops(){this.stopsContainer.innerHTML="",this.stops.forEach((t,e)=>{const s=o("div",{className:"cp-gradient-stop-row"}),i=o("input",{type:"color",className:"cp-input-color",value:t.color});i.addEventListener("input",l=>{t.color=l.target.value,this.updateOutput()});const a=o("input",{type:"number",className:"cp-input-number cp-input-small",min:"0",max:"1",step:"0.01",value:String(t.position)});a.addEventListener("change",l=>{let p=parseFloat(l.target.value);isNaN(p)&&(p=0),t.position=Math.max(0,Math.min(1,p)),this.sortStops(),this.renderStops(),this.updateOutput()});const r=j(()=>{this.stops.splice(e,1),this.renderStops(),this.updateOutput()});s.appendChild(i),s.appendChild(a),s.appendChild(r),this.stopsContainer.appendChild(s)})}updateOutput(t=this.manualPosition){if(this.stops.length===0)return;if(this.stops.length===1){this.setValue(this.stops[0].color),this.updateDisplay();return}let e="#000000";if(t=Math.max(0,Math.min(1,t)),t<=this.stops[0].position)e=this.stops[0].color;else if(t>=this.stops[this.stops.length-1].position)e=this.stops[this.stops.length-1].color;else for(let s=0;s<this.stops.length-1;s++){const i=this.stops[s],a=this.stops[s+1];if(t>=i.position&&t<=a.position){const r=a.position-i.position,l=r===0?0:(t-i.position)/r;e=dt(i.color,a.color,l);break}}this.setValue(e),this.updateDisplay()}updateDisplay(){this.displayText&&(this.displayText.textContent=this.value)}applySignal(t,e){let s=t;if(e==="forward")s=t;else if(e==="backward")s=1-t;else{const i=t*.05;e==="loopForward"?(this.animationT=(this.animationT+i)%1,s=this.animationT):e==="loopBackward"?(this.animationT=(this.animationT-i+1)%1,s=this.animationT):e==="pingpong"&&(this.animationT+=i*this.pingPongDirection,this.animationT>=1?(this.animationT=1,this.pingPongDirection=-1):this.animationT<=0&&(this.animationT=0,this.pingPongDirection=1),s=this.animationT)}this.updateOutput(s),this.manualPosition=s}save(){return{stops:this.stops,settings:{signal:this.signalHandler.save()}}}load(t){t&&t.stops&&(this.stops=t.stops,this.sortStops(),this.renderStops()),t&&t.settings&&this.signalHandler?.load(t.settings.signal)}reset(){this.stops=this.initialOptions.stops||[{color:"#000000",position:0},{color:"#ffffff",position:1}],this.sortStops(),this.renderStops(),this.signalHandler?.reset(),this.updateOutput(0)}}class at extends d{constructor(t,e,s={}){super(t,e,s),this.items=[],this.initialOptions=s,this.itemType=s.itemType||"string",this.items=this.parseValue(this.value);const i=o("details",{className:"cp-controller-details"}),a=o("summary",{className:"cp-controller-summary"}),r=o("div",{className:"cp-controller-summary-content"}),l=o("span",{className:"cp-value-display"},[`${this.items.length} items`]);r.appendChild(l),a.appendChild(r),i.appendChild(a);const p=o("div",{className:"cp-number-settings"});this.itemsContainer=o("div",{className:"cp-stops-container"}),this.renderItems(),p.appendChild(this.itemsContainer);const u=o("button",{className:"cp-button cp-input-small",style:"margin-top: 8px; width: 100%;"},["+ Add Item"]);u.addEventListener("click",()=>{this.addItem()}),p.appendChild(u),i.appendChild(p),this.appendWidget(i)}parseValue(t){return!t||t.trim()===""?[]:t.split(",").map(e=>e.trim())}serializeValue(){return this.items.join(",")}getDefaultItemValue(){switch(this.itemType){case"color":return"#ffffff";case"number":return"0";default:return""}}addItem(t){const e=t!==void 0?t:this.getDefaultItemValue();this.items.push(e),this.renderItems(),this.updateValue()}updateValue(){const t=this.serializeValue();this.setValue(t),this.updateSummary()}updateSummary(){const t=this.domElement.querySelector(".cp-value-display");t&&(t.textContent=`${this.items.length} items`)}renderItems(){this.itemsContainer.innerHTML="",this.items.forEach((t,e)=>{const s=o("div",{className:"cp-array-row"});let i;this.itemType==="color"?i=o("input",{type:"color",className:"cp-input-color",value:t}):this.itemType==="number"?i=o("input",{type:"number",className:"cp-input-number cp-input-small",step:"any",value:t}):i=o("input",{type:"text",className:"cp-input-number cp-input-small",value:t}),i.addEventListener("input",r=>{this.items[e]=r.target.value,this.updateValue()});const a=j(()=>{this.items.splice(e,1),this.renderItems(),this.updateValue()});s.appendChild(i),s.appendChild(a),this.itemsContainer.appendChild(s)})}updateDisplay(){}save(){return[...this.items]}load(t){Array.isArray(t)?this.items=[...t]:typeof t=="string"&&(this.items=this.parseValue(t)),this.renderItems(),this.updateValue()}reset(){const t=this.initialValue||"";this.items=this.parseValue(t),this.renderItems(),this.updateValue()}}class ut{constructor(){this.frames=0,this.pollingInterval=1e3,this.prevTime=performance.now(),this.render=()=>{this.frames++;const t=performance.now();if(t>=this.prevTime+this.pollingInterval){const e=Math.round(this.frames*1e3/(t-this.prevTime));let s="";const i=performance.memory;i&&(s=` / ${Math.round(i.usedJSHeapSize/1048576)}MB`),this.domElement.textContent=`${e} FPS${s}`,this.prevTime=t,this.frames=0}this.rafId=requestAnimationFrame(this.render)},this.domElement=o("span",{className:"cp-stats"}),this.rafId=requestAnimationFrame(this.render)}destroy(){cancelAnimationFrame(this.rafId)}}class D{constructor(){this.controllers=[],this.folders=[]}addNumber(t,e,s={}){const i=new Y(t,e,s);return this.contentElement.appendChild(i.domElement),this.controllers.push(i),i}addRange(t,e,s={}){const i=new Z(t,e,s);return this.contentElement.appendChild(i.domElement),this.controllers.push(i),i}addSelect(t,e,s={}){const i=new K(t,e,s);return this.contentElement.appendChild(i.domElement),this.controllers.push(i),i}addBoolean(t,e,s={}){const i=new tt(t,e,s);return this.contentElement.appendChild(i.domElement),this.controllers.push(i),i}addButton(t,e,s={}){const i=new Q(t,e,s);return this.contentElement.appendChild(i.domElement),this.controllers.push(i),i}addRadio(t,e,s={}){const i=new et(t,e,s);return this.contentElement.appendChild(i.domElement),this.controllers.push(i),i}addColor(t,e,s={}){const i=new st(t,e,s);return this.contentElement.appendChild(i.domElement),this.controllers.push(i),i}addGradient(t,e,s={}){const i=new nt(t,e,s);return this.contentElement.appendChild(i.domElement),this.controllers.push(i),i}addArray(t,e,s={}){const i=new at(t,e,s);return this.contentElement.appendChild(i.domElement),this.controllers.push(i),i}addFolder(t){const e=new ot(t);return this.addSeparator(),this.contentElement.appendChild(e.domElement),this.folders.push(e),e}addSeparator(){const t=o("hr",{className:"cp-separator"});this.contentElement.appendChild(t)}save(){const t={controllers:{},folders:{}};for(const e of this.controllers)typeof e.value!="function"&&(t.controllers[e.key]=e.save());for(const e of this.folders)t.folders[e.title]=e.save();return t}load(t){if(!t){this.reset();return}for(const e of this.controllers)if(typeof e.value!="function")if(t.controllers&&e.key in t.controllers){const s=t.controllers[e.key];s!==void 0&&e.load(s)}else e.reset();for(const e of this.folders){const s=t.folders?t.folders[e.title]:void 0;e.load(s)}}reset(){for(const t of this.controllers)typeof t.value!="function"&&t.reset();for(const t of this.folders)t.reset()}}class ot extends D{constructor(t){super(),this.title=t,this.domElement=o("details",{className:"cp-folder",open:!0}),this.summaryElement=o("summary",{className:"cp-summary"},[t]),this.domElement.appendChild(this.summaryElement),this.contentElement=o("div",{className:"cp-content cp-folder-content"}),this.domElement.appendChild(this.contentElement)}}class mt extends D{constructor(t,e={}){super(),lt(),this.domElement=o("details",{className:"cp-root",open:!0}),this.summaryElement=o("summary",{className:"cp-summary cp-summary-root"}),this.domElement.appendChild(this.summaryElement);const s=o("span",{},[e.title||"ControlPanel"]);this.summaryElement.appendChild(s),this.stats=new ut,this.summaryElement.appendChild(this.stats.domElement);let i=!1,a=0,r=0,l=0,p=0;this.summaryElement.addEventListener("mousedown",c=>{if(c.target!==this.summaryElement&&c.target!==s)return;i=!0,a=c.clientX,r=c.clientY;const g=this.domElement.getBoundingClientRect();l=g.left,p=g.top,c.preventDefault()}),document.addEventListener("mousemove",c=>{if(!i)return;const g=c.clientX-a,y=c.clientY-r,w=l+g,A=p+y;this.domElement.style.left=`${w}px`,this.domElement.style.top=`${A}px`,this.domElement.style.right="auto",this.domElement.style.bottom="auto"}),document.addEventListener("mouseup",()=>{i&&(i=!1,this.savePositionAndSize())}),new ResizeObserver(()=>{i||this.savePositionAndSize()}).observe(this.domElement),this.restorePositionAndSize(),this.contentElement=o("div",{className:"cp-content"}),this.domElement.appendChild(this.contentElement);const m=this.addFolder("_Signals"),b={audioInput:null,fftSize:2048};m.addRadio(b,"audioInput",{label:"Audio Signal",options:["microphone","browser"]}).onChange(c=>{E.setInput(c)}),m.addSelect(b,"fftSize",{label:"FFT Size",options:[256,512,1024,2048]}).onChange(c=>{E.setFFTSize(c)}),m.addRange(E,"smoothingTimeConstant",{min:0,max:.99,step:.01,label:"Smoothing"}).onChange(c=>{E.analyser.smoothingTimeConstant=c}),m.addRange(E,"spectrumBoost",{min:1,max:5,step:.1,label:"Compression"}),t?t.appendChild(this.domElement):document.body.appendChild(this.domElement);const v=e.title||"ControlPanel";this.presetStoragePrefix=`cp-presets-${v}-`;const S=this.addFolder("_User Presets"),T=()=>{const c=["Default"];if(typeof localStorage>"u")return c;for(let g=0;g<localStorage.length;g++){const y=localStorage.key(g);if(y&&y.startsWith(this.presetStoragePrefix)){const w=y.substring(this.presetStoragePrefix.length);w!=="Default"&&!c.includes(w)&&c.push(w)}}return c.sort()},f={selected:"Default",save:()=>{const c=prompt("Preset Name:",f.selected);if(c){if(c==="Default"){alert("Cannot overwrite Default preset");return}const g=this.presetStoragePrefix+c;this.saveToLocalStorage(g);const y=T();C.setOptions(y),f.selected=c,C.setValue(c)}},load:()=>{const c=f.selected,g=this.presetStoragePrefix+c;this.loadFromLocalStorage(g),f.selected=c,C.setValue(c)},delete:()=>{if(f.selected==="Default"){alert("Cannot delete Default preset");return}if(confirm(`Delete preset "${f.selected}"?`)){const c=this.presetStoragePrefix+f.selected;localStorage.removeItem(c);const g=T();C.setOptions(g),f.selected="Default",C.setValue("Default"),this.reset()}},export:()=>{const c=this.save(),g=O=>{const P={controllers:{},folders:{}};for(const[V,q]of Object.entries(O.controllers))V.startsWith("_")||(P.controllers[V]=q);for(const[V,q]of Object.entries(O.folders))V.startsWith("_")||(P.folders[V]=g(q));return P},y=g(c),w={_presetName:f.selected||"CustomPreset",_exportDate:new Date().toISOString(),_instructions:"To add as factory preset: Copy 'controllers' and 'folders' fields into the presets.json file",...y},A=JSON.stringify(w,null,2),I=new Blob([A],{type:"application/json"}),M=URL.createObjectURL(I),x=document.createElement("a");x.href=M;const k=new Date().toISOString().split("T")[0],rt=f.selected.replace(/[^a-z0-9]/gi,"-").toLowerCase();x.download=`${v.toLowerCase()}-preset-${rt}-${k}.json`,document.body.appendChild(x),x.click(),document.body.removeChild(x),URL.revokeObjectURL(M)},import:()=>{const c=document.createElement("input");c.type="file",c.accept=".json",c.onchange=g=>{const y=g.target.files?.[0];if(!y)return;const w=new FileReader;w.onload=A=>{try{const I=A.target?.result,M=JSON.parse(I),x={controllers:M.controllers||{},folders:M.folders||{}};if(!x.controllers||!x.folders){alert("Invalid preset file: missing 'controllers' or 'folders'");return}this.load(x);const k=M._presetName||"ImportedPreset";if(confirm(`Preset loaded! Save as "${k}" to User Presets?`)){const O=this.presetStoragePrefix+k;this.saveToLocalStorage(O);const P=T();C.setOptions(P),f.selected=k,C.setValue(k)}}catch(I){alert(`Failed to import preset: ${I instanceof Error?I.message:"Invalid JSON"}`),console.error("Import error:",I)}},w.readAsText(y)},c.click()}},B=T(),C=S.addSelect(f,"selected",{label:"Preset",options:B});S.addButton("Load",()=>f.load()),S.addButton("Save",()=>f.save()),S.addButton("Delete",()=>f.delete()),S.addButton("Export",()=>f.export()),S.addButton("Import",()=>f.import())}saveToLocalStorage(t){const e=this.save();try{localStorage.setItem(t,JSON.stringify(e))}catch(s){console.warn("ControlPanel: Failed to save to localStorage",s)}}loadFromLocalStorage(t){try{const e=localStorage.getItem(t);if(e){const s=JSON.parse(e);this.load(s)}}catch(e){console.warn("ControlPanel: Failed to load from localStorage",e)}}saveDefaultPreset(){const t=this.presetStoragePrefix+"Default";this.save(),this.saveToLocalStorage(t)}savePositionAndSize(){const t=this.domElement.getBoundingClientRect(),e=`cp-position-${this.presetStoragePrefix}`,s={left:t.left,top:t.top,width:this.domElement.offsetWidth,height:this.domElement.offsetHeight};try{sessionStorage.setItem(e,JSON.stringify(s))}catch(i){console.warn("Failed to save panel position/size",i)}}restorePositionAndSize(){const t=`cp-position-${this.presetStoragePrefix}`;try{const e=sessionStorage.getItem(t);if(e){const s=JSON.parse(e);this.domElement.style.left=`${s.left}px`,this.domElement.style.top=`${s.top}px`,this.domElement.style.right="auto",this.domElement.style.bottom="auto",this.domElement.style.width=`${s.width}px`,this.domElement.style.height=`${s.height}px`}}catch(e){console.warn("Failed to restore panel position/size",e)}}destroy(){this.stats.destroy(),this.domElement.remove(),this.controllers=[],this.folders=[]}}h.ArrayController=at,h.AudioSignals=H,h.BooleanController=tt,h.ButtonController=Q,h.ColorController=st,h.ControlPanel=mt,h.ControlPanelContainer=D,h.Controller=d,h.Folder=ot,h.GradientController=nt,h.MathSignals=_,h.MidiSignals=U,h.NumberController=Y,h.RadioController=et,h.RangeController=Z,h.SelectController=K,h.audioSignals=E,h.mathSignals=J,h.midiSignals=W,Object.defineProperty(h,Symbol.toStringTag,{value:"Module"})}));
|
package/dist/styles.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"AA8YA,wBAAgB,YAAY,SAS3B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@digitalmeadow/control-panel",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.12",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A minimalist, framework-agnostic control panel GUI",
|
|
6
6
|
"author": "Digital Meadow <inbox@digitalmeadow.studio> (https://digitalmeadow.studio)",
|