solid-pianoroll 0.0.20 → 0.0.22
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 +211 -262
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +213 -264
- package/dist/esm/index.js.map +1 -1
- package/dist/source/PianoRoll.jsx +1 -1
- package/dist/source/PianoRollContext.jsx +2 -35
- package/dist/source/PianoRollKeys.jsx +6 -19
- package/dist/source/PianoRollNotes.jsx +87 -110
- package/dist/source/PianoRollTrackList.jsx +2 -3
- package/dist/source/index.jsx +1 -1
- package/dist/source/usePianoRollState.js +56 -44
- package/dist/source/{PlayHead.jsx → viewport/PlayHead.jsx} +13 -17
- package/dist/types/PianoRollContext.d.ts +67 -31
- package/dist/types/index.d.ts +1 -1
- package/dist/types/usePianoRollState.d.ts +21 -17
- package/dist/types/{PlayHead.d.ts → viewport/PlayHead.d.ts} +3 -3
- package/package.json +1 -1
package/dist/cjs/index.js
CHANGED
|
@@ -29,10 +29,88 @@ function styleInject(css, ref) {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
var css_248z$5 = ".PianoRoll-module_PianoRoll__rkRYx {\n box-sizing: border-box;\n display: flex;\n overflow: hidden;\n flex-direction: column;\n height: 100%;\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$5 = {"PianoRoll":"PianoRoll-module_PianoRoll__rkRYx","PianoRollContainer":"PianoRoll-module_PianoRollContainer__Oyxr7"};
|
|
32
|
+
var css_248z$5 = ".PianoRoll-module_PianoRoll__rkRYx {\n box-sizing: border-box;\n display: flex;\n overflow: hidden;\n flex-direction: column;\n height: 100%;\n}\n\n.PianoRoll-module_PianoRollContainer__Oyxr7 {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: row;\n}\n\n.PianoRoll-module_PianoRollLeftColumn__S6SZQ {\n display: flex;\n width: 30%;\n max-width: 250px;\n}\n";
|
|
33
|
+
var styles$5 = {"PianoRoll":"PianoRoll-module_PianoRoll__rkRYx","PianoRollContainer":"PianoRoll-module_PianoRollContainer__Oyxr7","PianoRollLeftColumn":"PianoRoll-module_PianoRollLeftColumn__S6SZQ"};
|
|
34
34
|
styleInject(css_248z$5);
|
|
35
35
|
|
|
36
|
+
const defaultState = {
|
|
37
|
+
ppq: 0,
|
|
38
|
+
mode: "keys",
|
|
39
|
+
position: 0,
|
|
40
|
+
zoom: 10,
|
|
41
|
+
verticalZoom: 5,
|
|
42
|
+
verticalPosition: 44,
|
|
43
|
+
verticalTrackZoom: 0.5,
|
|
44
|
+
verticalTrackPosition: 0,
|
|
45
|
+
gridDivision: 4,
|
|
46
|
+
snapToGrid: true,
|
|
47
|
+
duration: 0,
|
|
48
|
+
tracks: [],
|
|
49
|
+
selectedTrackIndex: 0,
|
|
50
|
+
pressedKeys: {}
|
|
51
|
+
};
|
|
52
|
+
const propNameToHandlerName = name => `on${name[0]?.toUpperCase()}${name.slice(1)}Change`;
|
|
53
|
+
const pianoRollStatePropNames = [...Object.keys(defaultState), ...Object.keys(defaultState).map(propNameToHandlerName), "onNoteChange", "onInsertNote", "onRemoveNote", "onNoteDown", "onNoteUp", "isKeyDown"];
|
|
54
|
+
const createPianoRollstate = initialState => {
|
|
55
|
+
const [state, setState] = store.createStore({
|
|
56
|
+
...defaultState,
|
|
57
|
+
...initialState
|
|
58
|
+
});
|
|
59
|
+
const handlers = Object.fromEntries(Object.entries(state).map(entry => {
|
|
60
|
+
return [propNameToHandlerName(entry[0]), value => setState(entry[0], value)];
|
|
61
|
+
}));
|
|
62
|
+
const updateNotes = async (trackIndex, getNotes) => {
|
|
63
|
+
const track = state.tracks[trackIndex];
|
|
64
|
+
if (!track) return;
|
|
65
|
+
const notes = track.notes;
|
|
66
|
+
handlers.onTracksChange([...state.tracks.slice(0, trackIndex), {
|
|
67
|
+
...track,
|
|
68
|
+
notes: getNotes(notes)
|
|
69
|
+
}, ...state.tracks.slice(trackIndex + 1)]);
|
|
70
|
+
};
|
|
71
|
+
const onNoteChange = (trackIndex, noteIndex, note) => {
|
|
72
|
+
updateNotes(trackIndex, notes => [...notes.slice(0, noteIndex), note, ...notes.slice(noteIndex + 1)]);
|
|
73
|
+
};
|
|
74
|
+
const onInsertNote = (trackIndex, note) => {
|
|
75
|
+
const track = state.tracks[trackIndex];
|
|
76
|
+
if (!track) return -1;
|
|
77
|
+
const notes = track.notes;
|
|
78
|
+
const newNoteIndex = Math.max(notes.findIndex(({
|
|
79
|
+
ticks
|
|
80
|
+
}) => ticks > note.ticks), 0);
|
|
81
|
+
updateNotes(trackIndex, notes => [...notes.slice(0, newNoteIndex), note, ...notes.slice(newNoteIndex)]);
|
|
82
|
+
return newNoteIndex;
|
|
83
|
+
};
|
|
84
|
+
const onRemoveNote = (trackIndex, noteIndex) => {
|
|
85
|
+
updateNotes(trackIndex, notes => [...notes.slice(0, noteIndex), ...notes.slice(noteIndex + 1)]);
|
|
86
|
+
};
|
|
87
|
+
const updateKeyPressedState = (trackIndex, keyNumber, value) => {
|
|
88
|
+
handlers.onPressedKeysChange?.({
|
|
89
|
+
...state.pressedKeys,
|
|
90
|
+
[trackIndex]: {
|
|
91
|
+
...state.pressedKeys[trackIndex],
|
|
92
|
+
[keyNumber]: value
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
const onNoteDown = (trackIndex, keyNumber) => {
|
|
97
|
+
updateKeyPressedState(trackIndex, keyNumber, true);
|
|
98
|
+
};
|
|
99
|
+
const onNoteUp = (trackIndex, keyNumber) => {
|
|
100
|
+
updateKeyPressedState(trackIndex, keyNumber, false);
|
|
101
|
+
};
|
|
102
|
+
const isKeyDown = (trackIndex, keyNumber) => !!state.pressedKeys[trackIndex]?.[keyNumber];
|
|
103
|
+
return solidJs.mergeProps(state, {
|
|
104
|
+
...handlers,
|
|
105
|
+
onNoteChange,
|
|
106
|
+
onInsertNote,
|
|
107
|
+
onRemoveNote,
|
|
108
|
+
onNoteDown,
|
|
109
|
+
onNoteUp,
|
|
110
|
+
isKeyDown
|
|
111
|
+
});
|
|
112
|
+
};
|
|
113
|
+
|
|
36
114
|
const PianoRollContext = solidJs.createContext();
|
|
37
115
|
const PianoRollContextProvider = PianoRollContext.Provider;
|
|
38
116
|
const usePianoRollContext = () => {
|
|
@@ -40,9 +118,9 @@ const usePianoRollContext = () => {
|
|
|
40
118
|
if (!context) throw new Error("No PianoRollContext found");
|
|
41
119
|
return context;
|
|
42
120
|
};
|
|
43
|
-
const splitContextProps = allProps => solidJs.splitProps(allProps, [
|
|
121
|
+
const splitContextProps = allProps => solidJs.splitProps(allProps, [...pianoRollStatePropNames, "showAllTracks", "showTrackList"]);
|
|
44
122
|
|
|
45
|
-
var css_248z$4 = ".PianoRollKeys-module_PianoRollKeys__5vnQ0 {\n position: relative;\n height: 100%;\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}\n\n.PianoRollKeys-module_Key__jybNC {\n transition-property: background-color, box-shadow;\n transition-duration: 200ms;\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";
|
|
123
|
+
var css_248z$4 = ".PianoRollKeys-module_PianoRollKeys__5vnQ0 {\n position: relative;\n height: 100%;\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}\n\n.PianoRollKeys-module_Key__jybNC {\n transition-property: background-color, box-shadow;\n transition-duration: 200ms;\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 transform: rotateX(0deg);\n perspective: 100px;\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 border: 1px black outset;\n}\n\n.PianoRollKeys-module_white__fR2Lm {\n background: white;\n border-top-width: 0.5px;\n border-bottom-width: 0.5px;\n border-top-right-radius: 4%;\n border-bottom-right-radius: 4%;\n}\n\n.PianoRollKeys-module_down__GcNeZ {\n transition: none;\n background: red;\n transform: rotateX(0deg) rotateY(20deg);\n}\n";
|
|
46
124
|
var styles$4 = {"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
125
|
styleInject(css_248z$4);
|
|
48
126
|
|
|
@@ -285,13 +363,7 @@ const PianoRollKeys = () => {
|
|
|
285
363
|
return web.createComponent(solidJs.Index, {
|
|
286
364
|
each: keys,
|
|
287
365
|
children: key => {
|
|
288
|
-
const isDown = solidJs.createMemo(() => context.
|
|
289
|
-
const handleKeyDown = () => {
|
|
290
|
-
context.onPressedKeysChange?.([...context.pressedKeys, key().number]);
|
|
291
|
-
};
|
|
292
|
-
const handleKeyUp = () => {
|
|
293
|
-
context.onPressedKeysChange?.([...context.pressedKeys].filter(number => number !== key().number));
|
|
294
|
-
};
|
|
366
|
+
const isDown = solidJs.createMemo(() => context.isKeyDown(context.selectedTrackIndex, key().number));
|
|
295
367
|
const virtualDimensions = solidJs.createMemo(() => verticalViewPort().calculatePixelDimensions(127 - key().number, 1));
|
|
296
368
|
const previousIsBlack = blackKeys.includes((key().number - 1) % 12);
|
|
297
369
|
const nextIsBlack = blackKeys.includes((key().number + 1) % 12);
|
|
@@ -303,69 +375,47 @@ const PianoRollKeys = () => {
|
|
|
303
375
|
const _el$2 = _tmpl$$6.cloneNode(true);
|
|
304
376
|
_el$2.addEventListener("mouseleave", () => {
|
|
305
377
|
if (isMouseDown()) {
|
|
306
|
-
|
|
378
|
+
context.onNoteUp(context.selectedTrackIndex, key().number);
|
|
307
379
|
}
|
|
308
380
|
});
|
|
309
381
|
_el$2.addEventListener("mouseenter", () => {
|
|
310
382
|
if (isMouseDown()) {
|
|
311
|
-
|
|
383
|
+
context.onNoteDown(context.selectedTrackIndex, key().number);
|
|
312
384
|
}
|
|
313
385
|
});
|
|
314
386
|
_el$2.$$mouseup = () => {
|
|
315
|
-
|
|
387
|
+
context.onNoteUp(context.selectedTrackIndex, key().number);
|
|
316
388
|
};
|
|
317
389
|
_el$2.$$mousedown = () => {
|
|
318
390
|
setIsMouseDown(true);
|
|
319
|
-
|
|
391
|
+
context.onNoteDown(context.selectedTrackIndex, key().number);
|
|
320
392
|
};
|
|
321
|
-
web.insert(_el$2, web.createComponent(solidJs.Show, {
|
|
322
|
-
get when() {
|
|
323
|
-
return key().isBlack && false;
|
|
324
|
-
},
|
|
325
|
-
get children() {
|
|
326
|
-
const _el$3 = _tmpl$$6.cloneNode(true);
|
|
327
|
-
web.effect(_p$ => {
|
|
328
|
-
const _v$3 = styles$4["black-separator"],
|
|
329
|
-
_v$4 = `${virtualDimensions().offset}px`,
|
|
330
|
-
_v$5 = `${virtualDimensions().size / 2 - 0.25}px`;
|
|
331
|
-
_v$3 !== _p$._v$3 && web.className(_el$3, _p$._v$3 = _v$3);
|
|
332
|
-
_v$4 !== _p$._v$4 && _el$3.style.setProperty("top", _p$._v$4 = _v$4);
|
|
333
|
-
_v$5 !== _p$._v$5 && _el$3.style.setProperty("height", _p$._v$5 = _v$5);
|
|
334
|
-
return _p$;
|
|
335
|
-
}, {
|
|
336
|
-
_v$3: undefined,
|
|
337
|
-
_v$4: undefined,
|
|
338
|
-
_v$5: undefined
|
|
339
|
-
});
|
|
340
|
-
return _el$3;
|
|
341
|
-
}
|
|
342
|
-
}));
|
|
343
393
|
web.effect(_p$ => {
|
|
344
|
-
const _v$
|
|
394
|
+
const _v$3 = {
|
|
345
395
|
[styles$4["Key"]]: true,
|
|
346
396
|
[styles$4["black"]]: key().isBlack,
|
|
347
397
|
[styles$4["white"]]: !key().isBlack,
|
|
348
398
|
[styles$4["down"]]: isDown()
|
|
349
399
|
},
|
|
350
|
-
_v$
|
|
351
|
-
_v$
|
|
352
|
-
_v$
|
|
353
|
-
_v$
|
|
354
|
-
_v$
|
|
355
|
-
_p$._v$
|
|
356
|
-
_v$
|
|
357
|
-
_v$
|
|
358
|
-
_v$
|
|
359
|
-
_v$
|
|
360
|
-
_v$
|
|
400
|
+
_v$4 = key().name,
|
|
401
|
+
_v$5 = key().number % 12,
|
|
402
|
+
_v$6 = `${virtualDimensions().offset - virtualDimensions().size * (!key().isBlack ? nextIsBlack ? 1 / 2 : 0 : 0)}px`,
|
|
403
|
+
_v$7 = `${virtualDimensions().size + (!key().isBlack && nextIsBlack ? virtualDimensions().size / 2 : 0) + (!key().isBlack && previousIsBlack ? virtualDimensions().size / 2 : 0)}px`,
|
|
404
|
+
_v$8 = [`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(", ");
|
|
405
|
+
_p$._v$3 = web.classList(_el$2, _v$3, _p$._v$3);
|
|
406
|
+
_v$4 !== _p$._v$4 && web.setAttribute(_el$2, "title", _p$._v$4 = _v$4);
|
|
407
|
+
_v$5 !== _p$._v$5 && web.setAttribute(_el$2, "data-index", _p$._v$5 = _v$5);
|
|
408
|
+
_v$6 !== _p$._v$6 && _el$2.style.setProperty("top", _p$._v$6 = _v$6);
|
|
409
|
+
_v$7 !== _p$._v$7 && _el$2.style.setProperty("height", _p$._v$7 = _v$7);
|
|
410
|
+
_v$8 !== _p$._v$8 && _el$2.style.setProperty("box-shadow", _p$._v$8 = _v$8);
|
|
361
411
|
return _p$;
|
|
362
412
|
}, {
|
|
413
|
+
_v$3: undefined,
|
|
414
|
+
_v$4: undefined,
|
|
415
|
+
_v$5: undefined,
|
|
363
416
|
_v$6: undefined,
|
|
364
417
|
_v$7: undefined,
|
|
365
|
-
_v$8: undefined
|
|
366
|
-
_v$9: undefined,
|
|
367
|
-
_v$10: undefined,
|
|
368
|
-
_v$11: undefined
|
|
418
|
+
_v$8: undefined
|
|
369
419
|
});
|
|
370
420
|
return _el$2;
|
|
371
421
|
}
|
|
@@ -408,72 +458,96 @@ const PianoRollNotes = props => {
|
|
|
408
458
|
const verticalViewPort = solidJs.createMemo(() => useViewPortDimension(context.mode === "keys" ? "vertical" : "verticalTracks"));
|
|
409
459
|
const horizontalViewPort = solidJs.createMemo(() => useViewPortDimension("horizontal"));
|
|
410
460
|
const gridDivisionTicks = solidJs.createMemo(() => context.ppq * 4 / context.gridDivision);
|
|
461
|
+
const [isDragging, setIsDragging] = solidJs.createSignal(false);
|
|
462
|
+
const [noteDragMode, setNoteDragMode] = solidJs.createSignal();
|
|
463
|
+
const [currentNoteIndex, setCurrentNoteIndex] = solidJs.createSignal(-1);
|
|
464
|
+
const [currentNoteTrackIndex, setCurrentNoteTrackIndex] = solidJs.createSignal(-1);
|
|
465
|
+
const [diffPosition, setDiffPosition] = solidJs.createSignal(0);
|
|
466
|
+
const [getInitialNote, setInitialNote] = solidJs.createSignal();
|
|
411
467
|
const snapValueToGridIfEnabled = (value, altKey) => context.snapToGrid && !altKey ? Math.round(value / gridDivisionTicks()) * gridDivisionTicks() : value;
|
|
412
|
-
const
|
|
413
|
-
const
|
|
414
|
-
const
|
|
415
|
-
const
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
const velocity = 127;
|
|
419
|
-
const ticks = existingNote?.ticks ?? eventPositionTicks;
|
|
420
|
-
const durationTicks = existingNote?.ticks ? eventPositionTicks - existingNote?.ticks : gridDivisionTicks();
|
|
421
|
-
const note = {
|
|
468
|
+
const calculateNoteDragValues = event => {
|
|
469
|
+
const targetTrackIndex = context.mode === "tracks" ? clamp(Math.floor(verticalViewPort().calculatePosition(event.clientY)), 0, context.tracks.length - 1) : currentNoteTrackIndex() > -1 ? currentNoteTrackIndex() : context.selectedTrackIndex;
|
|
470
|
+
const midi = context.mode === "keys" ? Math.floor(128 - verticalViewPort().calculatePosition(event.clientY)) : getInitialNote()?.midi ?? 60;
|
|
471
|
+
const horiontalPosition = horizontalViewPort().calculatePosition(event.clientX);
|
|
472
|
+
return {
|
|
473
|
+
targetTrackIndex,
|
|
422
474
|
midi,
|
|
423
|
-
|
|
424
|
-
durationTicks,
|
|
425
|
-
velocity
|
|
475
|
+
horiontalPosition
|
|
426
476
|
};
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
477
|
+
};
|
|
478
|
+
const handleMouseMove = mouseMoveEvent => {
|
|
479
|
+
const note = getInitialNote();
|
|
480
|
+
if (!note) return;
|
|
481
|
+
const {
|
|
482
|
+
targetTrackIndex,
|
|
483
|
+
midi,
|
|
484
|
+
horiontalPosition
|
|
485
|
+
} = calculateNoteDragValues(mouseMoveEvent);
|
|
486
|
+
const ticks = snapValueToGridIfEnabled(horiontalPosition - diffPosition(), mouseMoveEvent.altKey);
|
|
487
|
+
const updatedNote = {
|
|
488
|
+
...note,
|
|
489
|
+
midi,
|
|
490
|
+
...(noteDragMode() === "move" && {
|
|
491
|
+
ticks
|
|
492
|
+
}),
|
|
493
|
+
...(noteDragMode() === "trimStart" && {
|
|
494
|
+
ticks: ticks < note.ticks + note.durationTicks ? ticks : note.ticks + note.durationTicks,
|
|
495
|
+
durationTicks: ticks < note.ticks + note.durationTicks ? note.ticks + note.durationTicks - ticks : snapValueToGridIfEnabled(horiontalPosition - note.ticks, mouseMoveEvent.altKey)
|
|
496
|
+
}),
|
|
497
|
+
...(noteDragMode() === "trimEnd" && {
|
|
498
|
+
ticks: ticks < note.ticks ? ticks : note.ticks,
|
|
499
|
+
durationTicks: ticks < note.ticks ? note.ticks - ticks : snapValueToGridIfEnabled(horiontalPosition - note.ticks, mouseMoveEvent.altKey)
|
|
500
|
+
})
|
|
501
|
+
};
|
|
502
|
+
const previousTrackIndex = currentNoteTrackIndex();
|
|
503
|
+
const previousNoteIndex = currentNoteIndex();
|
|
504
|
+
if (targetTrackIndex === previousTrackIndex) {
|
|
505
|
+
context.onNoteChange?.(previousTrackIndex, previousNoteIndex, updatedNote);
|
|
430
506
|
} else {
|
|
431
|
-
|
|
507
|
+
if (context.onInsertNote) {
|
|
508
|
+
context.onRemoveNote?.(previousTrackIndex, previousNoteIndex);
|
|
509
|
+
const newNoteIndex = context.onInsertNote(targetTrackIndex, updatedNote);
|
|
510
|
+
setCurrentNoteTrackIndex(targetTrackIndex);
|
|
511
|
+
setCurrentNoteIndex(newNoteIndex);
|
|
512
|
+
}
|
|
432
513
|
}
|
|
433
514
|
};
|
|
434
|
-
const
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
const
|
|
515
|
+
const stopDragging = () => {
|
|
516
|
+
window.removeEventListener("mousemove", handleMouseMove);
|
|
517
|
+
window.removeEventListener("mouseup", stopDragging);
|
|
518
|
+
setIsDragging(false);
|
|
519
|
+
};
|
|
520
|
+
const startDragging = () => {
|
|
521
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
522
|
+
window.addEventListener("mouseup", stopDragging);
|
|
523
|
+
};
|
|
440
524
|
const getClasses = noteDragMode => {
|
|
441
525
|
return noteDragMode ? [styles$2.Note, styles$2[noteDragMode]] : [styles$2.Note];
|
|
442
526
|
};
|
|
443
527
|
return (() => {
|
|
444
528
|
const _el$ = _tmpl$$5.cloneNode(true);
|
|
445
|
-
_el$.$$
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
const index = insertOrUpdateNote(event);
|
|
468
|
-
setCurrentNoteIndex(index);
|
|
469
|
-
};
|
|
470
|
-
_el$.$$mousedown = event => {
|
|
471
|
-
solidJs.batch(() => {
|
|
472
|
-
setIsMouseDown(true);
|
|
473
|
-
const index = insertOrUpdateNote(event);
|
|
474
|
-
setCurrentNoteTrackIndex(context.selectedTrackIndex ?? 0);
|
|
475
|
-
setCurrentNoteIndex(index);
|
|
476
|
-
});
|
|
529
|
+
_el$.$$mousedown = mouseDownEvent => {
|
|
530
|
+
const {
|
|
531
|
+
targetTrackIndex,
|
|
532
|
+
midi,
|
|
533
|
+
horiontalPosition
|
|
534
|
+
} = calculateNoteDragValues(mouseDownEvent);
|
|
535
|
+
const ticks = snapValueToGridIfEnabled(horiontalPosition, mouseDownEvent.altKey);
|
|
536
|
+
const durationTicks = gridDivisionTicks();
|
|
537
|
+
const newNote = {
|
|
538
|
+
midi,
|
|
539
|
+
ticks,
|
|
540
|
+
durationTicks,
|
|
541
|
+
velocity: 100
|
|
542
|
+
};
|
|
543
|
+
const newNoteIndex = context.onInsertNote(targetTrackIndex, newNote);
|
|
544
|
+
setIsDragging(true);
|
|
545
|
+
setCurrentNoteTrackIndex(targetTrackIndex);
|
|
546
|
+
setCurrentNoteIndex(newNoteIndex);
|
|
547
|
+
setInitialNote(newNote);
|
|
548
|
+
setDiffPosition(0);
|
|
549
|
+
setNoteDragMode("trimEnd");
|
|
550
|
+
startDragging();
|
|
477
551
|
};
|
|
478
552
|
const _ref$ = props.ref;
|
|
479
553
|
typeof _ref$ === "function" ? web.use(_ref$, _el$) : props.ref = _el$;
|
|
@@ -502,55 +576,13 @@ const PianoRollNotes = props => {
|
|
|
502
576
|
const _el$2 = _tmpl$$5.cloneNode(true);
|
|
503
577
|
_el$2.$$mousedown = event => {
|
|
504
578
|
event.stopPropagation();
|
|
579
|
+
const initialPosition = horizontalViewPort().calculatePosition(event.clientX);
|
|
580
|
+
setDiffPosition(noteDragMode() === "trimEnd" ? -(note.ticks + note.durationTicks - initialPosition) : initialPosition - note.ticks);
|
|
505
581
|
setIsDragging(true);
|
|
506
582
|
setCurrentNoteIndex(noteIndex());
|
|
507
583
|
setCurrentNoteTrackIndex(trackIndex());
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
const handleMouseMove = mouseMoveEvent => {
|
|
511
|
-
const note = currentNote();
|
|
512
|
-
if (!note) return;
|
|
513
|
-
const ticks = snapValueToGridIfEnabled(Math.max(horizontalViewPort().calculatePosition(mouseMoveEvent.clientX) - diffPosition, 0), mouseMoveEvent.altKey);
|
|
514
|
-
const updatedNote = {
|
|
515
|
-
...note,
|
|
516
|
-
...(noteDragMode() === "move" && context.mode === "keys" && {
|
|
517
|
-
midi: Math.round(127 - verticalViewPort().calculatePosition(mouseMoveEvent.clientY))
|
|
518
|
-
}),
|
|
519
|
-
...((noteDragMode() === "move" || noteDragMode() === "trimStart") && {
|
|
520
|
-
ticks
|
|
521
|
-
}),
|
|
522
|
-
...(noteDragMode() === "trimStart" && {
|
|
523
|
-
durationTicks: note.durationTicks + note.ticks - ticks
|
|
524
|
-
}),
|
|
525
|
-
...(noteDragMode() === "trimEnd" && {
|
|
526
|
-
durationTicks: snapValueToGridIfEnabled(horizontalViewPort().calculatePosition(mouseMoveEvent.clientX) - note.ticks, mouseMoveEvent.altKey)
|
|
527
|
-
})
|
|
528
|
-
};
|
|
529
|
-
const previousTrackIndex = currentNoteTrackIndex();
|
|
530
|
-
const previousNoteIndex = currentNoteIndex();
|
|
531
|
-
const targetTrackIndex = context.mode === "tracks" ? clamp(Math.floor(verticalViewPort().calculatePosition(mouseMoveEvent.clientY)), 0, context.tracks.length - 1) : previousTrackIndex;
|
|
532
|
-
if (targetTrackIndex === previousTrackIndex) {
|
|
533
|
-
context.onNoteChange?.(previousTrackIndex, previousNoteIndex, updatedNote);
|
|
534
|
-
} else {
|
|
535
|
-
solidJs.batch(() => {
|
|
536
|
-
if (context.onInsertNote) {
|
|
537
|
-
context.onRemoveNote?.(previousTrackIndex, previousNoteIndex);
|
|
538
|
-
const newNoteIndex = context.onInsertNote(targetTrackIndex, updatedNote);
|
|
539
|
-
setCurrentNoteTrackIndex(targetTrackIndex);
|
|
540
|
-
setCurrentNoteIndex(newNoteIndex);
|
|
541
|
-
}
|
|
542
|
-
});
|
|
543
|
-
}
|
|
544
|
-
};
|
|
545
|
-
const handleMouseUp = () => {
|
|
546
|
-
setIsDragging(false);
|
|
547
|
-
setCurrentNoteIndex(-1);
|
|
548
|
-
setCurrentNoteTrackIndex(-1);
|
|
549
|
-
window.removeEventListener("mousemove", handleMouseMove);
|
|
550
|
-
window.removeEventListener("mouseup", handleMouseUp);
|
|
551
|
-
};
|
|
552
|
-
window.addEventListener("mousemove", handleMouseMove);
|
|
553
|
-
window.addEventListener("mouseup", handleMouseUp);
|
|
584
|
+
setInitialNote(note);
|
|
585
|
+
startDragging();
|
|
554
586
|
};
|
|
555
587
|
_el$2.$$dblclick = event => {
|
|
556
588
|
event.stopPropagation();
|
|
@@ -602,7 +634,7 @@ const PianoRollNotes = props => {
|
|
|
602
634
|
return _el$;
|
|
603
635
|
})();
|
|
604
636
|
};
|
|
605
|
-
web.delegateEvents(["mousedown", "mousemove", "
|
|
637
|
+
web.delegateEvents(["mousedown", "mousemove", "dblclick"]);
|
|
606
638
|
|
|
607
639
|
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";
|
|
608
640
|
var styles$1 = {"PianoRollGrid":"PianoRollGrid-module_PianoRollGrid__tG119","PianoRollGrid-Row":"PianoRollGrid-module_PianoRollGrid-Row__nRMCs","PianoRollGrid-Time":"PianoRollGrid-module_PianoRollGrid-Time__jLz3E"};
|
|
@@ -841,8 +873,8 @@ const ZoomSliderControl = props => {
|
|
|
841
873
|
})();
|
|
842
874
|
};
|
|
843
875
|
|
|
844
|
-
var css_248z = ".PianoRollTrackList-
|
|
845
|
-
var styles = {"PianoRollTrackList":"PianoRollTrackList-
|
|
876
|
+
var css_248z = ".PianoRollTrackList-module_PianoRollTrackList__-sDf0 {\n position: relative;\n height: 100%;\n flex: 1;\n}\n\n.PianoRollTrackList-module_Track__mZP1K {\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 cursor: \"pointer\";\n background: \"lightgrey\";\n}\n.PianoRollTrackList-module_Track__mZP1K.PianoRollTrackList-module_selected__0b-mf {\n background: \"gray\";\n}";
|
|
877
|
+
var styles = {"PianoRollTrackList":"PianoRollTrackList-module_PianoRollTrackList__-sDf0","Track":"PianoRollTrackList-module_Track__mZP1K","selected":"PianoRollTrackList-module_selected__0b-mf"};
|
|
846
878
|
styleInject(css_248z);
|
|
847
879
|
|
|
848
880
|
const _tmpl$$2 = /*#__PURE__*/web.template(`<div></div>`, 2),
|
|
@@ -866,29 +898,26 @@ const PianoRollTrackList = () => {
|
|
|
866
898
|
const _el$2 = _tmpl$2$1.cloneNode(true),
|
|
867
899
|
_el$3 = _el$2.firstChild;
|
|
868
900
|
_el$2.$$click = () => context.onSelectedTrackIndexChange?.(index);
|
|
869
|
-
_el$2.style.setProperty("cursor", "pointer");
|
|
870
901
|
web.insert(_el$2, index, _el$3);
|
|
871
902
|
web.insert(_el$2, () => track().name || "[unnamed track]", null);
|
|
872
903
|
web.effect(_p$ => {
|
|
873
904
|
const _v$ = {
|
|
874
|
-
[styles["Track"]]: true
|
|
905
|
+
[styles["Track"]]: true,
|
|
906
|
+
[styles["selected"]]: index === context.selectedTrackIndex
|
|
875
907
|
},
|
|
876
908
|
_v$2 = track().name,
|
|
877
909
|
_v$3 = `${virtualDimensions().offset}px`,
|
|
878
|
-
_v$4 = `${virtualDimensions().size}px
|
|
879
|
-
_v$5 = index === context.selectedTrackIndex ? "gray" : "lightgrey";
|
|
910
|
+
_v$4 = `${virtualDimensions().size}px`;
|
|
880
911
|
_p$._v$ = web.classList(_el$2, _v$, _p$._v$);
|
|
881
912
|
_v$2 !== _p$._v$2 && web.setAttribute(_el$2, "title", _p$._v$2 = _v$2);
|
|
882
913
|
_v$3 !== _p$._v$3 && _el$2.style.setProperty("top", _p$._v$3 = _v$3);
|
|
883
914
|
_v$4 !== _p$._v$4 && _el$2.style.setProperty("height", _p$._v$4 = _v$4);
|
|
884
|
-
_v$5 !== _p$._v$5 && _el$2.style.setProperty("background", _p$._v$5 = _v$5);
|
|
885
915
|
return _p$;
|
|
886
916
|
}, {
|
|
887
917
|
_v$: undefined,
|
|
888
918
|
_v$2: undefined,
|
|
889
919
|
_v$3: undefined,
|
|
890
|
-
_v$4: undefined
|
|
891
|
-
_v$5: undefined
|
|
920
|
+
_v$4: undefined
|
|
892
921
|
});
|
|
893
922
|
return _el$2;
|
|
894
923
|
}
|
|
@@ -973,9 +1002,6 @@ const PianoRoll = allProps => {
|
|
|
973
1002
|
orientation: "vertical",
|
|
974
1003
|
dimensionName: "verticalTracks"
|
|
975
1004
|
}), _el$3);
|
|
976
|
-
_el$3.style.setProperty("display", "flex");
|
|
977
|
-
_el$3.style.setProperty("width", "30%");
|
|
978
|
-
_el$3.style.setProperty("max-width", "250px");
|
|
979
1005
|
web.insert(_el$3, web.createComponent(solidJs.Show, {
|
|
980
1006
|
get when() {
|
|
981
1007
|
return context.showTrackList;
|
|
@@ -1017,7 +1043,16 @@ const PianoRoll = allProps => {
|
|
|
1017
1043
|
return context.mode !== "keys";
|
|
1018
1044
|
}
|
|
1019
1045
|
}), null);
|
|
1020
|
-
web.effect(
|
|
1046
|
+
web.effect(_p$ => {
|
|
1047
|
+
const _v$ = styles$5.PianoRollContainer,
|
|
1048
|
+
_v$2 = styles$5.PianoRollLeftColumn;
|
|
1049
|
+
_v$ !== _p$._v$ && web.className(_el$2, _p$._v$ = _v$);
|
|
1050
|
+
_v$2 !== _p$._v$2 && web.className(_el$3, _p$._v$2 = _v$2);
|
|
1051
|
+
return _p$;
|
|
1052
|
+
}, {
|
|
1053
|
+
_v$: undefined,
|
|
1054
|
+
_v$2: undefined
|
|
1055
|
+
});
|
|
1021
1056
|
return _el$2;
|
|
1022
1057
|
})(), web.createComponent(ZoomSliderControl, {
|
|
1023
1058
|
orientation: "horizontal",
|
|
@@ -1037,19 +1072,15 @@ const PianoRoll = allProps => {
|
|
|
1037
1072
|
|
|
1038
1073
|
const _tmpl$ = /*#__PURE__*/web.template(`<div class="PlayHead"></div>`, 2);
|
|
1039
1074
|
const PlayHead = allProps => {
|
|
1040
|
-
const
|
|
1041
|
-
|
|
1042
|
-
sync: false
|
|
1043
|
-
}, allProps);
|
|
1044
|
-
const [props, divProps] = solidJs.splitProps(propsWithDefauls, ["playHeadPosition", "sync", "onPlayHeadPositionChange", "onPositionChange"]);
|
|
1045
|
-
const viewPort = useViewPortDimension("horizontal");
|
|
1075
|
+
const [props, divProps] = solidJs.splitProps(allProps, ["position", "sync", "onPositionChange", "dimensionName"]);
|
|
1076
|
+
const viewPort = useViewPortDimension(props.dimensionName ?? "horizontal");
|
|
1046
1077
|
solidJs.createEffect(() => {
|
|
1047
1078
|
if (!props.sync) return;
|
|
1048
1079
|
const maxPosition = viewPort.range;
|
|
1049
|
-
const newPosition = clamp(props.
|
|
1050
|
-
|
|
1080
|
+
const newPosition = clamp(props.position - viewPort.range / viewPort.zoom / 2, 0, maxPosition);
|
|
1081
|
+
viewPort.onPositionChange?.(newPosition);
|
|
1051
1082
|
});
|
|
1052
|
-
const leftPosition = solidJs.createMemo(() => viewPort.calculatePixelOffset(props.
|
|
1083
|
+
const leftPosition = solidJs.createMemo(() => viewPort.calculatePixelOffset(props.position));
|
|
1053
1084
|
return (() => {
|
|
1054
1085
|
const _el$ = _tmpl$.cloneNode(true);
|
|
1055
1086
|
web.spread(_el$, web.mergeProps(divProps, {
|
|
@@ -1068,14 +1099,10 @@ const PlayHead = allProps => {
|
|
|
1068
1099
|
event.preventDefault();
|
|
1069
1100
|
event.stopPropagation();
|
|
1070
1101
|
const handleMouseMove = ({
|
|
1071
|
-
|
|
1102
|
+
clientX
|
|
1072
1103
|
}) => {
|
|
1073
|
-
const
|
|
1074
|
-
|
|
1075
|
-
} = event.currentTarget;
|
|
1076
|
-
if (!parentElement) return;
|
|
1077
|
-
const newPosition = viewPort.calculatePosition(leftPosition() + movementX);
|
|
1078
|
-
props.onPlayHeadPositionChange?.(newPosition);
|
|
1104
|
+
const newPosition = viewPort.calculatePosition(clientX);
|
|
1105
|
+
props.onPositionChange?.(newPosition);
|
|
1079
1106
|
};
|
|
1080
1107
|
const handleMouseUp = () => {
|
|
1081
1108
|
window.removeEventListener("mousemove", handleMouseMove);
|
|
@@ -1113,84 +1140,6 @@ const useNotes = () => {
|
|
|
1113
1140
|
};
|
|
1114
1141
|
};
|
|
1115
1142
|
|
|
1116
|
-
const createPianoRollstate = defaultState => {
|
|
1117
|
-
const [state, setState] = store.createStore({
|
|
1118
|
-
ppq: 0,
|
|
1119
|
-
mode: "keys",
|
|
1120
|
-
position: 0,
|
|
1121
|
-
zoom: 10,
|
|
1122
|
-
verticalZoom: 5,
|
|
1123
|
-
verticalPosition: 44,
|
|
1124
|
-
verticalTrackZoom: 0.5,
|
|
1125
|
-
verticalTrackPosition: 0,
|
|
1126
|
-
gridDivision: 4,
|
|
1127
|
-
snapToGrid: true,
|
|
1128
|
-
duration: 0,
|
|
1129
|
-
tracks: [],
|
|
1130
|
-
selectedTrackIndex: 0,
|
|
1131
|
-
pressedKeys: [],
|
|
1132
|
-
...defaultState
|
|
1133
|
-
});
|
|
1134
|
-
const updateNotes = async (trackIndex, getNotes) => {
|
|
1135
|
-
const track = state.tracks[trackIndex];
|
|
1136
|
-
if (!track) return;
|
|
1137
|
-
const notes = track.notes;
|
|
1138
|
-
onTracksChange([...state.tracks.slice(0, trackIndex), {
|
|
1139
|
-
...track,
|
|
1140
|
-
notes: getNotes(notes)
|
|
1141
|
-
}, ...state.tracks.slice(trackIndex + 1)]);
|
|
1142
|
-
};
|
|
1143
|
-
const onNoteChange = (trackIndex, noteIndex, note) => {
|
|
1144
|
-
updateNotes(trackIndex, notes => [...notes.slice(0, noteIndex), note, ...notes.slice(noteIndex + 1)]);
|
|
1145
|
-
};
|
|
1146
|
-
const onInsertNote = (trackIndex, note) => {
|
|
1147
|
-
const track = state.tracks[trackIndex];
|
|
1148
|
-
if (!track) return -1;
|
|
1149
|
-
const notes = track.notes;
|
|
1150
|
-
const newNoteIndex = Math.max(notes.findIndex(({
|
|
1151
|
-
ticks
|
|
1152
|
-
}) => ticks > note.ticks), 0);
|
|
1153
|
-
updateNotes(trackIndex, notes => [...notes.slice(0, newNoteIndex), note, ...notes.slice(newNoteIndex)]);
|
|
1154
|
-
return newNoteIndex;
|
|
1155
|
-
};
|
|
1156
|
-
const onRemoveNote = (trackIndex, noteIndex) => {
|
|
1157
|
-
updateNotes(trackIndex, notes => [...notes.slice(0, noteIndex), ...notes.slice(noteIndex + 1)]);
|
|
1158
|
-
};
|
|
1159
|
-
const onPpqChange = ppq => setState("ppq", ppq);
|
|
1160
|
-
const onModeChange = mode => setState("mode", mode);
|
|
1161
|
-
const onPositionChange = position => setState("position", position);
|
|
1162
|
-
const onZoomChange = zoom => setState("zoom", zoom);
|
|
1163
|
-
const onVerticalZoomChange = verticalZoom => setState("verticalZoom", verticalZoom);
|
|
1164
|
-
const onVerticalPositionChange = verticalPosition => setState("verticalPosition", verticalPosition);
|
|
1165
|
-
const onVerticalTrackZoomChange = verticalTrackZoom => setState("verticalTrackZoom", verticalTrackZoom);
|
|
1166
|
-
const onVerticalTrackPositionChange = verticalTrackPosition => setState("verticalTrackPosition", verticalTrackPosition);
|
|
1167
|
-
const onGridDivisionChange = gridDivision => setState("gridDivision", gridDivision);
|
|
1168
|
-
const onSnapToGridChange = snapToGrid => setState("snapToGrid", snapToGrid);
|
|
1169
|
-
const onDurationChange = duration => setState("duration", duration);
|
|
1170
|
-
const onTracksChange = tracks => setState("tracks", tracks);
|
|
1171
|
-
const onSelectedTrackIndexChange = selectedTrackIndex => setState("selectedTrackIndex", selectedTrackIndex);
|
|
1172
|
-
const onPressedKeysChange = pressedKeys => setState("pressedKeys", pressedKeys);
|
|
1173
|
-
return solidJs.mergeProps(state, {
|
|
1174
|
-
onPpqChange,
|
|
1175
|
-
onModeChange,
|
|
1176
|
-
onPositionChange,
|
|
1177
|
-
onZoomChange,
|
|
1178
|
-
onVerticalZoomChange,
|
|
1179
|
-
onVerticalPositionChange,
|
|
1180
|
-
onVerticalTrackZoomChange,
|
|
1181
|
-
onVerticalTrackPositionChange,
|
|
1182
|
-
onGridDivisionChange,
|
|
1183
|
-
onSnapToGridChange,
|
|
1184
|
-
onDurationChange,
|
|
1185
|
-
onTracksChange,
|
|
1186
|
-
onNoteChange,
|
|
1187
|
-
onInsertNote,
|
|
1188
|
-
onRemoveNote,
|
|
1189
|
-
onSelectedTrackIndexChange,
|
|
1190
|
-
onPressedKeysChange
|
|
1191
|
-
});
|
|
1192
|
-
};
|
|
1193
|
-
|
|
1194
1143
|
exports.PianoRoll = PianoRoll;
|
|
1195
1144
|
exports.PlayHead = PlayHead;
|
|
1196
1145
|
exports.createPianoRollstate = createPianoRollstate;
|