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