solid-pianoroll 0.0.13 → 0.0.15
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 +451 -412
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +453 -414
- package/dist/esm/index.js.map +1 -1
- package/dist/source/PianoRoll.jsx +19 -3
- package/dist/source/PianoRollContext.jsx +5 -2
- package/dist/source/PianoRollGrid.jsx +25 -5
- package/dist/source/PianoRollNotes.jsx +117 -81
- package/dist/source/PianoRollTrackList.jsx +28 -0
- package/dist/source/PlayHead.jsx +47 -0
- package/dist/source/index.jsx +2 -2
- package/dist/source/usePianoRoll.js +4 -4
- package/dist/source/viewport/createViewPortDimension.js +1 -0
- package/dist/types/PianoRoll.d.ts +12 -8
- package/dist/types/PianoRollContext.d.ts +2 -1
- package/dist/types/PianoRollTrackList.d.ts +2 -0
- package/dist/types/PlayHead.d.ts +8 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/types.d.ts +4 -0
- package/dist/types/usePianoRoll.d.ts +2 -2
- package/dist/types/viewport/ScrollZoomViewPort.d.ts +1 -0
- package/dist/types/viewport/createViewPortDimension.d.ts +1 -0
- package/package.json +3 -2
- package/dist/source/MultiTrackPianoRoll.jsx +0 -136
- package/dist/types/MultiTrackPianoRoll.d.ts +0 -10
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,34 +40,16 @@ 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$$7.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}\n\n.PianoRollKeys-module_Key__jybNC {\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}\n\n.PianoRollKeys-module_black__7rncB {\n background: black;\n}\n\n.PianoRollKeys-module_white__fR2Lm {\n background: white;\n}\n\n.PianoRollKeys-module_whiteAndNextIsWhite__PN1O8 {\n border-top-width: 0.1px;\n}\n\n.PianoRollKeys-module_whiteAndPreviousIsWhite__-fP3q {\n border-bottom-width: 0.1px;\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","whiteAndNextIsWhite":"PianoRollKeys-module_whiteAndNextIsWhite__PN1O8","whiteAndPreviousIsWhite":"PianoRollKeys-module_whiteAndPreviousIsWhite__-fP3q"};
|
|
47
|
+
styleInject(css_248z$3);
|
|
67
48
|
|
|
68
49
|
function createViewPortDimension(getState) {
|
|
69
50
|
const getStateWithFunctions = () => ({
|
|
70
51
|
...getState(),
|
|
52
|
+
calculatePixelOffset,
|
|
71
53
|
calculatePixelValue,
|
|
72
54
|
calculatePosition,
|
|
73
55
|
calculatePixelDimensions,
|
|
@@ -136,11 +118,70 @@ const useViewPortDimension = name => {
|
|
|
136
118
|
return viewPort;
|
|
137
119
|
};
|
|
138
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 virtualDimensions = solidJs.createMemo(() => viewPort().calculatePixelDimensions(127 - key().number, 1));
|
|
130
|
+
return web.createComponent(solidJs.Show, {
|
|
131
|
+
get when() {
|
|
132
|
+
return virtualDimensions().size > 0;
|
|
133
|
+
},
|
|
134
|
+
get children() {
|
|
135
|
+
const _el$2 = _tmpl$$8.cloneNode(true);
|
|
136
|
+
web.effect(_p$ => {
|
|
137
|
+
const _v$ = {
|
|
138
|
+
[styles$3["Key"]]: true,
|
|
139
|
+
[styles$3["black"]]: key().isBlack,
|
|
140
|
+
[styles$3["white"]]: !key().isBlack,
|
|
141
|
+
[styles$3["whiteAndNextIsWhite"]]: !key().isBlack && !blackKeys.includes((key().number + 1) % 12),
|
|
142
|
+
[styles$3["whiteAndPreviousIsWhite"]]: !key().isBlack && !blackKeys.includes((key().number - 1) % 12)
|
|
143
|
+
},
|
|
144
|
+
_v$2 = key().name,
|
|
145
|
+
_v$3 = key().number % 12,
|
|
146
|
+
_v$4 = `${virtualDimensions().offset}px`,
|
|
147
|
+
_v$5 = `${virtualDimensions().size}px`;
|
|
148
|
+
_p$._v$ = web.classList(_el$2, _v$, _p$._v$);
|
|
149
|
+
_v$2 !== _p$._v$2 && web.setAttribute(_el$2, "title", _p$._v$2 = _v$2);
|
|
150
|
+
_v$3 !== _p$._v$3 && web.setAttribute(_el$2, "data-index", _p$._v$3 = _v$3);
|
|
151
|
+
_v$4 !== _p$._v$4 && _el$2.style.setProperty("top", _p$._v$4 = _v$4);
|
|
152
|
+
_v$5 !== _p$._v$5 && _el$2.style.setProperty("height", _p$._v$5 = _v$5);
|
|
153
|
+
return _p$;
|
|
154
|
+
}, {
|
|
155
|
+
_v$: undefined,
|
|
156
|
+
_v$2: undefined,
|
|
157
|
+
_v$3: undefined,
|
|
158
|
+
_v$4: undefined,
|
|
159
|
+
_v$5: undefined
|
|
160
|
+
});
|
|
161
|
+
return _el$2;
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}));
|
|
166
|
+
web.effect(() => web.className(_el$, styles$3.PianoRollKeys));
|
|
167
|
+
return _el$;
|
|
168
|
+
})();
|
|
169
|
+
};
|
|
170
|
+
const blackKeys = [1, 3, 6, 8, 10];
|
|
171
|
+
const keyNames = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
|
|
172
|
+
const keys = Array.from({
|
|
173
|
+
length: 128
|
|
174
|
+
}).map((_, index) => ({
|
|
175
|
+
number: index,
|
|
176
|
+
name: `${keyNames[index % 12]} ${Math.floor(index / 12) - 2}`,
|
|
177
|
+
isBlack: blackKeys.includes(index % 12)
|
|
178
|
+
}));
|
|
179
|
+
|
|
139
180
|
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}";
|
|
140
181
|
var styles$2 = {"PianoRollNotes":"PianoRollNotes-module_PianoRollNotes__6pF-y","Note":"PianoRollNotes-module_Note__-jxLb","trimStart":"PianoRollNotes-module_trimStart__vuBlj","trimEnd":"PianoRollNotes-module_trimEnd__zPdjr"};
|
|
141
182
|
styleInject(css_248z$2);
|
|
142
183
|
|
|
143
|
-
const _tmpl$$
|
|
184
|
+
const _tmpl$$7 = /*#__PURE__*/web.template(`<div></div>`, 2);
|
|
144
185
|
const PianoRollNotes = props => {
|
|
145
186
|
const context = usePianoRollContext();
|
|
146
187
|
const verticalViewPort = solidJs.createMemo(() => useViewPortDimension("vertical"));
|
|
@@ -149,10 +190,11 @@ const PianoRollNotes = props => {
|
|
|
149
190
|
const snapValueToGridIfEnabled = (value, altKey) => context.snapToGrid && !altKey ? Math.round(value / gridDivisionTicks()) * gridDivisionTicks() : value;
|
|
150
191
|
const insertOrUpdateNote = event => {
|
|
151
192
|
const position = horizontalViewPort().calculatePosition(event.clientX);
|
|
152
|
-
const
|
|
193
|
+
const existingNote = currentNote();
|
|
194
|
+
const midi = context.mode === "keys" ? 127 - Math.floor(verticalViewPort().calculatePosition(event.clientY)) : existingNote?.midi ?? 60;
|
|
195
|
+
const targetTrackIndex = context.mode === "tracks" ? Math.floor(verticalViewPort().calculatePosition(event.clientY)) : context.selectedTrackIndex ?? 0;
|
|
153
196
|
const eventPositionTicks = Math.floor(position / gridDivisionTicks()) * gridDivisionTicks();
|
|
154
197
|
const velocity = 127;
|
|
155
|
-
const existingNote = newNote();
|
|
156
198
|
const ticks = existingNote?.ticks ?? eventPositionTicks;
|
|
157
199
|
const durationTicks = existingNote?.ticks ? eventPositionTicks - existingNote?.ticks : gridDivisionTicks();
|
|
158
200
|
const note = {
|
|
@@ -162,25 +204,26 @@ const PianoRollNotes = props => {
|
|
|
162
204
|
velocity
|
|
163
205
|
};
|
|
164
206
|
if (existingNote) {
|
|
165
|
-
context.onNoteChange?.(
|
|
166
|
-
return
|
|
207
|
+
context.onNoteChange?.(currentNoteTrackIndex(), currentNoteIndex(), note);
|
|
208
|
+
return currentNoteIndex();
|
|
167
209
|
} else {
|
|
168
|
-
return context.onInsertNote?.(note) ?? -1;
|
|
210
|
+
return context.onInsertNote?.(targetTrackIndex, note) ?? -1;
|
|
169
211
|
}
|
|
170
212
|
};
|
|
171
213
|
const [isDragging, setIsDragging] = solidJs.createSignal(false);
|
|
172
214
|
const [noteDragMode, setNoteDragMode] = solidJs.createSignal();
|
|
173
|
-
const [
|
|
215
|
+
const [currentNoteIndex, setCurrentNoteIndex] = solidJs.createSignal(-1);
|
|
216
|
+
const [currentNoteTrackIndex, setCurrentNoteTrackIndex] = solidJs.createSignal(-1);
|
|
174
217
|
const [isMouseDown, setIsMouseDown] = solidJs.createSignal(false);
|
|
175
|
-
const
|
|
218
|
+
const currentNote = solidJs.createMemo(() => context.tracks[currentNoteTrackIndex()]?.notes[currentNoteIndex()]);
|
|
176
219
|
const getClasses = noteDragMode => {
|
|
177
220
|
return noteDragMode ? [styles$2.Note, styles$2[noteDragMode]] : [styles$2.Note];
|
|
178
221
|
};
|
|
179
222
|
return (() => {
|
|
180
|
-
const _el$ = _tmpl$$
|
|
223
|
+
const _el$ = _tmpl$$7.cloneNode(true);
|
|
181
224
|
_el$.$$click = event => {
|
|
182
|
-
if (
|
|
183
|
-
|
|
225
|
+
if (currentNote()) {
|
|
226
|
+
setCurrentNoteIndex(-1);
|
|
184
227
|
return;
|
|
185
228
|
}
|
|
186
229
|
if (!event.altKey) return;
|
|
@@ -201,94 +244,133 @@ const PianoRollNotes = props => {
|
|
|
201
244
|
return;
|
|
202
245
|
}
|
|
203
246
|
const index = insertOrUpdateNote(event);
|
|
204
|
-
|
|
247
|
+
setCurrentNoteIndex(index);
|
|
205
248
|
};
|
|
206
249
|
_el$.$$mousedown = event => {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
250
|
+
solidJs.batch(() => {
|
|
251
|
+
setIsMouseDown(true);
|
|
252
|
+
const index = insertOrUpdateNote(event);
|
|
253
|
+
setCurrentNoteTrackIndex(context.selectedTrackIndex ?? 0);
|
|
254
|
+
setCurrentNoteIndex(index);
|
|
255
|
+
});
|
|
211
256
|
};
|
|
212
257
|
const _ref$ = props.ref;
|
|
213
258
|
typeof _ref$ === "function" ? web.use(_ref$, _el$) : props.ref = _el$;
|
|
214
|
-
web.insert(_el$, web.createComponent(solidJs.
|
|
259
|
+
web.insert(_el$, web.createComponent(solidJs.For, {
|
|
215
260
|
get each() {
|
|
216
|
-
return context.
|
|
261
|
+
return context.tracks;
|
|
217
262
|
},
|
|
218
|
-
children: (
|
|
219
|
-
const verticalVirtualDimensions = solidJs.createMemo(() => verticalViewPort().calculatePixelDimensions(127 - note().midi, 1));
|
|
220
|
-
const horizontalDimensions = solidJs.createMemo(() => horizontalViewPort().calculatePixelDimensions(note().ticks, note().durationTicks));
|
|
263
|
+
children: (track, trackIndex) => {
|
|
221
264
|
return web.createComponent(solidJs.Show, {
|
|
222
265
|
get when() {
|
|
223
|
-
return
|
|
266
|
+
return trackIndex() === context.selectedTrackIndex || context.showAllTracks || context.mode === "tracks";
|
|
224
267
|
},
|
|
225
268
|
get children() {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
269
|
+
return web.createComponent(solidJs.For, {
|
|
270
|
+
get each() {
|
|
271
|
+
return track.notes;
|
|
272
|
+
},
|
|
273
|
+
children: (note, noteIndex) => {
|
|
274
|
+
const verticalVirtualDimensions = solidJs.createMemo(() => verticalViewPort().calculatePixelDimensions(context.mode === "keys" ? 127 - note.midi : trackIndex(), 1));
|
|
275
|
+
const horizontalDimensions = solidJs.createMemo(() => horizontalViewPort().calculatePixelDimensions(note.ticks, note.durationTicks));
|
|
276
|
+
return web.createComponent(solidJs.Show, {
|
|
277
|
+
get when() {
|
|
278
|
+
return web.memo(() => !!verticalViewPort().isVisible(verticalVirtualDimensions()))() && horizontalViewPort().isVisible(horizontalDimensions());
|
|
279
|
+
},
|
|
280
|
+
get children() {
|
|
281
|
+
const _el$2 = _tmpl$$7.cloneNode(true);
|
|
282
|
+
_el$2.$$mousedown = event => {
|
|
283
|
+
event.stopPropagation();
|
|
284
|
+
setIsDragging(true);
|
|
285
|
+
setCurrentNoteIndex(noteIndex());
|
|
286
|
+
setCurrentNoteTrackIndex(trackIndex());
|
|
287
|
+
const initialPosition = horizontalViewPort().calculatePosition(event.clientX);
|
|
288
|
+
const diffPosition = initialPosition - note.ticks;
|
|
289
|
+
const handleMouseMove = mouseMoveEvent => {
|
|
290
|
+
const note = currentNote();
|
|
291
|
+
if (!note) return;
|
|
292
|
+
const ticks = snapValueToGridIfEnabled(Math.max(horizontalViewPort().calculatePosition(mouseMoveEvent.clientX) - diffPosition, 0), mouseMoveEvent.altKey);
|
|
293
|
+
const updatedNote = {
|
|
294
|
+
...note,
|
|
295
|
+
...(noteDragMode() === "move" && context.mode === "keys" && {
|
|
296
|
+
midi: Math.round(127 - verticalViewPort().calculatePosition(mouseMoveEvent.clientY))
|
|
297
|
+
}),
|
|
298
|
+
...((noteDragMode() === "move" || noteDragMode() === "trimStart") && {
|
|
299
|
+
ticks
|
|
300
|
+
}),
|
|
301
|
+
...(noteDragMode() === "trimStart" && {
|
|
302
|
+
durationTicks: note.durationTicks + note.ticks - ticks
|
|
303
|
+
}),
|
|
304
|
+
...(noteDragMode() === "trimEnd" && {
|
|
305
|
+
durationTicks: snapValueToGridIfEnabled(horizontalViewPort().calculatePosition(mouseMoveEvent.clientX) - note.ticks, mouseMoveEvent.altKey)
|
|
306
|
+
})
|
|
307
|
+
};
|
|
308
|
+
const previousTrackIndex = currentNoteTrackIndex();
|
|
309
|
+
const previousNoteIndex = currentNoteIndex();
|
|
310
|
+
const targetTrackIndex = context.mode === "tracks" ? Math.floor(verticalViewPort().calculatePosition(mouseMoveEvent.clientY)) : previousTrackIndex;
|
|
311
|
+
if (targetTrackIndex === previousTrackIndex) {
|
|
312
|
+
context.onNoteChange?.(previousTrackIndex, previousNoteIndex, updatedNote);
|
|
313
|
+
} else {
|
|
314
|
+
solidJs.batch(() => {
|
|
315
|
+
if (context.onInsertNote) {
|
|
316
|
+
context.onRemoveNote?.(previousTrackIndex, previousNoteIndex);
|
|
317
|
+
const newNoteIndex = context.onInsertNote(targetTrackIndex, updatedNote);
|
|
318
|
+
setCurrentNoteTrackIndex(targetTrackIndex);
|
|
319
|
+
setCurrentNoteIndex(newNoteIndex);
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
const handleMouseUp = () => {
|
|
325
|
+
setIsDragging(false);
|
|
326
|
+
setCurrentNoteIndex(-1);
|
|
327
|
+
setCurrentNoteTrackIndex(-1);
|
|
328
|
+
window.removeEventListener("mousemove", handleMouseMove);
|
|
329
|
+
window.removeEventListener("mouseup", handleMouseUp);
|
|
330
|
+
};
|
|
331
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
332
|
+
window.addEventListener("mouseup", handleMouseUp);
|
|
333
|
+
};
|
|
334
|
+
_el$2.$$dblclick = event => {
|
|
335
|
+
event.stopPropagation();
|
|
336
|
+
context.onRemoveNote?.(trackIndex(), noteIndex());
|
|
337
|
+
};
|
|
338
|
+
_el$2.$$mousemove = event => {
|
|
339
|
+
if (isDragging()) return;
|
|
340
|
+
event.stopPropagation();
|
|
341
|
+
const relativeX = horizontalViewPort().calculatePixelValue(horizontalViewPort().calculatePosition(event.clientX));
|
|
342
|
+
const noteStartX = horizontalViewPort().calculatePixelValue(note.ticks);
|
|
343
|
+
const noteEndX = horizontalViewPort().calculatePixelValue(note.ticks + note.durationTicks);
|
|
344
|
+
setNoteDragMode(relativeX - noteStartX < 3 ? "trimStart" : noteEndX - relativeX < 3 ? "trimEnd" : "move");
|
|
345
|
+
};
|
|
346
|
+
web.setAttribute(_el$2, "draggable", false);
|
|
347
|
+
web.effect(_p$ => {
|
|
348
|
+
const _v$ = getClasses(noteDragMode()).join(" "),
|
|
349
|
+
_v$2 = `rgba(255,0,0, ${(128 + note.velocity) / 256})`,
|
|
350
|
+
_v$3 = `${verticalVirtualDimensions().offset}px`,
|
|
351
|
+
_v$4 = `${verticalVirtualDimensions().size}px`,
|
|
352
|
+
_v$5 = `${horizontalDimensions().offset}px`,
|
|
353
|
+
_v$6 = `${horizontalDimensions().size}px`;
|
|
354
|
+
_v$ !== _p$._v$ && web.className(_el$2, _p$._v$ = _v$);
|
|
355
|
+
_v$2 !== _p$._v$2 && _el$2.style.setProperty("background-color", _p$._v$2 = _v$2);
|
|
356
|
+
_v$3 !== _p$._v$3 && _el$2.style.setProperty("top", _p$._v$3 = _v$3);
|
|
357
|
+
_v$4 !== _p$._v$4 && _el$2.style.setProperty("height", _p$._v$4 = _v$4);
|
|
358
|
+
_v$5 !== _p$._v$5 && _el$2.style.setProperty("left", _p$._v$5 = _v$5);
|
|
359
|
+
_v$6 !== _p$._v$6 && _el$2.style.setProperty("width", _p$._v$6 = _v$6);
|
|
360
|
+
return _p$;
|
|
361
|
+
}, {
|
|
362
|
+
_v$: undefined,
|
|
363
|
+
_v$2: undefined,
|
|
364
|
+
_v$3: undefined,
|
|
365
|
+
_v$4: undefined,
|
|
366
|
+
_v$5: undefined,
|
|
367
|
+
_v$6: undefined
|
|
368
|
+
});
|
|
369
|
+
return _el$2;
|
|
370
|
+
}
|
|
248
371
|
});
|
|
249
|
-
}
|
|
250
|
-
const handleMouseUp = () => {
|
|
251
|
-
setIsDragging(false);
|
|
252
|
-
window.removeEventListener("mousemove", handleMouseMove);
|
|
253
|
-
window.removeEventListener("mouseup", handleMouseUp);
|
|
254
|
-
};
|
|
255
|
-
window.addEventListener("mousemove", handleMouseMove);
|
|
256
|
-
window.addEventListener("mouseup", handleMouseUp);
|
|
257
|
-
};
|
|
258
|
-
_el$2.$$dblclick = event => {
|
|
259
|
-
event.stopPropagation();
|
|
260
|
-
context.onRemoveNote?.(index);
|
|
261
|
-
};
|
|
262
|
-
_el$2.$$mousemove = event => {
|
|
263
|
-
if (isDragging()) return;
|
|
264
|
-
event.stopPropagation();
|
|
265
|
-
const relativeX = horizontalViewPort().calculatePixelValue(horizontalViewPort().calculatePosition(event.clientX));
|
|
266
|
-
const noteStartX = horizontalViewPort().calculatePixelValue(note().ticks);
|
|
267
|
-
const noteEndX = horizontalViewPort().calculatePixelValue(note().ticks + note().durationTicks);
|
|
268
|
-
setNoteDragMode(relativeX - noteStartX < 3 ? "trimStart" : noteEndX - relativeX < 3 ? "trimEnd" : "move");
|
|
269
|
-
};
|
|
270
|
-
web.effect(_p$ => {
|
|
271
|
-
const _v$ = getClasses(noteDragMode()).join(" "),
|
|
272
|
-
_v$2 = {
|
|
273
|
-
"background-color": `rgba(255,0,0, ${(128 + note().velocity) / 256})`,
|
|
274
|
-
...(context.condensed ? {
|
|
275
|
-
top: 0,
|
|
276
|
-
height: "100%"
|
|
277
|
-
} : {
|
|
278
|
-
top: `${verticalVirtualDimensions().offset}px`,
|
|
279
|
-
height: `${verticalVirtualDimensions().size}px`
|
|
280
|
-
}),
|
|
281
|
-
left: `${horizontalDimensions().offset}px`,
|
|
282
|
-
width: `${horizontalDimensions().size}px`
|
|
283
|
-
};
|
|
284
|
-
_v$ !== _p$._v$ && web.className(_el$2, _p$._v$ = _v$);
|
|
285
|
-
_p$._v$2 = web.style(_el$2, _v$2, _p$._v$2);
|
|
286
|
-
return _p$;
|
|
287
|
-
}, {
|
|
288
|
-
_v$: undefined,
|
|
289
|
-
_v$2: undefined
|
|
372
|
+
}
|
|
290
373
|
});
|
|
291
|
-
return _el$2;
|
|
292
374
|
}
|
|
293
375
|
});
|
|
294
376
|
}
|
|
@@ -299,7 +381,7 @@ const PianoRollNotes = props => {
|
|
|
299
381
|
};
|
|
300
382
|
web.delegateEvents(["mousedown", "mousemove", "mouseup", "dblclick", "click"]);
|
|
301
383
|
|
|
302
|
-
const _tmpl$$
|
|
384
|
+
const _tmpl$$6 = /*#__PURE__*/web.template(`<div class="PianoRoll-Scroller"><div><div><div></div></div></div></div>`, 8);
|
|
303
385
|
const ScrollContainer = props => {
|
|
304
386
|
let scrollContentRef;
|
|
305
387
|
const verticalViewPort = solidJs.createMemo(() => useViewPortDimension("vertical"));
|
|
@@ -361,7 +443,7 @@ const ScrollContainer = props => {
|
|
|
361
443
|
});
|
|
362
444
|
});
|
|
363
445
|
return (() => {
|
|
364
|
-
const _el$ = _tmpl$$
|
|
446
|
+
const _el$ = _tmpl$$6.cloneNode(true),
|
|
365
447
|
_el$2 = _el$.firstChild,
|
|
366
448
|
_el$3 = _el$2.firstChild,
|
|
367
449
|
_el$4 = _el$3.firstChild;
|
|
@@ -402,74 +484,11 @@ const ScrollContainer = props => {
|
|
|
402
484
|
})();
|
|
403
485
|
};
|
|
404
486
|
|
|
405
|
-
var css_248z$1 = ".
|
|
406
|
-
var styles$1 = {"
|
|
487
|
+
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";
|
|
488
|
+
var styles$1 = {"PianoRollGrid":"PianoRollGrid-module_PianoRollGrid__tG119","PianoRollGrid-Row":"PianoRollGrid-module_PianoRollGrid-Row__nRMCs","PianoRollGrid-Time":"PianoRollGrid-module_PianoRollGrid-Time__jLz3E"};
|
|
407
489
|
styleInject(css_248z$1);
|
|
408
490
|
|
|
409
|
-
const _tmpl$$
|
|
410
|
-
const PianoRollKeys = () => {
|
|
411
|
-
const viewPort = solidJs.createMemo(() => useViewPortDimension("vertical"));
|
|
412
|
-
return (() => {
|
|
413
|
-
const _el$ = _tmpl$$4.cloneNode(true);
|
|
414
|
-
web.insert(_el$, web.createComponent(solidJs.Index, {
|
|
415
|
-
each: keys,
|
|
416
|
-
children: key => {
|
|
417
|
-
const virtualDimensions = solidJs.createMemo(() => viewPort().calculatePixelDimensions(127 - key().number, 1));
|
|
418
|
-
return web.createComponent(solidJs.Show, {
|
|
419
|
-
get when() {
|
|
420
|
-
return virtualDimensions().size > 0;
|
|
421
|
-
},
|
|
422
|
-
get children() {
|
|
423
|
-
const _el$2 = _tmpl$$4.cloneNode(true);
|
|
424
|
-
web.effect(_p$ => {
|
|
425
|
-
const _v$ = {
|
|
426
|
-
[styles$1["Key"]]: true,
|
|
427
|
-
[styles$1["black"]]: key().isBlack,
|
|
428
|
-
[styles$1["white"]]: !key().isBlack,
|
|
429
|
-
[styles$1["whiteAndNextIsWhite"]]: !key().isBlack && !blackKeys.includes((key().number + 1) % 12),
|
|
430
|
-
[styles$1["whiteAndPreviousIsWhite"]]: !key().isBlack && !blackKeys.includes((key().number - 1) % 12)
|
|
431
|
-
},
|
|
432
|
-
_v$2 = key().name,
|
|
433
|
-
_v$3 = key().number % 12,
|
|
434
|
-
_v$4 = `${virtualDimensions().offset}px`,
|
|
435
|
-
_v$5 = `${virtualDimensions().size}px`;
|
|
436
|
-
_p$._v$ = web.classList(_el$2, _v$, _p$._v$);
|
|
437
|
-
_v$2 !== _p$._v$2 && web.setAttribute(_el$2, "title", _p$._v$2 = _v$2);
|
|
438
|
-
_v$3 !== _p$._v$3 && web.setAttribute(_el$2, "data-index", _p$._v$3 = _v$3);
|
|
439
|
-
_v$4 !== _p$._v$4 && _el$2.style.setProperty("top", _p$._v$4 = _v$4);
|
|
440
|
-
_v$5 !== _p$._v$5 && _el$2.style.setProperty("height", _p$._v$5 = _v$5);
|
|
441
|
-
return _p$;
|
|
442
|
-
}, {
|
|
443
|
-
_v$: undefined,
|
|
444
|
-
_v$2: undefined,
|
|
445
|
-
_v$3: undefined,
|
|
446
|
-
_v$4: undefined,
|
|
447
|
-
_v$5: undefined
|
|
448
|
-
});
|
|
449
|
-
return _el$2;
|
|
450
|
-
}
|
|
451
|
-
});
|
|
452
|
-
}
|
|
453
|
-
}));
|
|
454
|
-
web.effect(() => web.className(_el$, styles$1.PianoRollKeys));
|
|
455
|
-
return _el$;
|
|
456
|
-
})();
|
|
457
|
-
};
|
|
458
|
-
const blackKeys = [1, 3, 6, 8, 10];
|
|
459
|
-
const keyNames = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
|
|
460
|
-
const keys = Array.from({
|
|
461
|
-
length: 128
|
|
462
|
-
}).map((_, index) => ({
|
|
463
|
-
number: index,
|
|
464
|
-
name: `${keyNames[index % 12]} ${Math.floor(index / 12) - 2}`,
|
|
465
|
-
isBlack: blackKeys.includes(index % 12)
|
|
466
|
-
}));
|
|
467
|
-
|
|
468
|
-
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";
|
|
469
|
-
var styles = {"PianoRollGrid":"PianoRollGrid-module_PianoRollGrid__tG119","PianoRollGrid-Key":"PianoRollGrid-module_PianoRollGrid-Key__VRbiB","PianoRollGrid-Time":"PianoRollGrid-module_PianoRollGrid-Time__jLz3E"};
|
|
470
|
-
styleInject(css_248z);
|
|
471
|
-
|
|
472
|
-
const _tmpl$$3 = /*#__PURE__*/web.template(`<div></div>`, 2);
|
|
491
|
+
const _tmpl$$5 = /*#__PURE__*/web.template(`<div></div>`, 2);
|
|
473
492
|
const PianoRollGrid = () => {
|
|
474
493
|
const context = usePianoRollContext();
|
|
475
494
|
const verticalViewPort = solidJs.createMemo(() => useViewPortDimension("vertical"));
|
|
@@ -477,10 +496,12 @@ const PianoRollGrid = () => {
|
|
|
477
496
|
const measureTicks = solidJs.createMemo(() => context.ppq * 4);
|
|
478
497
|
const selectedGridDivisorTicks = solidJs.createMemo(() => measureTicks() / context.gridDivision);
|
|
479
498
|
function calculateVisibleGridDivisorTicks(value) {
|
|
480
|
-
|
|
499
|
+
const visibleRange = horizontalViewPort().calculateVisibleRange();
|
|
500
|
+
if (visibleRange <= 0) return 0;
|
|
501
|
+
if (visibleRange / value > 100) {
|
|
481
502
|
return calculateVisibleGridDivisorTicks(value * 2);
|
|
482
503
|
}
|
|
483
|
-
if (
|
|
504
|
+
if (visibleRange / value < 30) {
|
|
484
505
|
return calculateVisibleGridDivisorTicks(value / 2);
|
|
485
506
|
}
|
|
486
507
|
return value;
|
|
@@ -497,7 +518,7 @@ const PianoRollGrid = () => {
|
|
|
497
518
|
}));
|
|
498
519
|
});
|
|
499
520
|
return (() => {
|
|
500
|
-
const _el$ = _tmpl$$
|
|
521
|
+
const _el$ = _tmpl$$5.cloneNode(true);
|
|
501
522
|
web.insert(_el$, web.createComponent(solidJs.Index, {
|
|
502
523
|
get each() {
|
|
503
524
|
return gridArray();
|
|
@@ -509,9 +530,9 @@ const PianoRollGrid = () => {
|
|
|
509
530
|
return virtualDimensions().size > 0;
|
|
510
531
|
},
|
|
511
532
|
get children() {
|
|
512
|
-
const _el$2 = _tmpl$$
|
|
533
|
+
const _el$2 = _tmpl$$5.cloneNode(true);
|
|
513
534
|
web.effect(_p$ => {
|
|
514
|
-
const _v$ = styles["PianoRollGrid-Time"],
|
|
535
|
+
const _v$ = styles$1["PianoRollGrid-Time"],
|
|
515
536
|
_v$2 = Math.ceil((entry().index + 1 * selectedGridDivisorTicks()) / measureTicks()) % 2 === 0 ? "#ddd" : "#ccc",
|
|
516
537
|
_v$3 = `${virtualDimensions().offset}px`,
|
|
517
538
|
_v$4 = `${virtualDimensions().size}px`,
|
|
@@ -536,7 +557,7 @@ const PianoRollGrid = () => {
|
|
|
536
557
|
}), null);
|
|
537
558
|
web.insert(_el$, web.createComponent(solidJs.Show, {
|
|
538
559
|
get when() {
|
|
539
|
-
return
|
|
560
|
+
return context.mode === "keys";
|
|
540
561
|
},
|
|
541
562
|
get children() {
|
|
542
563
|
return web.createComponent(solidJs.Index, {
|
|
@@ -548,10 +569,10 @@ const PianoRollGrid = () => {
|
|
|
548
569
|
return virtualDimensions().size > 0;
|
|
549
570
|
},
|
|
550
571
|
get children() {
|
|
551
|
-
const _el$3 = _tmpl$$
|
|
572
|
+
const _el$3 = _tmpl$$5.cloneNode(true);
|
|
552
573
|
_el$3.style.setProperty("width", "100%");
|
|
553
574
|
web.effect(_p$ => {
|
|
554
|
-
const _v$6 = styles["PianoRollGrid-
|
|
575
|
+
const _v$6 = styles$1["PianoRollGrid-Row"],
|
|
555
576
|
_v$7 = `${virtualDimensions().offset}px`,
|
|
556
577
|
_v$8 = `${virtualDimensions().size}px`,
|
|
557
578
|
_v$9 = key().isBlack ? "rgba(0,0,0,0.2)" : "none",
|
|
@@ -576,35 +597,53 @@ const PianoRollGrid = () => {
|
|
|
576
597
|
});
|
|
577
598
|
}
|
|
578
599
|
}), null);
|
|
579
|
-
web.
|
|
600
|
+
web.insert(_el$, web.createComponent(solidJs.Show, {
|
|
601
|
+
get when() {
|
|
602
|
+
return context.mode === "tracks";
|
|
603
|
+
},
|
|
604
|
+
get children() {
|
|
605
|
+
return web.createComponent(solidJs.For, {
|
|
606
|
+
get each() {
|
|
607
|
+
return context.tracks;
|
|
608
|
+
},
|
|
609
|
+
children: (track, index) => {
|
|
610
|
+
const virtualDimensions = solidJs.createMemo(() => verticalViewPort().calculatePixelDimensions(index(), 1));
|
|
611
|
+
return web.createComponent(solidJs.Show, {
|
|
612
|
+
get when() {
|
|
613
|
+
return virtualDimensions().size > 0;
|
|
614
|
+
},
|
|
615
|
+
get children() {
|
|
616
|
+
const _el$4 = _tmpl$$5.cloneNode(true);
|
|
617
|
+
_el$4.style.setProperty("width", "100%");
|
|
618
|
+
_el$4.style.setProperty("border-width", "0");
|
|
619
|
+
web.effect(_p$ => {
|
|
620
|
+
const _v$11 = styles$1["PianoRollGrid-Row"],
|
|
621
|
+
_v$12 = `${virtualDimensions().offset}px`,
|
|
622
|
+
_v$13 = `${virtualDimensions().size}px`,
|
|
623
|
+
_v$14 = index() % 2 === 0 ? "rgba(0,0,0,0.2)" : "none";
|
|
624
|
+
_v$11 !== _p$._v$11 && web.className(_el$4, _p$._v$11 = _v$11);
|
|
625
|
+
_v$12 !== _p$._v$12 && _el$4.style.setProperty("top", _p$._v$12 = _v$12);
|
|
626
|
+
_v$13 !== _p$._v$13 && _el$4.style.setProperty("height", _p$._v$13 = _v$13);
|
|
627
|
+
_v$14 !== _p$._v$14 && _el$4.style.setProperty("background-color", _p$._v$14 = _v$14);
|
|
628
|
+
return _p$;
|
|
629
|
+
}, {
|
|
630
|
+
_v$11: undefined,
|
|
631
|
+
_v$12: undefined,
|
|
632
|
+
_v$13: undefined,
|
|
633
|
+
_v$14: undefined
|
|
634
|
+
});
|
|
635
|
+
return _el$4;
|
|
636
|
+
}
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
}), null);
|
|
642
|
+
web.effect(() => web.className(_el$, styles$1.PianoRollGrid));
|
|
580
643
|
return _el$;
|
|
581
644
|
})();
|
|
582
645
|
};
|
|
583
646
|
|
|
584
|
-
const useNotes = () => {
|
|
585
|
-
const [notes, onNotesChange] = solidJs.createSignal([]);
|
|
586
|
-
const onNoteChange = (index, note) => {
|
|
587
|
-
onNotesChange([...notes().slice(0, index), note, ...notes().splice(index + 1)]);
|
|
588
|
-
};
|
|
589
|
-
const onInsertNote = note => {
|
|
590
|
-
const index = Math.max(notes().findIndex(({
|
|
591
|
-
ticks
|
|
592
|
-
}) => ticks > note.ticks), 0);
|
|
593
|
-
onNotesChange([...notes().slice(0, index), note, ...notes().splice(index)]);
|
|
594
|
-
return index;
|
|
595
|
-
};
|
|
596
|
-
const onRemoveNote = index => {
|
|
597
|
-
onNotesChange([...notes().slice(0, index), ...notes().splice(index + 1)]);
|
|
598
|
-
};
|
|
599
|
-
return {
|
|
600
|
-
notes,
|
|
601
|
-
onNotesChange,
|
|
602
|
-
onNoteChange,
|
|
603
|
-
onInsertNote,
|
|
604
|
-
onRemoveNote
|
|
605
|
-
};
|
|
606
|
-
};
|
|
607
|
-
|
|
608
647
|
const defaultRect = {
|
|
609
648
|
left: 0,
|
|
610
649
|
width: 0,
|
|
@@ -633,11 +672,11 @@ function useBoundingClientRect(containerRef) {
|
|
|
633
672
|
return boundingClientRect;
|
|
634
673
|
}
|
|
635
674
|
|
|
636
|
-
const _tmpl$$
|
|
675
|
+
const _tmpl$$4 = /*#__PURE__*/web.template(`<input min="1" max="11" step="0.01">`, 1);
|
|
637
676
|
const VerticalZoomControl = props => {
|
|
638
677
|
const context = usePianoRollContext();
|
|
639
678
|
return (() => {
|
|
640
|
-
const _el$ = _tmpl$$
|
|
679
|
+
const _el$ = _tmpl$$4.cloneNode(true);
|
|
641
680
|
web.spread(_el$, web.mergeProps(props, {
|
|
642
681
|
get value() {
|
|
643
682
|
return context.verticalZoom;
|
|
@@ -661,196 +700,91 @@ const VerticalZoomControl = props => {
|
|
|
661
700
|
})();
|
|
662
701
|
};
|
|
663
702
|
|
|
664
|
-
const _tmpl$$
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
_el$2 =
|
|
712
|
-
_el$
|
|
713
|
-
_el$
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
_el$2.style.setProperty("margin-block-start", "0");
|
|
719
|
-
_el$2.style.setProperty("padding-inline-start", "0");
|
|
720
|
-
_el$2.style.setProperty("width", "150px");
|
|
721
|
-
web.insert(_el$2, web.createComponent(solidJs.Index, {
|
|
722
|
-
get each() {
|
|
723
|
-
return allProps.tracks;
|
|
724
|
-
},
|
|
725
|
-
children: track => (() => {
|
|
726
|
-
const _el$6 = _tmpl$3.cloneNode(true);
|
|
727
|
-
_el$6.$$click = () => {
|
|
728
|
-
if (track() === allProps.selectedTrack) {
|
|
729
|
-
allProps.onSelectedTrackChange(undefined);
|
|
730
|
-
} else {
|
|
731
|
-
allProps.onSelectedTrackChange(track());
|
|
732
|
-
}
|
|
733
|
-
};
|
|
734
|
-
_el$6.style.setProperty("width", "150px");
|
|
735
|
-
_el$6.style.setProperty("height", "30px");
|
|
736
|
-
_el$6.style.setProperty("list-style", "none");
|
|
737
|
-
_el$6.style.setProperty("display", "flex");
|
|
738
|
-
_el$6.style.setProperty("align-items", "center");
|
|
739
|
-
_el$6.style.setProperty("border-top", "1px black solid");
|
|
740
|
-
_el$6.style.setProperty("cursor", "pointer");
|
|
741
|
-
web.insert(_el$6, () => track().name);
|
|
742
|
-
web.effect(() => _el$6.style.setProperty("background", track() === allProps.selectedTrack ? "lightgray" : "none"));
|
|
743
|
-
return _el$6;
|
|
744
|
-
})()
|
|
745
|
-
}));
|
|
746
|
-
_el$3.style.setProperty("flex", "1");
|
|
747
|
-
web.insert(_el$4, web.createComponent(solidJs.Show, {
|
|
748
|
-
get when() {
|
|
749
|
-
return !condensed();
|
|
750
|
-
},
|
|
751
|
-
get children() {
|
|
752
|
-
return web.createComponent(PianoRollKeys, {});
|
|
753
|
-
}
|
|
754
|
-
}), null);
|
|
755
|
-
web.insert(_el$4, web.createComponent(ScrollContainer, {
|
|
756
|
-
ref: setScrollerRef,
|
|
757
|
-
get children() {
|
|
758
|
-
const _el$5 = _tmpl$$1.cloneNode(true);
|
|
759
|
-
_el$5.style.setProperty("margin", "0");
|
|
760
|
-
_el$5.style.setProperty("margin-block-start", "0");
|
|
761
|
-
_el$5.style.setProperty("padding-inline-start", "0");
|
|
762
|
-
web.insert(_el$5, web.createComponent(solidJs.Index, {
|
|
763
|
-
get each() {
|
|
764
|
-
return allProps.tracks;
|
|
765
|
-
},
|
|
766
|
-
children: track => {
|
|
767
|
-
const notes = useNotes();
|
|
768
|
-
solidJs.createEffect(() => {
|
|
769
|
-
notes.onNotesChange(track().notes);
|
|
770
|
-
});
|
|
771
|
-
const [context, setContext] = store.createStore({
|
|
772
|
-
...contextProps
|
|
773
|
-
});
|
|
774
|
-
solidJs.createEffect(() => {
|
|
775
|
-
setContext({
|
|
776
|
-
...contextProps,
|
|
777
|
-
condensed: condensed(),
|
|
778
|
-
notes: notes.notes(),
|
|
779
|
-
onNoteChange: notes.onNoteChange,
|
|
780
|
-
onInsertNote: notes.onInsertNote,
|
|
781
|
-
onRemoveNote: notes.onRemoveNote
|
|
782
|
-
});
|
|
783
|
-
});
|
|
784
|
-
const verticalViewPort = useViewPortDimension("vertical");
|
|
785
|
-
return web.createComponent(solidJs.Show, {
|
|
786
|
-
get when() {
|
|
787
|
-
return condensed() || allProps.selectedTrack === track();
|
|
788
|
-
},
|
|
789
|
-
get children() {
|
|
790
|
-
return web.createComponent(PianoRollContextProvider, {
|
|
791
|
-
value: context,
|
|
792
|
-
get children() {
|
|
793
|
-
const _el$7 = _tmpl$3.cloneNode(true);
|
|
794
|
-
_el$7.style.setProperty("display", "flex");
|
|
795
|
-
_el$7.style.setProperty("position", "relative");
|
|
796
|
-
_el$7.style.setProperty("list-style", "none");
|
|
797
|
-
_el$7.style.setProperty("flex-direction", "row");
|
|
798
|
-
_el$7.style.setProperty("border-top", "1px black solid");
|
|
799
|
-
web.insert(_el$7, web.createComponent(PianoRollNotes, {}), null);
|
|
800
|
-
web.insert(_el$7, web.createComponent(PianoRollGrid, {}), null);
|
|
801
|
-
web.effect(() => _el$7.style.setProperty("height", condensed() ? "30px" : `${verticalViewPort.pixelSize}px`));
|
|
802
|
-
return _el$7;
|
|
803
|
-
}
|
|
804
|
-
});
|
|
805
|
-
}
|
|
806
|
-
});
|
|
807
|
-
}
|
|
808
|
-
}));
|
|
809
|
-
return _el$5;
|
|
810
|
-
}
|
|
811
|
-
}), null);
|
|
812
|
-
web.insert(_el$4, web.createComponent(solidJs.Show, {
|
|
813
|
-
get when() {
|
|
814
|
-
return !condensed();
|
|
815
|
-
},
|
|
816
|
-
get children() {
|
|
817
|
-
return web.createComponent(VerticalZoomControl, {
|
|
818
|
-
get value() {
|
|
819
|
-
return contextProps.verticalZoom;
|
|
703
|
+
const _tmpl$$3 = /*#__PURE__*/web.template(`<input max="500" min="1" step="0.01">`, 1);
|
|
704
|
+
const HorizontalZoomControl = props => {
|
|
705
|
+
const context = usePianoRollContext();
|
|
706
|
+
return (() => {
|
|
707
|
+
const _el$ = _tmpl$$3.cloneNode(true);
|
|
708
|
+
web.spread(_el$, web.mergeProps(props, {
|
|
709
|
+
get value() {
|
|
710
|
+
return context.zoom;
|
|
711
|
+
},
|
|
712
|
+
"onInput": event => context.onZoomChange?.(event.currentTarget.valueAsNumber),
|
|
713
|
+
"type": "range",
|
|
714
|
+
get style() {
|
|
715
|
+
return {
|
|
716
|
+
"margin-left": "50px",
|
|
717
|
+
"margin-right": "16px",
|
|
718
|
+
...(typeof props.style === "object" && props.style)
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
}), false, false);
|
|
722
|
+
return _el$;
|
|
723
|
+
})();
|
|
724
|
+
};
|
|
725
|
+
|
|
726
|
+
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";
|
|
727
|
+
var styles = {"PianoRollTrackList":"PianoRollTrackList-module_PianoRollTrackList__pyuxQ","Track":"PianoRollTrackList-module_Track__VZFIg"};
|
|
728
|
+
styleInject(css_248z);
|
|
729
|
+
|
|
730
|
+
const _tmpl$$2 = /*#__PURE__*/web.template(`<div></div>`, 2),
|
|
731
|
+
_tmpl$2$1 = /*#__PURE__*/web.template(`<div> </div>`, 2);
|
|
732
|
+
const PianoRollTrackList = () => {
|
|
733
|
+
const viewPort = solidJs.createMemo(() => useViewPortDimension("vertical"));
|
|
734
|
+
const context = usePianoRollContext();
|
|
735
|
+
return (() => {
|
|
736
|
+
const _el$ = _tmpl$$2.cloneNode(true);
|
|
737
|
+
web.insert(_el$, web.createComponent(solidJs.Index, {
|
|
738
|
+
get each() {
|
|
739
|
+
return context.tracks;
|
|
740
|
+
},
|
|
741
|
+
children: (track, index) => {
|
|
742
|
+
const virtualDimensions = solidJs.createMemo(() => viewPort().calculatePixelDimensions(context.mode === "tracks" ? index : index * 8, context.mode === "tracks" ? 1 : 8));
|
|
743
|
+
return web.createComponent(solidJs.Show, {
|
|
744
|
+
get when() {
|
|
745
|
+
return virtualDimensions().size > 0;
|
|
746
|
+
},
|
|
747
|
+
get children() {
|
|
748
|
+
const _el$2 = _tmpl$2$1.cloneNode(true),
|
|
749
|
+
_el$3 = _el$2.firstChild;
|
|
750
|
+
_el$2.$$click = () => context.onSelectedTrackIndexChange?.(index);
|
|
751
|
+
_el$2.style.setProperty("cursor", "pointer");
|
|
752
|
+
web.insert(_el$2, index, _el$3);
|
|
753
|
+
web.insert(_el$2, () => track().name || "[unnamed track]", null);
|
|
754
|
+
web.effect(_p$ => {
|
|
755
|
+
const _v$ = {
|
|
756
|
+
[styles["Track"]]: true
|
|
820
757
|
},
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
"
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
}
|
|
847
|
-
});
|
|
848
|
-
}
|
|
849
|
-
});
|
|
758
|
+
_v$2 = track().name,
|
|
759
|
+
_v$3 = `${virtualDimensions().offset}px`,
|
|
760
|
+
_v$4 = `${virtualDimensions().size}px`,
|
|
761
|
+
_v$5 = index === context.selectedTrackIndex ? "gray" : "lightgrey";
|
|
762
|
+
_p$._v$ = web.classList(_el$2, _v$, _p$._v$);
|
|
763
|
+
_v$2 !== _p$._v$2 && web.setAttribute(_el$2, "title", _p$._v$2 = _v$2);
|
|
764
|
+
_v$3 !== _p$._v$3 && _el$2.style.setProperty("top", _p$._v$3 = _v$3);
|
|
765
|
+
_v$4 !== _p$._v$4 && _el$2.style.setProperty("height", _p$._v$4 = _v$4);
|
|
766
|
+
_v$5 !== _p$._v$5 && _el$2.style.setProperty("background", _p$._v$5 = _v$5);
|
|
767
|
+
return _p$;
|
|
768
|
+
}, {
|
|
769
|
+
_v$: undefined,
|
|
770
|
+
_v$2: undefined,
|
|
771
|
+
_v$3: undefined,
|
|
772
|
+
_v$4: undefined,
|
|
773
|
+
_v$5: undefined
|
|
774
|
+
});
|
|
775
|
+
return _el$2;
|
|
776
|
+
}
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
}));
|
|
780
|
+
web.effect(() => web.className(_el$, styles.PianoRollTrackList));
|
|
781
|
+
return _el$;
|
|
782
|
+
})();
|
|
850
783
|
};
|
|
851
784
|
web.delegateEvents(["click"]);
|
|
852
785
|
|
|
853
|
-
const _tmpl
|
|
786
|
+
const _tmpl$$1 = /*#__PURE__*/web.template(`<div></div>`, 2),
|
|
787
|
+
_tmpl$2 = /*#__PURE__*/web.template(`<div><div></div></div>`, 4);
|
|
854
788
|
const PianoRoll = allProps => {
|
|
855
789
|
const [contextProps, divProps] = splitContextProps(allProps);
|
|
856
790
|
const [scrollerRef, setScrollerRef] = solidJs.createSignal();
|
|
@@ -860,14 +794,20 @@ const PianoRoll = allProps => {
|
|
|
860
794
|
const maxZoom = solidJs.createMemo(() => 500 * (zoomFactor / clientRect().width));
|
|
861
795
|
const minVerticalZoom = solidJs.createMemo(() => 1 / (zoomFactor / clientRect().height));
|
|
862
796
|
const maxVerticalZoom = solidJs.createMemo(() => 10 * (zoomFactor / clientRect().height));
|
|
797
|
+
solidJs.createEffect(isInitial => {
|
|
798
|
+
if (isInitial) return false;
|
|
799
|
+
if (contextProps.mode === "tracks") {
|
|
800
|
+
contextProps.onVerticalPositionChange?.(0);
|
|
801
|
+
}
|
|
802
|
+
}, true);
|
|
863
803
|
return web.createComponent(PianoRollContextProvider, {
|
|
864
804
|
value: contextProps,
|
|
865
805
|
get children() {
|
|
866
|
-
const _el$ = _tmpl
|
|
806
|
+
const _el$ = _tmpl$2.cloneNode(true),
|
|
867
807
|
_el$2 = _el$.firstChild;
|
|
868
808
|
web.spread(_el$, web.mergeProps(divProps, {
|
|
869
809
|
get ["class"]() {
|
|
870
|
-
return styles$
|
|
810
|
+
return styles$4.PianoRoll;
|
|
871
811
|
}
|
|
872
812
|
}), false, true);
|
|
873
813
|
web.insert(_el$2, web.createComponent(ScrollZoomViewPort, {
|
|
@@ -885,17 +825,38 @@ const PianoRoll = allProps => {
|
|
|
885
825
|
pixelOffset: clientRect().top,
|
|
886
826
|
pixelSize: clientRect().height,
|
|
887
827
|
position: contextProps.verticalPosition,
|
|
888
|
-
range: 128,
|
|
828
|
+
range: contextProps.mode === "keys" ? 128 : Math.max(contextProps.tracks.length, 16),
|
|
889
829
|
zoom: contextProps.verticalZoom * (zoomFactor / clientRect().height),
|
|
890
830
|
onPositionChange: contextProps.onVerticalPositionChange,
|
|
891
831
|
onZoomChange: verticalZoom => contextProps.onVerticalZoomChange?.(clamp(verticalZoom / (zoomFactor / clientRect().height), minVerticalZoom(), maxVerticalZoom()))
|
|
892
832
|
})
|
|
893
833
|
},
|
|
894
834
|
get children() {
|
|
895
|
-
return [
|
|
835
|
+
return [(() => {
|
|
836
|
+
const _el$3 = _tmpl$$1.cloneNode(true);
|
|
837
|
+
_el$3.style.setProperty("display", "flex");
|
|
838
|
+
_el$3.style.setProperty("width", "20%");
|
|
839
|
+
web.insert(_el$3, web.createComponent(solidJs.Show, {
|
|
840
|
+
get when() {
|
|
841
|
+
return allProps.showTrackList;
|
|
842
|
+
},
|
|
843
|
+
get children() {
|
|
844
|
+
return web.createComponent(PianoRollTrackList, {});
|
|
845
|
+
}
|
|
846
|
+
}), null);
|
|
847
|
+
web.insert(_el$3, web.createComponent(solidJs.Show, {
|
|
848
|
+
get when() {
|
|
849
|
+
return contextProps.mode === "keys";
|
|
850
|
+
},
|
|
851
|
+
get children() {
|
|
852
|
+
return web.createComponent(PianoRollKeys, {});
|
|
853
|
+
}
|
|
854
|
+
}), null);
|
|
855
|
+
return _el$3;
|
|
856
|
+
})(), web.createComponent(ScrollContainer, {
|
|
896
857
|
ref: setScrollerRef,
|
|
897
858
|
get children() {
|
|
898
|
-
return [web.createComponent(PianoRollGrid, {}), web.createComponent(PianoRollNotes, {})];
|
|
859
|
+
return [web.memo(() => allProps.children), web.createComponent(PianoRollGrid, {}), web.createComponent(PianoRollNotes, {})];
|
|
899
860
|
}
|
|
900
861
|
}), web.createComponent(VerticalZoomControl, {
|
|
901
862
|
get min() {
|
|
@@ -915,19 +876,97 @@ const PianoRoll = allProps => {
|
|
|
915
876
|
return maxZoom();
|
|
916
877
|
}
|
|
917
878
|
}), null);
|
|
918
|
-
web.effect(() => web.className(_el$2, styles$
|
|
879
|
+
web.effect(() => web.className(_el$2, styles$4.PianoRollContainer));
|
|
919
880
|
return _el$;
|
|
920
881
|
}
|
|
921
882
|
});
|
|
922
883
|
};
|
|
923
884
|
|
|
885
|
+
const _tmpl$ = /*#__PURE__*/web.template(`<div class="PlayHead"></div>`, 2);
|
|
886
|
+
const PlayHead = allProps => {
|
|
887
|
+
const propsWithDefauls = solidJs.mergeProps({
|
|
888
|
+
playHeadPosition: 0,
|
|
889
|
+
sync: false
|
|
890
|
+
}, allProps);
|
|
891
|
+
const [props, divProps] = solidJs.splitProps(propsWithDefauls, ["playHeadPosition", "sync", "onPlayHeadPositionChange", "onPositionChange"]);
|
|
892
|
+
const viewPort = useViewPortDimension("horizontal");
|
|
893
|
+
solidJs.createEffect(() => {
|
|
894
|
+
if (!props.sync) return;
|
|
895
|
+
const maxPosition = viewPort.range;
|
|
896
|
+
const newPosition = clamp(props.playHeadPosition - viewPort.range / viewPort.zoom / 2, 0, maxPosition);
|
|
897
|
+
props.onPositionChange?.(newPosition);
|
|
898
|
+
});
|
|
899
|
+
const leftPosition = solidJs.createMemo(() => viewPort.calculatePixelOffset(props.playHeadPosition));
|
|
900
|
+
return (() => {
|
|
901
|
+
const _el$ = _tmpl$.cloneNode(true);
|
|
902
|
+
web.spread(_el$, web.mergeProps(divProps, {
|
|
903
|
+
get style() {
|
|
904
|
+
return {
|
|
905
|
+
position: "absolute",
|
|
906
|
+
height: "100%",
|
|
907
|
+
width: "2px",
|
|
908
|
+
left: `${leftPosition()}px`,
|
|
909
|
+
"background-color": "green",
|
|
910
|
+
cursor: "pointer",
|
|
911
|
+
...(typeof divProps.style === "object" && divProps.style)
|
|
912
|
+
};
|
|
913
|
+
},
|
|
914
|
+
"onMouseDown": event => {
|
|
915
|
+
event.preventDefault();
|
|
916
|
+
event.stopPropagation();
|
|
917
|
+
const handleMouseMove = ({
|
|
918
|
+
movementX
|
|
919
|
+
}) => {
|
|
920
|
+
const {
|
|
921
|
+
parentElement
|
|
922
|
+
} = event.currentTarget;
|
|
923
|
+
if (!parentElement) return;
|
|
924
|
+
const newPosition = viewPort.calculatePosition(leftPosition() + movementX);
|
|
925
|
+
props.onPlayHeadPositionChange?.(newPosition);
|
|
926
|
+
};
|
|
927
|
+
const handleMouseUp = () => {
|
|
928
|
+
window.removeEventListener("mousemove", handleMouseMove);
|
|
929
|
+
window.removeEventListener("mouseup", handleMouseUp);
|
|
930
|
+
};
|
|
931
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
932
|
+
window.addEventListener("mouseup", handleMouseUp);
|
|
933
|
+
}
|
|
934
|
+
}), false, false);
|
|
935
|
+
return _el$;
|
|
936
|
+
})();
|
|
937
|
+
};
|
|
938
|
+
|
|
939
|
+
const useNotes = () => {
|
|
940
|
+
const [notes, onNotesChange] = solidJs.createSignal([]);
|
|
941
|
+
const onNoteChange = (index, note) => {
|
|
942
|
+
onNotesChange([...notes().slice(0, index), note, ...notes().splice(index + 1)]);
|
|
943
|
+
};
|
|
944
|
+
const onInsertNote = note => {
|
|
945
|
+
const index = Math.max(notes().findIndex(({
|
|
946
|
+
ticks
|
|
947
|
+
}) => ticks > note.ticks), 0);
|
|
948
|
+
onNotesChange([...notes().slice(0, index), note, ...notes().splice(index)]);
|
|
949
|
+
return index;
|
|
950
|
+
};
|
|
951
|
+
const onRemoveNote = index => {
|
|
952
|
+
onNotesChange([...notes().slice(0, index), ...notes().splice(index + 1)]);
|
|
953
|
+
};
|
|
954
|
+
return {
|
|
955
|
+
notes,
|
|
956
|
+
onNotesChange,
|
|
957
|
+
onNoteChange,
|
|
958
|
+
onInsertNote,
|
|
959
|
+
onRemoveNote
|
|
960
|
+
};
|
|
961
|
+
};
|
|
962
|
+
|
|
924
963
|
const usePianoRoll = () => {
|
|
925
964
|
const [ppq, onPpqChange] = solidJs.createSignal(120);
|
|
926
|
-
const [
|
|
965
|
+
const [mode, onModeChange] = solidJs.createSignal("tracks");
|
|
927
966
|
const [position, onPositionChange] = solidJs.createSignal(0);
|
|
928
967
|
const [zoom, onZoomChange] = solidJs.createSignal(10);
|
|
929
968
|
const [verticalZoom, onVerticalZoomChange] = solidJs.createSignal(5);
|
|
930
|
-
const [verticalPosition, onVerticalPositionChange] = solidJs.createSignal(
|
|
969
|
+
const [verticalPosition, onVerticalPositionChange] = solidJs.createSignal(44);
|
|
931
970
|
const [gridDivision, onGridDivisionChange] = solidJs.createSignal(4);
|
|
932
971
|
const [snapToGrid, onSnapToGridChange] = solidJs.createSignal(true);
|
|
933
972
|
const [duration, onDurationChange] = solidJs.createSignal(0);
|
|
@@ -946,15 +985,15 @@ const usePianoRoll = () => {
|
|
|
946
985
|
onGridDivisionChange,
|
|
947
986
|
snapToGrid,
|
|
948
987
|
onSnapToGridChange,
|
|
949
|
-
|
|
950
|
-
|
|
988
|
+
mode,
|
|
989
|
+
onModeChange,
|
|
951
990
|
duration,
|
|
952
991
|
onDurationChange
|
|
953
992
|
};
|
|
954
993
|
};
|
|
955
994
|
|
|
956
|
-
exports.MultiTrackPianoRoll = MultiTrackPianoRoll;
|
|
957
995
|
exports.PianoRoll = PianoRoll;
|
|
996
|
+
exports.PlayHead = PlayHead;
|
|
958
997
|
exports.useNotes = useNotes;
|
|
959
998
|
exports.usePianoRoll = usePianoRoll;
|
|
960
999
|
//# sourceMappingURL=index.js.map
|