solid-pianoroll 0.0.14 → 0.0.16
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/cjs/index.js +401 -418
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +404 -420
- package/dist/esm/index.js.map +1 -1
- package/dist/source/PianoRoll.jsx +18 -3
- package/dist/source/PianoRollContext.jsx +5 -2
- package/dist/source/PianoRollGrid.jsx +20 -3
- package/dist/source/PianoRollKeys.jsx +24 -5
- package/dist/source/PianoRollNotes.jsx +117 -81
- package/dist/source/PianoRollTrackList.jsx +28 -0
- package/dist/source/index.jsx +1 -2
- package/dist/source/usePianoRoll.js +4 -4
- package/dist/types/PianoRoll.d.ts +10 -6
- package/dist/types/PianoRollContext.d.ts +1 -1
- package/dist/types/PianoRollTrackList.d.ts +2 -0
- package/dist/types/index.d.ts +1 -2
- package/dist/types/usePianoRoll.d.ts +2 -2
- package/package.json +1 -1
- package/dist/source/MultiTrackPianoRoll.jsx +0 -156
- package/dist/types/MultiTrackPianoRoll.d.ts +0 -13
package/dist/cjs/index.js
CHANGED
|
@@ -29,9 +29,9 @@ function styleInject(css, ref) {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
var css_248z$
|
|
33
|
-
var styles$
|
|
34
|
-
styleInject(css_248z$
|
|
32
|
+
var css_248z$4 = ".PianoRoll-module_PianoRoll__rkRYx {\n box-sizing: border-box;\n display: flex;\n overflow: hidden;\n flex-direction: column;\n}\n\n.PianoRoll-module_PianoRollContainer__Oyxr7 {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: row;\n}\n";
|
|
33
|
+
var styles$4 = {"PianoRoll":"PianoRoll-module_PianoRoll__rkRYx","PianoRollContainer":"PianoRoll-module_PianoRollContainer__Oyxr7"};
|
|
34
|
+
styleInject(css_248z$4);
|
|
35
35
|
|
|
36
36
|
const PianoRollContext = solidJs.createContext();
|
|
37
37
|
const PianoRollContextProvider = PianoRollContext.Provider;
|
|
@@ -40,30 +40,11 @@ const usePianoRollContext = () => {
|
|
|
40
40
|
if (!context) throw new Error("No PianoRollContext found");
|
|
41
41
|
return context;
|
|
42
42
|
};
|
|
43
|
-
const splitContextProps = allProps => solidJs.splitProps(allProps, ["
|
|
43
|
+
const splitContextProps = allProps => solidJs.splitProps(allProps, ["mode", "duration", "gridDivision", "tracks", "position", "ppq", "snapToGrid", "verticalPosition", "verticalZoom", "zoom", "onInsertNote", "onNoteChange", "onPositionChange", "onRemoveNote", "onVerticalPositionChange", "onVerticalZoomChange", "onZoomChange", "showAllTracks", "selectedTrackIndex", "onSelectedTrackIndexChange"]);
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return (() => {
|
|
49
|
-
const _el$ = _tmpl$$8.cloneNode(true);
|
|
50
|
-
web.spread(_el$, web.mergeProps(props, {
|
|
51
|
-
get value() {
|
|
52
|
-
return context.zoom;
|
|
53
|
-
},
|
|
54
|
-
"onInput": event => context.onZoomChange?.(event.currentTarget.valueAsNumber),
|
|
55
|
-
"type": "range",
|
|
56
|
-
get style() {
|
|
57
|
-
return {
|
|
58
|
-
"margin-left": "50px",
|
|
59
|
-
"margin-right": "16px",
|
|
60
|
-
...(typeof props.style === "object" && props.style)
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
}), false, false);
|
|
64
|
-
return _el$;
|
|
65
|
-
})();
|
|
66
|
-
};
|
|
45
|
+
var css_248z$3 = ".PianoRollKeys-module_PianoRollKeys__5vnQ0 {\n position: relative;\n height: 100%;\n width: 50px;\n border-width: 0;\n border-color: #000;\n border-style: solid;\n border-right-width: 1px;\n border-left-width: 1px;\n background: white;\n cursor: pointer;\n overflow: hidden;\n}\n\n.PianoRollKeys-module_Key__jybNC {\n transition-property: background-color, box-shadow;\n transition-duration: 400ms;\n transition-timing-function: ease-out;\n border-width: 0px;\n position: absolute;\n box-sizing: border-box;\n width: 120%;\n left: -20%;\n border-color: #000;\n border-style: solid;\n}\n\n.PianoRollKeys-module_black__7rncB {\n background: black;\n border-top-right-radius: 12%;\n border-bottom-right-radius: 12%;\n margin-left: -20%;\n z-index: 1;\n}\n\n.PianoRollKeys-module_white__fR2Lm {\n background: white;\n border-top-width: 0.5px;\n border-bottom-width: 0.5px;\n}\n\n.PianoRollKeys-module_down__GcNeZ {\n transition: none;\n background: red;\n}\n";
|
|
46
|
+
var styles$3 = {"PianoRollKeys":"PianoRollKeys-module_PianoRollKeys__5vnQ0","Key":"PianoRollKeys-module_Key__jybNC","black":"PianoRollKeys-module_black__7rncB","white":"PianoRollKeys-module_white__fR2Lm","down":"PianoRollKeys-module_down__GcNeZ"};
|
|
47
|
+
styleInject(css_248z$3);
|
|
67
48
|
|
|
68
49
|
function createViewPortDimension(getState) {
|
|
69
50
|
const getStateWithFunctions = () => ({
|
|
@@ -137,6 +118,95 @@ const useViewPortDimension = name => {
|
|
|
137
118
|
return viewPort;
|
|
138
119
|
};
|
|
139
120
|
|
|
121
|
+
const _tmpl$$8 = /*#__PURE__*/web.template(`<div></div>`, 2);
|
|
122
|
+
const PianoRollKeys = () => {
|
|
123
|
+
const viewPort = solidJs.createMemo(() => useViewPortDimension("vertical"));
|
|
124
|
+
return (() => {
|
|
125
|
+
const _el$ = _tmpl$$8.cloneNode(true);
|
|
126
|
+
web.insert(_el$, web.createComponent(solidJs.Index, {
|
|
127
|
+
each: keys,
|
|
128
|
+
children: key => {
|
|
129
|
+
const [isDown, setIsDown] = solidJs.createSignal(false);
|
|
130
|
+
const virtualDimensions = solidJs.createMemo(() => viewPort().calculatePixelDimensions(127 - key().number, 1));
|
|
131
|
+
const previousIsBlack = blackKeys.includes((key().number - 1) % 12);
|
|
132
|
+
const nextIsBlack = blackKeys.includes((key().number + 1) % 12);
|
|
133
|
+
return web.createComponent(solidJs.Show, {
|
|
134
|
+
get when() {
|
|
135
|
+
return virtualDimensions().size > 0;
|
|
136
|
+
},
|
|
137
|
+
get children() {
|
|
138
|
+
const _el$2 = _tmpl$$8.cloneNode(true);
|
|
139
|
+
_el$2.$$mouseup = () => setIsDown(false);
|
|
140
|
+
_el$2.$$mousedown = () => setIsDown(true);
|
|
141
|
+
web.insert(_el$2, web.createComponent(solidJs.Show, {
|
|
142
|
+
get when() {
|
|
143
|
+
return key().isBlack && false;
|
|
144
|
+
},
|
|
145
|
+
get children() {
|
|
146
|
+
const _el$3 = _tmpl$$8.cloneNode(true);
|
|
147
|
+
web.effect(_p$ => {
|
|
148
|
+
const _v$ = styles$3["black-separator"],
|
|
149
|
+
_v$2 = `${virtualDimensions().offset}px`,
|
|
150
|
+
_v$3 = `${virtualDimensions().size / 2 - 0.25}px`;
|
|
151
|
+
_v$ !== _p$._v$ && web.className(_el$3, _p$._v$ = _v$);
|
|
152
|
+
_v$2 !== _p$._v$2 && _el$3.style.setProperty("top", _p$._v$2 = _v$2);
|
|
153
|
+
_v$3 !== _p$._v$3 && _el$3.style.setProperty("height", _p$._v$3 = _v$3);
|
|
154
|
+
return _p$;
|
|
155
|
+
}, {
|
|
156
|
+
_v$: undefined,
|
|
157
|
+
_v$2: undefined,
|
|
158
|
+
_v$3: undefined
|
|
159
|
+
});
|
|
160
|
+
return _el$3;
|
|
161
|
+
}
|
|
162
|
+
}));
|
|
163
|
+
web.effect(_p$ => {
|
|
164
|
+
const _v$4 = {
|
|
165
|
+
[styles$3["Key"]]: true,
|
|
166
|
+
[styles$3["black"]]: key().isBlack,
|
|
167
|
+
[styles$3["white"]]: !key().isBlack,
|
|
168
|
+
[styles$3["down"]]: isDown()
|
|
169
|
+
},
|
|
170
|
+
_v$5 = key().name,
|
|
171
|
+
_v$6 = key().number % 12,
|
|
172
|
+
_v$7 = `${virtualDimensions().offset - (!key().isBlack && nextIsBlack ? virtualDimensions().size / 2 : 0)}px`,
|
|
173
|
+
_v$8 = `${virtualDimensions().size + (!key().isBlack && nextIsBlack ? virtualDimensions().size / 2 : 0) + (!key().isBlack && previousIsBlack ? virtualDimensions().size / 2 : 0)}px`,
|
|
174
|
+
_v$9 = [`0px 0px ${Math.min(virtualDimensions().size / 20, 1)}px ${Math.min(virtualDimensions().size / 50, 1)}px rgba(0, 0, 0, 0.5) ${key().isBlack ? "" : "inset"}`, isDown() && `0px 0px ${Math.min(virtualDimensions().size / 8, 2)}px ${Math.min(virtualDimensions().size / 20, 2)}px rgba(0, 0, 0, 0.5) inset`].filter(item => !!item).join(", ");
|
|
175
|
+
_p$._v$4 = web.classList(_el$2, _v$4, _p$._v$4);
|
|
176
|
+
_v$5 !== _p$._v$5 && web.setAttribute(_el$2, "title", _p$._v$5 = _v$5);
|
|
177
|
+
_v$6 !== _p$._v$6 && web.setAttribute(_el$2, "data-index", _p$._v$6 = _v$6);
|
|
178
|
+
_v$7 !== _p$._v$7 && _el$2.style.setProperty("top", _p$._v$7 = _v$7);
|
|
179
|
+
_v$8 !== _p$._v$8 && _el$2.style.setProperty("height", _p$._v$8 = _v$8);
|
|
180
|
+
_v$9 !== _p$._v$9 && _el$2.style.setProperty("box-shadow", _p$._v$9 = _v$9);
|
|
181
|
+
return _p$;
|
|
182
|
+
}, {
|
|
183
|
+
_v$4: undefined,
|
|
184
|
+
_v$5: undefined,
|
|
185
|
+
_v$6: undefined,
|
|
186
|
+
_v$7: undefined,
|
|
187
|
+
_v$8: undefined,
|
|
188
|
+
_v$9: undefined
|
|
189
|
+
});
|
|
190
|
+
return _el$2;
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}));
|
|
195
|
+
web.effect(() => web.className(_el$, styles$3.PianoRollKeys));
|
|
196
|
+
return _el$;
|
|
197
|
+
})();
|
|
198
|
+
};
|
|
199
|
+
const blackKeys = [1, 3, 6, 8, 10];
|
|
200
|
+
const keyNames = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
|
|
201
|
+
const keys = Array.from({
|
|
202
|
+
length: 128
|
|
203
|
+
}).map((_, index) => ({
|
|
204
|
+
number: index,
|
|
205
|
+
name: `${keyNames[index % 12]} ${Math.floor(index / 12) - 2}`,
|
|
206
|
+
isBlack: blackKeys.includes(index % 12)
|
|
207
|
+
}));
|
|
208
|
+
web.delegateEvents(["mousedown", "mouseup"]);
|
|
209
|
+
|
|
140
210
|
var css_248z$2 = ".PianoRollNotes-module_PianoRollNotes__6pF-y {\n position: absolute;\n flex: 1;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 1;\n cursor: grab;\n}\n.PianoRollNotes-module_PianoRollNotes__6pF-y .PianoRollNotes-module_Note__-jxLb {\n position: absolute;\n box-sizing: border-box;\n border-width: 0.5px;\n border-style: solid;\n border-color: #a00;\n cursor: move;\n}\n.PianoRollNotes-module_PianoRollNotes__6pF-y .PianoRollNotes-module_Note__-jxLb.PianoRollNotes-module_trimStart__vuBlj {\n cursor: w-resize;\n}\n.PianoRollNotes-module_PianoRollNotes__6pF-y .PianoRollNotes-module_Note__-jxLb.PianoRollNotes-module_trimEnd__zPdjr {\n cursor: e-resize;\n}";
|
|
141
211
|
var styles$2 = {"PianoRollNotes":"PianoRollNotes-module_PianoRollNotes__6pF-y","Note":"PianoRollNotes-module_Note__-jxLb","trimStart":"PianoRollNotes-module_trimStart__vuBlj","trimEnd":"PianoRollNotes-module_trimEnd__zPdjr"};
|
|
142
212
|
styleInject(css_248z$2);
|
|
@@ -150,10 +220,11 @@ const PianoRollNotes = props => {
|
|
|
150
220
|
const snapValueToGridIfEnabled = (value, altKey) => context.snapToGrid && !altKey ? Math.round(value / gridDivisionTicks()) * gridDivisionTicks() : value;
|
|
151
221
|
const insertOrUpdateNote = event => {
|
|
152
222
|
const position = horizontalViewPort().calculatePosition(event.clientX);
|
|
153
|
-
const
|
|
223
|
+
const existingNote = currentNote();
|
|
224
|
+
const midi = context.mode === "keys" ? 127 - Math.floor(verticalViewPort().calculatePosition(event.clientY)) : existingNote?.midi ?? 60;
|
|
225
|
+
const targetTrackIndex = context.mode === "tracks" ? Math.floor(verticalViewPort().calculatePosition(event.clientY)) : context.selectedTrackIndex ?? 0;
|
|
154
226
|
const eventPositionTicks = Math.floor(position / gridDivisionTicks()) * gridDivisionTicks();
|
|
155
227
|
const velocity = 127;
|
|
156
|
-
const existingNote = newNote();
|
|
157
228
|
const ticks = existingNote?.ticks ?? eventPositionTicks;
|
|
158
229
|
const durationTicks = existingNote?.ticks ? eventPositionTicks - existingNote?.ticks : gridDivisionTicks();
|
|
159
230
|
const note = {
|
|
@@ -163,25 +234,26 @@ const PianoRollNotes = props => {
|
|
|
163
234
|
velocity
|
|
164
235
|
};
|
|
165
236
|
if (existingNote) {
|
|
166
|
-
context.onNoteChange?.(
|
|
167
|
-
return
|
|
237
|
+
context.onNoteChange?.(currentNoteTrackIndex(), currentNoteIndex(), note);
|
|
238
|
+
return currentNoteIndex();
|
|
168
239
|
} else {
|
|
169
|
-
return context.onInsertNote?.(note) ?? -1;
|
|
240
|
+
return context.onInsertNote?.(targetTrackIndex, note) ?? -1;
|
|
170
241
|
}
|
|
171
242
|
};
|
|
172
243
|
const [isDragging, setIsDragging] = solidJs.createSignal(false);
|
|
173
244
|
const [noteDragMode, setNoteDragMode] = solidJs.createSignal();
|
|
174
|
-
const [
|
|
245
|
+
const [currentNoteIndex, setCurrentNoteIndex] = solidJs.createSignal(-1);
|
|
246
|
+
const [currentNoteTrackIndex, setCurrentNoteTrackIndex] = solidJs.createSignal(-1);
|
|
175
247
|
const [isMouseDown, setIsMouseDown] = solidJs.createSignal(false);
|
|
176
|
-
const
|
|
248
|
+
const currentNote = solidJs.createMemo(() => context.tracks[currentNoteTrackIndex()]?.notes[currentNoteIndex()]);
|
|
177
249
|
const getClasses = noteDragMode => {
|
|
178
250
|
return noteDragMode ? [styles$2.Note, styles$2[noteDragMode]] : [styles$2.Note];
|
|
179
251
|
};
|
|
180
252
|
return (() => {
|
|
181
253
|
const _el$ = _tmpl$$7.cloneNode(true);
|
|
182
254
|
_el$.$$click = event => {
|
|
183
|
-
if (
|
|
184
|
-
|
|
255
|
+
if (currentNote()) {
|
|
256
|
+
setCurrentNoteIndex(-1);
|
|
185
257
|
return;
|
|
186
258
|
}
|
|
187
259
|
if (!event.altKey) return;
|
|
@@ -202,94 +274,133 @@ const PianoRollNotes = props => {
|
|
|
202
274
|
return;
|
|
203
275
|
}
|
|
204
276
|
const index = insertOrUpdateNote(event);
|
|
205
|
-
|
|
277
|
+
setCurrentNoteIndex(index);
|
|
206
278
|
};
|
|
207
279
|
_el$.$$mousedown = event => {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
280
|
+
solidJs.batch(() => {
|
|
281
|
+
setIsMouseDown(true);
|
|
282
|
+
const index = insertOrUpdateNote(event);
|
|
283
|
+
setCurrentNoteTrackIndex(context.selectedTrackIndex ?? 0);
|
|
284
|
+
setCurrentNoteIndex(index);
|
|
285
|
+
});
|
|
212
286
|
};
|
|
213
287
|
const _ref$ = props.ref;
|
|
214
288
|
typeof _ref$ === "function" ? web.use(_ref$, _el$) : props.ref = _el$;
|
|
215
|
-
web.insert(_el$, web.createComponent(solidJs.
|
|
289
|
+
web.insert(_el$, web.createComponent(solidJs.For, {
|
|
216
290
|
get each() {
|
|
217
|
-
return context.
|
|
291
|
+
return context.tracks;
|
|
218
292
|
},
|
|
219
|
-
children: (
|
|
220
|
-
const verticalVirtualDimensions = solidJs.createMemo(() => verticalViewPort().calculatePixelDimensions(127 - note().midi, 1));
|
|
221
|
-
const horizontalDimensions = solidJs.createMemo(() => horizontalViewPort().calculatePixelDimensions(note().ticks, note().durationTicks));
|
|
293
|
+
children: (track, trackIndex) => {
|
|
222
294
|
return web.createComponent(solidJs.Show, {
|
|
223
295
|
get when() {
|
|
224
|
-
return
|
|
296
|
+
return trackIndex() === context.selectedTrackIndex || context.showAllTracks || context.mode === "tracks";
|
|
225
297
|
},
|
|
226
298
|
get children() {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
299
|
+
return web.createComponent(solidJs.For, {
|
|
300
|
+
get each() {
|
|
301
|
+
return track.notes;
|
|
302
|
+
},
|
|
303
|
+
children: (note, noteIndex) => {
|
|
304
|
+
const verticalVirtualDimensions = solidJs.createMemo(() => verticalViewPort().calculatePixelDimensions(context.mode === "keys" ? 127 - note.midi : trackIndex(), 1));
|
|
305
|
+
const horizontalDimensions = solidJs.createMemo(() => horizontalViewPort().calculatePixelDimensions(note.ticks, note.durationTicks));
|
|
306
|
+
return web.createComponent(solidJs.Show, {
|
|
307
|
+
get when() {
|
|
308
|
+
return web.memo(() => !!verticalViewPort().isVisible(verticalVirtualDimensions()))() && horizontalViewPort().isVisible(horizontalDimensions());
|
|
309
|
+
},
|
|
310
|
+
get children() {
|
|
311
|
+
const _el$2 = _tmpl$$7.cloneNode(true);
|
|
312
|
+
_el$2.$$mousedown = event => {
|
|
313
|
+
event.stopPropagation();
|
|
314
|
+
setIsDragging(true);
|
|
315
|
+
setCurrentNoteIndex(noteIndex());
|
|
316
|
+
setCurrentNoteTrackIndex(trackIndex());
|
|
317
|
+
const initialPosition = horizontalViewPort().calculatePosition(event.clientX);
|
|
318
|
+
const diffPosition = initialPosition - note.ticks;
|
|
319
|
+
const handleMouseMove = mouseMoveEvent => {
|
|
320
|
+
const note = currentNote();
|
|
321
|
+
if (!note) return;
|
|
322
|
+
const ticks = snapValueToGridIfEnabled(Math.max(horizontalViewPort().calculatePosition(mouseMoveEvent.clientX) - diffPosition, 0), mouseMoveEvent.altKey);
|
|
323
|
+
const updatedNote = {
|
|
324
|
+
...note,
|
|
325
|
+
...(noteDragMode() === "move" && context.mode === "keys" && {
|
|
326
|
+
midi: Math.round(127 - verticalViewPort().calculatePosition(mouseMoveEvent.clientY))
|
|
327
|
+
}),
|
|
328
|
+
...((noteDragMode() === "move" || noteDragMode() === "trimStart") && {
|
|
329
|
+
ticks
|
|
330
|
+
}),
|
|
331
|
+
...(noteDragMode() === "trimStart" && {
|
|
332
|
+
durationTicks: note.durationTicks + note.ticks - ticks
|
|
333
|
+
}),
|
|
334
|
+
...(noteDragMode() === "trimEnd" && {
|
|
335
|
+
durationTicks: snapValueToGridIfEnabled(horizontalViewPort().calculatePosition(mouseMoveEvent.clientX) - note.ticks, mouseMoveEvent.altKey)
|
|
336
|
+
})
|
|
337
|
+
};
|
|
338
|
+
const previousTrackIndex = currentNoteTrackIndex();
|
|
339
|
+
const previousNoteIndex = currentNoteIndex();
|
|
340
|
+
const targetTrackIndex = context.mode === "tracks" ? Math.floor(verticalViewPort().calculatePosition(mouseMoveEvent.clientY)) : previousTrackIndex;
|
|
341
|
+
if (targetTrackIndex === previousTrackIndex) {
|
|
342
|
+
context.onNoteChange?.(previousTrackIndex, previousNoteIndex, updatedNote);
|
|
343
|
+
} else {
|
|
344
|
+
solidJs.batch(() => {
|
|
345
|
+
if (context.onInsertNote) {
|
|
346
|
+
context.onRemoveNote?.(previousTrackIndex, previousNoteIndex);
|
|
347
|
+
const newNoteIndex = context.onInsertNote(targetTrackIndex, updatedNote);
|
|
348
|
+
setCurrentNoteTrackIndex(targetTrackIndex);
|
|
349
|
+
setCurrentNoteIndex(newNoteIndex);
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
const handleMouseUp = () => {
|
|
355
|
+
setIsDragging(false);
|
|
356
|
+
setCurrentNoteIndex(-1);
|
|
357
|
+
setCurrentNoteTrackIndex(-1);
|
|
358
|
+
window.removeEventListener("mousemove", handleMouseMove);
|
|
359
|
+
window.removeEventListener("mouseup", handleMouseUp);
|
|
360
|
+
};
|
|
361
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
362
|
+
window.addEventListener("mouseup", handleMouseUp);
|
|
363
|
+
};
|
|
364
|
+
_el$2.$$dblclick = event => {
|
|
365
|
+
event.stopPropagation();
|
|
366
|
+
context.onRemoveNote?.(trackIndex(), noteIndex());
|
|
367
|
+
};
|
|
368
|
+
_el$2.$$mousemove = event => {
|
|
369
|
+
if (isDragging()) return;
|
|
370
|
+
event.stopPropagation();
|
|
371
|
+
const relativeX = horizontalViewPort().calculatePixelValue(horizontalViewPort().calculatePosition(event.clientX));
|
|
372
|
+
const noteStartX = horizontalViewPort().calculatePixelValue(note.ticks);
|
|
373
|
+
const noteEndX = horizontalViewPort().calculatePixelValue(note.ticks + note.durationTicks);
|
|
374
|
+
setNoteDragMode(relativeX - noteStartX < 3 ? "trimStart" : noteEndX - relativeX < 3 ? "trimEnd" : "move");
|
|
375
|
+
};
|
|
376
|
+
web.setAttribute(_el$2, "draggable", false);
|
|
377
|
+
web.effect(_p$ => {
|
|
378
|
+
const _v$ = getClasses(noteDragMode()).join(" "),
|
|
379
|
+
_v$2 = `rgba(255,0,0, ${(128 + note.velocity) / 256})`,
|
|
380
|
+
_v$3 = `${verticalVirtualDimensions().offset}px`,
|
|
381
|
+
_v$4 = `${verticalVirtualDimensions().size}px`,
|
|
382
|
+
_v$5 = `${horizontalDimensions().offset}px`,
|
|
383
|
+
_v$6 = `${horizontalDimensions().size}px`;
|
|
384
|
+
_v$ !== _p$._v$ && web.className(_el$2, _p$._v$ = _v$);
|
|
385
|
+
_v$2 !== _p$._v$2 && _el$2.style.setProperty("background-color", _p$._v$2 = _v$2);
|
|
386
|
+
_v$3 !== _p$._v$3 && _el$2.style.setProperty("top", _p$._v$3 = _v$3);
|
|
387
|
+
_v$4 !== _p$._v$4 && _el$2.style.setProperty("height", _p$._v$4 = _v$4);
|
|
388
|
+
_v$5 !== _p$._v$5 && _el$2.style.setProperty("left", _p$._v$5 = _v$5);
|
|
389
|
+
_v$6 !== _p$._v$6 && _el$2.style.setProperty("width", _p$._v$6 = _v$6);
|
|
390
|
+
return _p$;
|
|
391
|
+
}, {
|
|
392
|
+
_v$: undefined,
|
|
393
|
+
_v$2: undefined,
|
|
394
|
+
_v$3: undefined,
|
|
395
|
+
_v$4: undefined,
|
|
396
|
+
_v$5: undefined,
|
|
397
|
+
_v$6: undefined
|
|
398
|
+
});
|
|
399
|
+
return _el$2;
|
|
400
|
+
}
|
|
249
401
|
});
|
|
250
|
-
}
|
|
251
|
-
const handleMouseUp = () => {
|
|
252
|
-
setIsDragging(false);
|
|
253
|
-
window.removeEventListener("mousemove", handleMouseMove);
|
|
254
|
-
window.removeEventListener("mouseup", handleMouseUp);
|
|
255
|
-
};
|
|
256
|
-
window.addEventListener("mousemove", handleMouseMove);
|
|
257
|
-
window.addEventListener("mouseup", handleMouseUp);
|
|
258
|
-
};
|
|
259
|
-
_el$2.$$dblclick = event => {
|
|
260
|
-
event.stopPropagation();
|
|
261
|
-
context.onRemoveNote?.(index);
|
|
262
|
-
};
|
|
263
|
-
_el$2.$$mousemove = event => {
|
|
264
|
-
if (isDragging()) return;
|
|
265
|
-
event.stopPropagation();
|
|
266
|
-
const relativeX = horizontalViewPort().calculatePixelValue(horizontalViewPort().calculatePosition(event.clientX));
|
|
267
|
-
const noteStartX = horizontalViewPort().calculatePixelValue(note().ticks);
|
|
268
|
-
const noteEndX = horizontalViewPort().calculatePixelValue(note().ticks + note().durationTicks);
|
|
269
|
-
setNoteDragMode(relativeX - noteStartX < 3 ? "trimStart" : noteEndX - relativeX < 3 ? "trimEnd" : "move");
|
|
270
|
-
};
|
|
271
|
-
web.effect(_p$ => {
|
|
272
|
-
const _v$ = getClasses(noteDragMode()).join(" "),
|
|
273
|
-
_v$2 = {
|
|
274
|
-
"background-color": `rgba(255,0,0, ${(128 + note().velocity) / 256})`,
|
|
275
|
-
...(context.condensed ? {
|
|
276
|
-
top: 0,
|
|
277
|
-
height: "100%"
|
|
278
|
-
} : {
|
|
279
|
-
top: `${verticalVirtualDimensions().offset}px`,
|
|
280
|
-
height: `${verticalVirtualDimensions().size}px`
|
|
281
|
-
}),
|
|
282
|
-
left: `${horizontalDimensions().offset}px`,
|
|
283
|
-
width: `${horizontalDimensions().size}px`
|
|
284
|
-
};
|
|
285
|
-
_v$ !== _p$._v$ && web.className(_el$2, _p$._v$ = _v$);
|
|
286
|
-
_p$._v$2 = web.style(_el$2, _v$2, _p$._v$2);
|
|
287
|
-
return _p$;
|
|
288
|
-
}, {
|
|
289
|
-
_v$: undefined,
|
|
290
|
-
_v$2: undefined
|
|
402
|
+
}
|
|
291
403
|
});
|
|
292
|
-
return _el$2;
|
|
293
404
|
}
|
|
294
405
|
});
|
|
295
406
|
}
|
|
@@ -403,74 +514,11 @@ const ScrollContainer = props => {
|
|
|
403
514
|
})();
|
|
404
515
|
};
|
|
405
516
|
|
|
406
|
-
var css_248z$1 = ".
|
|
407
|
-
var styles$1 = {"
|
|
517
|
+
var css_248z$1 = ".PianoRollGrid-module_PianoRollGrid__tG119 {\n position: relative;\n width: 100%;\n height: 100%;\n}\n\n.PianoRollGrid-module_PianoRollGrid-Row__nRMCs {\n position: absolute;\n border-style: solid;\n border-color: gray;\n}\n\n.PianoRollGrid-module_PianoRollGrid-Time__jLz3E {\n position: absolute;\n box-sizing: border-box;\n top: 0px;\n height: 100%;\n border-left-style: solid;\n border-left-width: 0.5px;\n}\n";
|
|
518
|
+
var styles$1 = {"PianoRollGrid":"PianoRollGrid-module_PianoRollGrid__tG119","PianoRollGrid-Row":"PianoRollGrid-module_PianoRollGrid-Row__nRMCs","PianoRollGrid-Time":"PianoRollGrid-module_PianoRollGrid-Time__jLz3E"};
|
|
408
519
|
styleInject(css_248z$1);
|
|
409
520
|
|
|
410
521
|
const _tmpl$$5 = /*#__PURE__*/web.template(`<div></div>`, 2);
|
|
411
|
-
const PianoRollKeys = () => {
|
|
412
|
-
const viewPort = solidJs.createMemo(() => useViewPortDimension("vertical"));
|
|
413
|
-
return (() => {
|
|
414
|
-
const _el$ = _tmpl$$5.cloneNode(true);
|
|
415
|
-
web.insert(_el$, web.createComponent(solidJs.Index, {
|
|
416
|
-
each: keys,
|
|
417
|
-
children: key => {
|
|
418
|
-
const virtualDimensions = solidJs.createMemo(() => viewPort().calculatePixelDimensions(127 - key().number, 1));
|
|
419
|
-
return web.createComponent(solidJs.Show, {
|
|
420
|
-
get when() {
|
|
421
|
-
return virtualDimensions().size > 0;
|
|
422
|
-
},
|
|
423
|
-
get children() {
|
|
424
|
-
const _el$2 = _tmpl$$5.cloneNode(true);
|
|
425
|
-
web.effect(_p$ => {
|
|
426
|
-
const _v$ = {
|
|
427
|
-
[styles$1["Key"]]: true,
|
|
428
|
-
[styles$1["black"]]: key().isBlack,
|
|
429
|
-
[styles$1["white"]]: !key().isBlack,
|
|
430
|
-
[styles$1["whiteAndNextIsWhite"]]: !key().isBlack && !blackKeys.includes((key().number + 1) % 12),
|
|
431
|
-
[styles$1["whiteAndPreviousIsWhite"]]: !key().isBlack && !blackKeys.includes((key().number - 1) % 12)
|
|
432
|
-
},
|
|
433
|
-
_v$2 = key().name,
|
|
434
|
-
_v$3 = key().number % 12,
|
|
435
|
-
_v$4 = `${virtualDimensions().offset}px`,
|
|
436
|
-
_v$5 = `${virtualDimensions().size}px`;
|
|
437
|
-
_p$._v$ = web.classList(_el$2, _v$, _p$._v$);
|
|
438
|
-
_v$2 !== _p$._v$2 && web.setAttribute(_el$2, "title", _p$._v$2 = _v$2);
|
|
439
|
-
_v$3 !== _p$._v$3 && web.setAttribute(_el$2, "data-index", _p$._v$3 = _v$3);
|
|
440
|
-
_v$4 !== _p$._v$4 && _el$2.style.setProperty("top", _p$._v$4 = _v$4);
|
|
441
|
-
_v$5 !== _p$._v$5 && _el$2.style.setProperty("height", _p$._v$5 = _v$5);
|
|
442
|
-
return _p$;
|
|
443
|
-
}, {
|
|
444
|
-
_v$: undefined,
|
|
445
|
-
_v$2: undefined,
|
|
446
|
-
_v$3: undefined,
|
|
447
|
-
_v$4: undefined,
|
|
448
|
-
_v$5: undefined
|
|
449
|
-
});
|
|
450
|
-
return _el$2;
|
|
451
|
-
}
|
|
452
|
-
});
|
|
453
|
-
}
|
|
454
|
-
}));
|
|
455
|
-
web.effect(() => web.className(_el$, styles$1.PianoRollKeys));
|
|
456
|
-
return _el$;
|
|
457
|
-
})();
|
|
458
|
-
};
|
|
459
|
-
const blackKeys = [1, 3, 6, 8, 10];
|
|
460
|
-
const keyNames = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
|
|
461
|
-
const keys = Array.from({
|
|
462
|
-
length: 128
|
|
463
|
-
}).map((_, index) => ({
|
|
464
|
-
number: index,
|
|
465
|
-
name: `${keyNames[index % 12]} ${Math.floor(index / 12) - 2}`,
|
|
466
|
-
isBlack: blackKeys.includes(index % 12)
|
|
467
|
-
}));
|
|
468
|
-
|
|
469
|
-
var css_248z = ".PianoRollGrid-module_PianoRollGrid__tG119 {\n position: relative;\n width: 100%;\n height: 100%;\n}\n\n.PianoRollGrid-module_PianoRollGrid-Key__VRbiB {\n position: absolute;\n border-style: solid;\n border-color: gray;\n}\n\n.PianoRollGrid-module_PianoRollGrid-Time__jLz3E {\n position: absolute;\n box-sizing: border-box;\n top: 0px;\n height: 100%;\n border-left-style: solid;\n border-left-width: 0.5px;\n}\n";
|
|
470
|
-
var styles = {"PianoRollGrid":"PianoRollGrid-module_PianoRollGrid__tG119","PianoRollGrid-Key":"PianoRollGrid-module_PianoRollGrid-Key__VRbiB","PianoRollGrid-Time":"PianoRollGrid-module_PianoRollGrid-Time__jLz3E"};
|
|
471
|
-
styleInject(css_248z);
|
|
472
|
-
|
|
473
|
-
const _tmpl$$4 = /*#__PURE__*/web.template(`<div></div>`, 2);
|
|
474
522
|
const PianoRollGrid = () => {
|
|
475
523
|
const context = usePianoRollContext();
|
|
476
524
|
const verticalViewPort = solidJs.createMemo(() => useViewPortDimension("vertical"));
|
|
@@ -500,7 +548,7 @@ const PianoRollGrid = () => {
|
|
|
500
548
|
}));
|
|
501
549
|
});
|
|
502
550
|
return (() => {
|
|
503
|
-
const _el$ = _tmpl$$
|
|
551
|
+
const _el$ = _tmpl$$5.cloneNode(true);
|
|
504
552
|
web.insert(_el$, web.createComponent(solidJs.Index, {
|
|
505
553
|
get each() {
|
|
506
554
|
return gridArray();
|
|
@@ -512,9 +560,9 @@ const PianoRollGrid = () => {
|
|
|
512
560
|
return virtualDimensions().size > 0;
|
|
513
561
|
},
|
|
514
562
|
get children() {
|
|
515
|
-
const _el$2 = _tmpl$$
|
|
563
|
+
const _el$2 = _tmpl$$5.cloneNode(true);
|
|
516
564
|
web.effect(_p$ => {
|
|
517
|
-
const _v$ = styles["PianoRollGrid-Time"],
|
|
565
|
+
const _v$ = styles$1["PianoRollGrid-Time"],
|
|
518
566
|
_v$2 = Math.ceil((entry().index + 1 * selectedGridDivisorTicks()) / measureTicks()) % 2 === 0 ? "#ddd" : "#ccc",
|
|
519
567
|
_v$3 = `${virtualDimensions().offset}px`,
|
|
520
568
|
_v$4 = `${virtualDimensions().size}px`,
|
|
@@ -539,7 +587,7 @@ const PianoRollGrid = () => {
|
|
|
539
587
|
}), null);
|
|
540
588
|
web.insert(_el$, web.createComponent(solidJs.Show, {
|
|
541
589
|
get when() {
|
|
542
|
-
return
|
|
590
|
+
return context.mode === "keys";
|
|
543
591
|
},
|
|
544
592
|
get children() {
|
|
545
593
|
return web.createComponent(solidJs.Index, {
|
|
@@ -551,10 +599,10 @@ const PianoRollGrid = () => {
|
|
|
551
599
|
return virtualDimensions().size > 0;
|
|
552
600
|
},
|
|
553
601
|
get children() {
|
|
554
|
-
const _el$3 = _tmpl$$
|
|
602
|
+
const _el$3 = _tmpl$$5.cloneNode(true);
|
|
555
603
|
_el$3.style.setProperty("width", "100%");
|
|
556
604
|
web.effect(_p$ => {
|
|
557
|
-
const _v$6 = styles["PianoRollGrid-
|
|
605
|
+
const _v$6 = styles$1["PianoRollGrid-Row"],
|
|
558
606
|
_v$7 = `${virtualDimensions().offset}px`,
|
|
559
607
|
_v$8 = `${virtualDimensions().size}px`,
|
|
560
608
|
_v$9 = key().isBlack ? "rgba(0,0,0,0.2)" : "none",
|
|
@@ -579,35 +627,53 @@ const PianoRollGrid = () => {
|
|
|
579
627
|
});
|
|
580
628
|
}
|
|
581
629
|
}), null);
|
|
582
|
-
web.
|
|
630
|
+
web.insert(_el$, web.createComponent(solidJs.Show, {
|
|
631
|
+
get when() {
|
|
632
|
+
return context.mode === "tracks";
|
|
633
|
+
},
|
|
634
|
+
get children() {
|
|
635
|
+
return web.createComponent(solidJs.For, {
|
|
636
|
+
get each() {
|
|
637
|
+
return context.tracks;
|
|
638
|
+
},
|
|
639
|
+
children: (track, index) => {
|
|
640
|
+
const virtualDimensions = solidJs.createMemo(() => verticalViewPort().calculatePixelDimensions(index(), 1));
|
|
641
|
+
return web.createComponent(solidJs.Show, {
|
|
642
|
+
get when() {
|
|
643
|
+
return virtualDimensions().size > 0;
|
|
644
|
+
},
|
|
645
|
+
get children() {
|
|
646
|
+
const _el$4 = _tmpl$$5.cloneNode(true);
|
|
647
|
+
_el$4.style.setProperty("width", "100%");
|
|
648
|
+
_el$4.style.setProperty("border-width", "0");
|
|
649
|
+
web.effect(_p$ => {
|
|
650
|
+
const _v$11 = styles$1["PianoRollGrid-Row"],
|
|
651
|
+
_v$12 = `${virtualDimensions().offset}px`,
|
|
652
|
+
_v$13 = `${virtualDimensions().size}px`,
|
|
653
|
+
_v$14 = index() % 2 === 0 ? "rgba(0,0,0,0.2)" : "none";
|
|
654
|
+
_v$11 !== _p$._v$11 && web.className(_el$4, _p$._v$11 = _v$11);
|
|
655
|
+
_v$12 !== _p$._v$12 && _el$4.style.setProperty("top", _p$._v$12 = _v$12);
|
|
656
|
+
_v$13 !== _p$._v$13 && _el$4.style.setProperty("height", _p$._v$13 = _v$13);
|
|
657
|
+
_v$14 !== _p$._v$14 && _el$4.style.setProperty("background-color", _p$._v$14 = _v$14);
|
|
658
|
+
return _p$;
|
|
659
|
+
}, {
|
|
660
|
+
_v$11: undefined,
|
|
661
|
+
_v$12: undefined,
|
|
662
|
+
_v$13: undefined,
|
|
663
|
+
_v$14: undefined
|
|
664
|
+
});
|
|
665
|
+
return _el$4;
|
|
666
|
+
}
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
}), null);
|
|
672
|
+
web.effect(() => web.className(_el$, styles$1.PianoRollGrid));
|
|
583
673
|
return _el$;
|
|
584
674
|
})();
|
|
585
675
|
};
|
|
586
676
|
|
|
587
|
-
const useNotes = () => {
|
|
588
|
-
const [notes, onNotesChange] = solidJs.createSignal([]);
|
|
589
|
-
const onNoteChange = (index, note) => {
|
|
590
|
-
onNotesChange([...notes().slice(0, index), note, ...notes().splice(index + 1)]);
|
|
591
|
-
};
|
|
592
|
-
const onInsertNote = note => {
|
|
593
|
-
const index = Math.max(notes().findIndex(({
|
|
594
|
-
ticks
|
|
595
|
-
}) => ticks > note.ticks), 0);
|
|
596
|
-
onNotesChange([...notes().slice(0, index), note, ...notes().splice(index)]);
|
|
597
|
-
return index;
|
|
598
|
-
};
|
|
599
|
-
const onRemoveNote = index => {
|
|
600
|
-
onNotesChange([...notes().slice(0, index), ...notes().splice(index + 1)]);
|
|
601
|
-
};
|
|
602
|
-
return {
|
|
603
|
-
notes,
|
|
604
|
-
onNotesChange,
|
|
605
|
-
onNoteChange,
|
|
606
|
-
onInsertNote,
|
|
607
|
-
onRemoveNote
|
|
608
|
-
};
|
|
609
|
-
};
|
|
610
|
-
|
|
611
677
|
const defaultRect = {
|
|
612
678
|
left: 0,
|
|
613
679
|
width: 0,
|
|
@@ -636,11 +702,11 @@ function useBoundingClientRect(containerRef) {
|
|
|
636
702
|
return boundingClientRect;
|
|
637
703
|
}
|
|
638
704
|
|
|
639
|
-
const _tmpl$$
|
|
705
|
+
const _tmpl$$4 = /*#__PURE__*/web.template(`<input min="1" max="11" step="0.01">`, 1);
|
|
640
706
|
const VerticalZoomControl = props => {
|
|
641
707
|
const context = usePianoRollContext();
|
|
642
708
|
return (() => {
|
|
643
|
-
const _el$ = _tmpl$$
|
|
709
|
+
const _el$ = _tmpl$$4.cloneNode(true);
|
|
644
710
|
web.spread(_el$, web.mergeProps(props, {
|
|
645
711
|
get value() {
|
|
646
712
|
return context.verticalZoom;
|
|
@@ -664,224 +730,91 @@ const VerticalZoomControl = props => {
|
|
|
664
730
|
})();
|
|
665
731
|
};
|
|
666
732
|
|
|
667
|
-
const _tmpl$$
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
_tmpl$4 = /*#__PURE__*/web.template(`<div></div>`, 2),
|
|
671
|
-
_tmpl$5 = /*#__PURE__*/web.template(`<li></li>`, 2);
|
|
672
|
-
const MultiTrackPianoRoll = allProps => {
|
|
673
|
-
const selectedTrack = solidJs.createMemo(() => allProps.tracks[allProps.selectedTrackIndex]);
|
|
674
|
-
const condensed = solidJs.createMemo(() => !selectedTrack());
|
|
675
|
-
const [ownProps, restProps] = solidJs.splitProps(allProps, ["tracks", "selectedTrackIndex"]);
|
|
676
|
-
const [contextProps, divProps] = splitContextProps(solidJs.mergeProps(restProps, {
|
|
677
|
-
notes: [],
|
|
678
|
-
condensed: false,
|
|
679
|
-
onNoteChange: () => undefined,
|
|
680
|
-
onInsertNote: () => -1,
|
|
681
|
-
onRemoveNote: () => undefined
|
|
682
|
-
}));
|
|
683
|
-
const [scrollerRef, setScrollerRef] = solidJs.createSignal();
|
|
684
|
-
const clientRect = useBoundingClientRect(scrollerRef);
|
|
685
|
-
const zoomFactor = 500;
|
|
686
|
-
const minZoom = solidJs.createMemo(() => 1 / (zoomFactor / clientRect().width));
|
|
687
|
-
const maxZoom = solidJs.createMemo(() => 500 * (zoomFactor / clientRect().width));
|
|
688
|
-
const minVerticalZoom = solidJs.createMemo(() => 1 / (zoomFactor / clientRect().height));
|
|
689
|
-
const maxVerticalZoom = solidJs.createMemo(() => 10 * (zoomFactor / clientRect().height));
|
|
733
|
+
const _tmpl$$3 = /*#__PURE__*/web.template(`<input max="500" min="1" step="0.01">`, 1);
|
|
734
|
+
const HorizontalZoomControl = props => {
|
|
735
|
+
const context = usePianoRollContext();
|
|
690
736
|
return (() => {
|
|
691
|
-
const _el$ = _tmpl
|
|
692
|
-
web.spread(_el$, web.mergeProps(
|
|
737
|
+
const _el$ = _tmpl$$3.cloneNode(true);
|
|
738
|
+
web.spread(_el$, web.mergeProps(props, {
|
|
739
|
+
get value() {
|
|
740
|
+
return context.zoom;
|
|
741
|
+
},
|
|
742
|
+
"onInput": event => context.onZoomChange?.(event.currentTarget.valueAsNumber),
|
|
743
|
+
"type": "range",
|
|
693
744
|
get style() {
|
|
694
745
|
return {
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
"flex-direction": "row",
|
|
699
|
-
overflow: "hidden",
|
|
700
|
-
...(typeof divProps.style === "object" && divProps.style)
|
|
746
|
+
"margin-left": "50px",
|
|
747
|
+
"margin-right": "16px",
|
|
748
|
+
...(typeof props.style === "object" && props.style)
|
|
701
749
|
};
|
|
702
750
|
}
|
|
703
|
-
}), false,
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
751
|
+
}), false, false);
|
|
752
|
+
return _el$;
|
|
753
|
+
})();
|
|
754
|
+
};
|
|
755
|
+
|
|
756
|
+
var css_248z = ".PianoRollTrackList-module_PianoRollTrackList__pyuxQ {\n position: relative;\n height: 100%;\n flex: 1;\n}\n\n.PianoRollTrackList-module_Track__VZFIg {\n border-width: 0px;\n position: absolute;\n box-sizing: border-box;\n width: 100%;\n border-color: #000;\n border-style: solid;\n border-right-width: 1px;\n border-bottom-width: 1px;\n}\n";
|
|
757
|
+
var styles = {"PianoRollTrackList":"PianoRollTrackList-module_PianoRollTrackList__pyuxQ","Track":"PianoRollTrackList-module_Track__VZFIg"};
|
|
758
|
+
styleInject(css_248z);
|
|
759
|
+
|
|
760
|
+
const _tmpl$$2 = /*#__PURE__*/web.template(`<div></div>`, 2),
|
|
761
|
+
_tmpl$2$1 = /*#__PURE__*/web.template(`<div> </div>`, 2);
|
|
762
|
+
const PianoRollTrackList = () => {
|
|
763
|
+
const viewPort = solidJs.createMemo(() => useViewPortDimension("vertical"));
|
|
764
|
+
const context = usePianoRollContext();
|
|
765
|
+
return (() => {
|
|
766
|
+
const _el$ = _tmpl$$2.cloneNode(true);
|
|
767
|
+
web.insert(_el$, web.createComponent(solidJs.Index, {
|
|
768
|
+
get each() {
|
|
769
|
+
return context.tracks;
|
|
709
770
|
},
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
pixelSize: clientRect().width,
|
|
716
|
-
position: contextProps.position,
|
|
717
|
-
range: contextProps.duration,
|
|
718
|
-
zoom: contextProps.zoom * (zoomFactor / clientRect().width),
|
|
719
|
-
onPositionChange: contextProps.onPositionChange,
|
|
720
|
-
onZoomChange: zoom => contextProps.onZoomChange?.(clamp(zoom / (zoomFactor / clientRect().width), minZoom(), maxZoom()))
|
|
721
|
-
}),
|
|
722
|
-
vertical: () => ({
|
|
723
|
-
pixelOffset: clientRect().top,
|
|
724
|
-
pixelSize: clientRect().height,
|
|
725
|
-
position: contextProps.verticalPosition,
|
|
726
|
-
range: 128,
|
|
727
|
-
zoom: contextProps.verticalZoom * (zoomFactor / clientRect().height),
|
|
728
|
-
onPositionChange: contextProps.onVerticalPositionChange,
|
|
729
|
-
onZoomChange: verticalZoom => contextProps.onVerticalZoomChange?.(clamp(verticalZoom / (zoomFactor / clientRect().height), minVerticalZoom(), maxVerticalZoom()))
|
|
730
|
-
})
|
|
771
|
+
children: (track, index) => {
|
|
772
|
+
const virtualDimensions = solidJs.createMemo(() => viewPort().calculatePixelDimensions(context.mode === "tracks" ? index : index * 8, context.mode === "tracks" ? 1 : 8));
|
|
773
|
+
return web.createComponent(solidJs.Show, {
|
|
774
|
+
get when() {
|
|
775
|
+
return virtualDimensions().size > 0;
|
|
731
776
|
},
|
|
732
777
|
get children() {
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
_el$3.style.setProperty("position", "relative");
|
|
743
|
-
web.insert(_el$3, web.createComponent(solidJs.Index, {
|
|
744
|
-
get each() {
|
|
745
|
-
return allProps.tracks;
|
|
746
|
-
},
|
|
747
|
-
children: (track, noteIndex) => (() => {
|
|
748
|
-
const _el$7 = _tmpl$5.cloneNode(true);
|
|
749
|
-
_el$7.$$click = () => {
|
|
750
|
-
if (noteIndex === allProps.selectedTrackIndex) {
|
|
751
|
-
allProps.onSelectedTrackIndexChange(-1);
|
|
752
|
-
} else {
|
|
753
|
-
allProps.onSelectedTrackIndexChange(noteIndex);
|
|
754
|
-
}
|
|
755
|
-
};
|
|
756
|
-
_el$7.style.setProperty("width", "100%");
|
|
757
|
-
_el$7.style.setProperty("height", "30px");
|
|
758
|
-
_el$7.style.setProperty("list-style", "none");
|
|
759
|
-
_el$7.style.setProperty("display", "flex");
|
|
760
|
-
_el$7.style.setProperty("align-items", "center");
|
|
761
|
-
_el$7.style.setProperty("border-top", "1px black solid");
|
|
762
|
-
_el$7.style.setProperty("cursor", "pointer");
|
|
763
|
-
web.insert(_el$7, () => track().name);
|
|
764
|
-
web.effect(() => _el$7.style.setProperty("background", noteIndex === allProps.selectedTrackIndex ? "lightgray" : "none"));
|
|
765
|
-
return _el$7;
|
|
766
|
-
})()
|
|
767
|
-
}));
|
|
768
|
-
web.insert(_el$2, web.createComponent(solidJs.Show, {
|
|
769
|
-
get when() {
|
|
770
|
-
return !condensed();
|
|
771
|
-
},
|
|
772
|
-
get children() {
|
|
773
|
-
return web.createComponent(PianoRollKeys, {});
|
|
774
|
-
}
|
|
775
|
-
}), null);
|
|
776
|
-
return _el$2;
|
|
777
|
-
})(), (() => {
|
|
778
|
-
const _el$4 = _tmpl$3.cloneNode(true),
|
|
779
|
-
_el$5 = _el$4.firstChild;
|
|
780
|
-
_el$4.style.setProperty("flex", "1");
|
|
781
|
-
web.insert(_el$5, web.createComponent(ScrollContainer, {
|
|
782
|
-
ref: setScrollerRef,
|
|
783
|
-
get children() {
|
|
784
|
-
return [web.memo(() => allProps.children), (() => {
|
|
785
|
-
const _el$6 = _tmpl$2.cloneNode(true);
|
|
786
|
-
_el$6.style.setProperty("margin", "0");
|
|
787
|
-
_el$6.style.setProperty("margin-block-start", "0");
|
|
788
|
-
_el$6.style.setProperty("padding-inline-start", "0");
|
|
789
|
-
web.insert(_el$6, web.createComponent(solidJs.Index, {
|
|
790
|
-
get each() {
|
|
791
|
-
return allProps.tracks;
|
|
792
|
-
},
|
|
793
|
-
children: (track, trackIndex) => {
|
|
794
|
-
const notes = useNotes();
|
|
795
|
-
solidJs.createEffect(() => {
|
|
796
|
-
notes.onNotesChange(track().notes);
|
|
797
|
-
});
|
|
798
|
-
const [context, setContext] = store.createStore({
|
|
799
|
-
...contextProps
|
|
800
|
-
});
|
|
801
|
-
solidJs.createEffect(() => {
|
|
802
|
-
setContext({
|
|
803
|
-
...contextProps,
|
|
804
|
-
condensed: condensed(),
|
|
805
|
-
notes: track()?.notes,
|
|
806
|
-
onNoteChange: (noteIndex, note) => allProps?.onNoteChange?.(trackIndex, noteIndex, note),
|
|
807
|
-
onInsertNote: note => allProps.onInsertNote?.(trackIndex, note) ?? -1,
|
|
808
|
-
onRemoveNote: noteIndex => allProps.onRemoveNote?.(trackIndex, noteIndex)
|
|
809
|
-
});
|
|
810
|
-
});
|
|
811
|
-
const verticalViewPort = useViewPortDimension("vertical");
|
|
812
|
-
return web.createComponent(solidJs.Show, {
|
|
813
|
-
get when() {
|
|
814
|
-
return condensed() || allProps.selectedTrackIndex === trackIndex;
|
|
815
|
-
},
|
|
816
|
-
get children() {
|
|
817
|
-
return web.createComponent(PianoRollContextProvider, {
|
|
818
|
-
value: context,
|
|
819
|
-
get children() {
|
|
820
|
-
const _el$8 = _tmpl$5.cloneNode(true);
|
|
821
|
-
_el$8.style.setProperty("display", "flex");
|
|
822
|
-
_el$8.style.setProperty("position", "relative");
|
|
823
|
-
_el$8.style.setProperty("list-style", "none");
|
|
824
|
-
_el$8.style.setProperty("flex-direction", "row");
|
|
825
|
-
_el$8.style.setProperty("border-top", "1px black solid");
|
|
826
|
-
web.insert(_el$8, web.createComponent(PianoRollNotes, {}), null);
|
|
827
|
-
web.insert(_el$8, web.createComponent(PianoRollGrid, {}), null);
|
|
828
|
-
web.effect(() => _el$8.style.setProperty("height", condensed() ? "30px" : `${verticalViewPort.pixelSize}px`));
|
|
829
|
-
return _el$8;
|
|
830
|
-
}
|
|
831
|
-
});
|
|
832
|
-
}
|
|
833
|
-
});
|
|
834
|
-
}
|
|
835
|
-
}));
|
|
836
|
-
return _el$6;
|
|
837
|
-
})()];
|
|
838
|
-
}
|
|
839
|
-
}), null);
|
|
840
|
-
web.insert(_el$5, web.createComponent(solidJs.Show, {
|
|
841
|
-
get when() {
|
|
842
|
-
return !condensed();
|
|
843
|
-
},
|
|
844
|
-
get children() {
|
|
845
|
-
return web.createComponent(VerticalZoomControl, {
|
|
846
|
-
get value() {
|
|
847
|
-
return contextProps.verticalZoom;
|
|
848
|
-
},
|
|
849
|
-
onInput: event => contextProps.onVerticalZoomChange?.(event.currentTarget.valueAsNumber)
|
|
850
|
-
});
|
|
851
|
-
}
|
|
852
|
-
}), null);
|
|
853
|
-
web.insert(_el$4, web.createComponent(HorizontalZoomControl, {
|
|
854
|
-
style: {
|
|
855
|
-
width: "100%",
|
|
856
|
-
"margin-left": 0
|
|
857
|
-
},
|
|
858
|
-
get value() {
|
|
859
|
-
return contextProps.zoom;
|
|
778
|
+
const _el$2 = _tmpl$2$1.cloneNode(true),
|
|
779
|
+
_el$3 = _el$2.firstChild;
|
|
780
|
+
_el$2.$$click = () => context.onSelectedTrackIndexChange?.(index);
|
|
781
|
+
_el$2.style.setProperty("cursor", "pointer");
|
|
782
|
+
web.insert(_el$2, index, _el$3);
|
|
783
|
+
web.insert(_el$2, () => track().name || "[unnamed track]", null);
|
|
784
|
+
web.effect(_p$ => {
|
|
785
|
+
const _v$ = {
|
|
786
|
+
[styles["Track"]]: true
|
|
860
787
|
},
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
788
|
+
_v$2 = track().name,
|
|
789
|
+
_v$3 = `${virtualDimensions().offset}px`,
|
|
790
|
+
_v$4 = `${virtualDimensions().size}px`,
|
|
791
|
+
_v$5 = index === context.selectedTrackIndex ? "gray" : "lightgrey";
|
|
792
|
+
_p$._v$ = web.classList(_el$2, _v$, _p$._v$);
|
|
793
|
+
_v$2 !== _p$._v$2 && web.setAttribute(_el$2, "title", _p$._v$2 = _v$2);
|
|
794
|
+
_v$3 !== _p$._v$3 && _el$2.style.setProperty("top", _p$._v$3 = _v$3);
|
|
795
|
+
_v$4 !== _p$._v$4 && _el$2.style.setProperty("height", _p$._v$4 = _v$4);
|
|
796
|
+
_v$5 !== _p$._v$5 && _el$2.style.setProperty("background", _p$._v$5 = _v$5);
|
|
797
|
+
return _p$;
|
|
798
|
+
}, {
|
|
799
|
+
_v$: undefined,
|
|
800
|
+
_v$2: undefined,
|
|
801
|
+
_v$3: undefined,
|
|
802
|
+
_v$4: undefined,
|
|
803
|
+
_v$5: undefined
|
|
804
|
+
});
|
|
805
|
+
return _el$2;
|
|
875
806
|
}
|
|
876
807
|
});
|
|
877
808
|
}
|
|
878
809
|
}));
|
|
810
|
+
web.effect(() => web.className(_el$, styles.PianoRollTrackList));
|
|
879
811
|
return _el$;
|
|
880
812
|
})();
|
|
881
813
|
};
|
|
882
814
|
web.delegateEvents(["click"]);
|
|
883
815
|
|
|
884
|
-
const _tmpl$$1 = /*#__PURE__*/web.template(`<div
|
|
816
|
+
const _tmpl$$1 = /*#__PURE__*/web.template(`<div></div>`, 2),
|
|
817
|
+
_tmpl$2 = /*#__PURE__*/web.template(`<div><div></div></div>`, 4);
|
|
885
818
|
const PianoRoll = allProps => {
|
|
886
819
|
const [contextProps, divProps] = splitContextProps(allProps);
|
|
887
820
|
const [scrollerRef, setScrollerRef] = solidJs.createSignal();
|
|
@@ -891,14 +824,20 @@ const PianoRoll = allProps => {
|
|
|
891
824
|
const maxZoom = solidJs.createMemo(() => 500 * (zoomFactor / clientRect().width));
|
|
892
825
|
const minVerticalZoom = solidJs.createMemo(() => 1 / (zoomFactor / clientRect().height));
|
|
893
826
|
const maxVerticalZoom = solidJs.createMemo(() => 10 * (zoomFactor / clientRect().height));
|
|
827
|
+
solidJs.createEffect(isInitial => {
|
|
828
|
+
if (isInitial) return false;
|
|
829
|
+
if (contextProps.mode === "tracks") {
|
|
830
|
+
contextProps.onVerticalPositionChange?.(0);
|
|
831
|
+
}
|
|
832
|
+
}, true);
|
|
894
833
|
return web.createComponent(PianoRollContextProvider, {
|
|
895
834
|
value: contextProps,
|
|
896
835
|
get children() {
|
|
897
|
-
const _el$ = _tmpl
|
|
836
|
+
const _el$ = _tmpl$2.cloneNode(true),
|
|
898
837
|
_el$2 = _el$.firstChild;
|
|
899
838
|
web.spread(_el$, web.mergeProps(divProps, {
|
|
900
839
|
get ["class"]() {
|
|
901
|
-
return styles$
|
|
840
|
+
return styles$4.PianoRoll;
|
|
902
841
|
}
|
|
903
842
|
}), false, true);
|
|
904
843
|
web.insert(_el$2, web.createComponent(ScrollZoomViewPort, {
|
|
@@ -916,14 +855,35 @@ const PianoRoll = allProps => {
|
|
|
916
855
|
pixelOffset: clientRect().top,
|
|
917
856
|
pixelSize: clientRect().height,
|
|
918
857
|
position: contextProps.verticalPosition,
|
|
919
|
-
range: 128,
|
|
858
|
+
range: contextProps.mode === "keys" ? 128 : Math.max(contextProps.tracks.length, 16),
|
|
920
859
|
zoom: contextProps.verticalZoom * (zoomFactor / clientRect().height),
|
|
921
860
|
onPositionChange: contextProps.onVerticalPositionChange,
|
|
922
861
|
onZoomChange: verticalZoom => contextProps.onVerticalZoomChange?.(clamp(verticalZoom / (zoomFactor / clientRect().height), minVerticalZoom(), maxVerticalZoom()))
|
|
923
862
|
})
|
|
924
863
|
},
|
|
925
864
|
get children() {
|
|
926
|
-
return [
|
|
865
|
+
return [(() => {
|
|
866
|
+
const _el$3 = _tmpl$$1.cloneNode(true);
|
|
867
|
+
_el$3.style.setProperty("display", "flex");
|
|
868
|
+
_el$3.style.setProperty("width", "20%");
|
|
869
|
+
web.insert(_el$3, web.createComponent(solidJs.Show, {
|
|
870
|
+
get when() {
|
|
871
|
+
return allProps.showTrackList;
|
|
872
|
+
},
|
|
873
|
+
get children() {
|
|
874
|
+
return web.createComponent(PianoRollTrackList, {});
|
|
875
|
+
}
|
|
876
|
+
}), null);
|
|
877
|
+
web.insert(_el$3, web.createComponent(solidJs.Show, {
|
|
878
|
+
get when() {
|
|
879
|
+
return contextProps.mode === "keys";
|
|
880
|
+
},
|
|
881
|
+
get children() {
|
|
882
|
+
return web.createComponent(PianoRollKeys, {});
|
|
883
|
+
}
|
|
884
|
+
}), null);
|
|
885
|
+
return _el$3;
|
|
886
|
+
})(), web.createComponent(ScrollContainer, {
|
|
927
887
|
ref: setScrollerRef,
|
|
928
888
|
get children() {
|
|
929
889
|
return [web.memo(() => allProps.children), web.createComponent(PianoRollGrid, {}), web.createComponent(PianoRollNotes, {})];
|
|
@@ -946,7 +906,7 @@ const PianoRoll = allProps => {
|
|
|
946
906
|
return maxZoom();
|
|
947
907
|
}
|
|
948
908
|
}), null);
|
|
949
|
-
web.effect(() => web.className(_el$2, styles$
|
|
909
|
+
web.effect(() => web.className(_el$2, styles$4.PianoRollContainer));
|
|
950
910
|
return _el$;
|
|
951
911
|
}
|
|
952
912
|
});
|
|
@@ -1006,13 +966,37 @@ const PlayHead = allProps => {
|
|
|
1006
966
|
})();
|
|
1007
967
|
};
|
|
1008
968
|
|
|
969
|
+
const useNotes = () => {
|
|
970
|
+
const [notes, onNotesChange] = solidJs.createSignal([]);
|
|
971
|
+
const onNoteChange = (index, note) => {
|
|
972
|
+
onNotesChange([...notes().slice(0, index), note, ...notes().splice(index + 1)]);
|
|
973
|
+
};
|
|
974
|
+
const onInsertNote = note => {
|
|
975
|
+
const index = Math.max(notes().findIndex(({
|
|
976
|
+
ticks
|
|
977
|
+
}) => ticks > note.ticks), 0);
|
|
978
|
+
onNotesChange([...notes().slice(0, index), note, ...notes().splice(index)]);
|
|
979
|
+
return index;
|
|
980
|
+
};
|
|
981
|
+
const onRemoveNote = index => {
|
|
982
|
+
onNotesChange([...notes().slice(0, index), ...notes().splice(index + 1)]);
|
|
983
|
+
};
|
|
984
|
+
return {
|
|
985
|
+
notes,
|
|
986
|
+
onNotesChange,
|
|
987
|
+
onNoteChange,
|
|
988
|
+
onInsertNote,
|
|
989
|
+
onRemoveNote
|
|
990
|
+
};
|
|
991
|
+
};
|
|
992
|
+
|
|
1009
993
|
const usePianoRoll = () => {
|
|
1010
994
|
const [ppq, onPpqChange] = solidJs.createSignal(120);
|
|
1011
|
-
const [
|
|
995
|
+
const [mode, onModeChange] = solidJs.createSignal("tracks");
|
|
1012
996
|
const [position, onPositionChange] = solidJs.createSignal(0);
|
|
1013
997
|
const [zoom, onZoomChange] = solidJs.createSignal(10);
|
|
1014
998
|
const [verticalZoom, onVerticalZoomChange] = solidJs.createSignal(5);
|
|
1015
|
-
const [verticalPosition, onVerticalPositionChange] = solidJs.createSignal(
|
|
999
|
+
const [verticalPosition, onVerticalPositionChange] = solidJs.createSignal(44);
|
|
1016
1000
|
const [gridDivision, onGridDivisionChange] = solidJs.createSignal(4);
|
|
1017
1001
|
const [snapToGrid, onSnapToGridChange] = solidJs.createSignal(true);
|
|
1018
1002
|
const [duration, onDurationChange] = solidJs.createSignal(0);
|
|
@@ -1031,14 +1015,13 @@ const usePianoRoll = () => {
|
|
|
1031
1015
|
onGridDivisionChange,
|
|
1032
1016
|
snapToGrid,
|
|
1033
1017
|
onSnapToGridChange,
|
|
1034
|
-
|
|
1035
|
-
|
|
1018
|
+
mode,
|
|
1019
|
+
onModeChange,
|
|
1036
1020
|
duration,
|
|
1037
1021
|
onDurationChange
|
|
1038
1022
|
};
|
|
1039
1023
|
};
|
|
1040
1024
|
|
|
1041
|
-
exports.MultiTrackPianoRoll = MultiTrackPianoRoll;
|
|
1042
1025
|
exports.PianoRoll = PianoRoll;
|
|
1043
1026
|
exports.PlayHead = PlayHead;
|
|
1044
1027
|
exports.useNotes = useNotes;
|