solid-pianoroll 0.0.23 → 0.0.24
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 +82 -40
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +82 -40
- package/dist/esm/index.js.map +1 -1
- package/dist/source/PianoRoll.jsx +13 -9
- package/dist/source/PianoRollNotes.jsx +6 -8
- package/dist/source/PianoRollScale.jsx +15 -1
- package/dist/source/usePianoRollState.js +22 -2
- package/dist/source/viewport/PlayHead.jsx +3 -3
- package/dist/types/PianoRoll.d.ts +0 -1
- package/dist/types/PianoRollContext.d.ts +11 -88
- package/dist/types/index.d.ts +1 -0
- package/dist/types/types.d.ts +2 -0
- package/dist/types/usePianoRollState.d.ts +29 -19
- package/dist/types/viewport/PlayHead.d.ts +1 -1
- package/package.json +1 -1
package/dist/cjs/index.js
CHANGED
|
@@ -42,6 +42,7 @@ const defaultState = {
|
|
|
42
42
|
verticalPosition: 44,
|
|
43
43
|
verticalTrackZoom: 0.5,
|
|
44
44
|
verticalTrackPosition: 0,
|
|
45
|
+
playHeadPosition: 0,
|
|
45
46
|
gridDivision: 4,
|
|
46
47
|
snapToGrid: true,
|
|
47
48
|
duration: 0,
|
|
@@ -62,15 +63,25 @@ const defaultState = {
|
|
|
62
63
|
}
|
|
63
64
|
};
|
|
64
65
|
const propNameToHandlerName = name => `on${name[0]?.toUpperCase()}${name.slice(1)}Change`;
|
|
65
|
-
const pianoRollStatePropNames = [...Object.keys(defaultState), ...Object.keys(defaultState).map(propNameToHandlerName), "onNoteChange", "onInsertNote", "onRemoveNote", "onNoteDown", "onNoteUp", "isKeyDown"];
|
|
66
|
+
const pianoRollStatePropNames = [...Object.keys(defaultState), ...Object.keys(defaultState).map(propNameToHandlerName), "onNoteChange", "onInsertNote", "onRemoveNote", "onNoteDown", "onNoteUp", "isKeyDown", "snapValueToGridIfEnabled"];
|
|
66
67
|
const createPianoRollstate = initialState => {
|
|
67
68
|
const [state, setState] = store.createStore({
|
|
68
69
|
...defaultState,
|
|
69
70
|
...initialState
|
|
70
71
|
});
|
|
71
72
|
const handlers = Object.fromEntries(Object.entries(state).map(entry => {
|
|
72
|
-
|
|
73
|
+
const handlerName = propNameToHandlerName(entry[0]);
|
|
74
|
+
return [handlerName, (value, originalEvent) => {
|
|
75
|
+
const handler = initialState?.[handlerName];
|
|
76
|
+
setState(entry[0], value);
|
|
77
|
+
if (handler) {
|
|
78
|
+
handler(value, originalEvent);
|
|
79
|
+
}
|
|
80
|
+
}];
|
|
73
81
|
}));
|
|
82
|
+
const onPlayheadPositionChange = (playheadPosition, originalEvent) => {
|
|
83
|
+
handlers.onPlayHeadPositionChange(snapValueToGridIfEnabled(playheadPosition, !!originalEvent?.altKey));
|
|
84
|
+
};
|
|
74
85
|
const updateNotes = async (trackIndex, getNotes) => {
|
|
75
86
|
const track = state.tracks[trackIndex];
|
|
76
87
|
if (!track) return;
|
|
@@ -112,6 +123,10 @@ const createPianoRollstate = initialState => {
|
|
|
112
123
|
updateKeyPressedState(trackIndex, keyNumber, false);
|
|
113
124
|
};
|
|
114
125
|
const isKeyDown = (trackIndex, keyNumber) => !!state.pressedKeys[trackIndex]?.[keyNumber];
|
|
126
|
+
const snapValueToGridIfEnabled = (value, altKey) => {
|
|
127
|
+
const gridDivisionTicks = state.ppq * 4 / state.gridDivision;
|
|
128
|
+
return state.snapToGrid && !altKey ? Math.round(value / gridDivisionTicks) * gridDivisionTicks : value;
|
|
129
|
+
};
|
|
115
130
|
return solidJs.mergeProps(state, {
|
|
116
131
|
...handlers,
|
|
117
132
|
onNoteChange,
|
|
@@ -119,7 +134,9 @@ const createPianoRollstate = initialState => {
|
|
|
119
134
|
onRemoveNote,
|
|
120
135
|
onNoteDown,
|
|
121
136
|
onNoteUp,
|
|
122
|
-
isKeyDown
|
|
137
|
+
isKeyDown,
|
|
138
|
+
snapValueToGridIfEnabled,
|
|
139
|
+
onPlayheadPositionChange
|
|
123
140
|
});
|
|
124
141
|
};
|
|
125
142
|
|
|
@@ -132,7 +149,7 @@ const usePianoRollContext = () => {
|
|
|
132
149
|
};
|
|
133
150
|
const splitContextProps = allProps => solidJs.splitProps(allProps, [...pianoRollStatePropNames, "showAllTracks", "showTrackList"]);
|
|
134
151
|
|
|
135
|
-
var css_248z$5 = ".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";
|
|
152
|
+
var css_248z$5 = ".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 background: black;\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";
|
|
136
153
|
var styles$5 = {"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"};
|
|
137
154
|
styleInject(css_248z$5);
|
|
138
155
|
|
|
@@ -476,7 +493,6 @@ const PianoRollNotes = props => {
|
|
|
476
493
|
const [currentNoteTrackIndex, setCurrentNoteTrackIndex] = solidJs.createSignal(-1);
|
|
477
494
|
const [diffPosition, setDiffPosition] = solidJs.createSignal(0);
|
|
478
495
|
const [getInitialNote, setInitialNote] = solidJs.createSignal();
|
|
479
|
-
const snapValueToGridIfEnabled = (value, altKey) => context.snapToGrid && !altKey ? Math.round(value / gridDivisionTicks()) * gridDivisionTicks() : value;
|
|
480
496
|
const calculateNoteDragValues = event => {
|
|
481
497
|
const targetTrackIndex = context.mode === "tracks" ? clamp(Math.floor(verticalViewPort().calculatePosition(event.clientY)), 0, context.tracks.length - 1) : currentNoteTrackIndex() > -1 ? currentNoteTrackIndex() : context.selectedTrackIndex;
|
|
482
498
|
const midi = context.mode === "keys" ? Math.floor(128 - verticalViewPort().calculatePosition(event.clientY)) : getInitialNote()?.midi ?? 60;
|
|
@@ -497,7 +513,7 @@ const PianoRollNotes = props => {
|
|
|
497
513
|
midi,
|
|
498
514
|
horiontalPosition
|
|
499
515
|
} = calculateNoteDragValues(mouseMoveEvent);
|
|
500
|
-
const ticks = snapValueToGridIfEnabled(horiontalPosition - diffPosition(), mouseMoveEvent.altKey);
|
|
516
|
+
const ticks = context.snapValueToGridIfEnabled(horiontalPosition - diffPosition(), mouseMoveEvent.altKey);
|
|
501
517
|
const updatedNote = {
|
|
502
518
|
...note,
|
|
503
519
|
midi,
|
|
@@ -506,11 +522,11 @@ const PianoRollNotes = props => {
|
|
|
506
522
|
}),
|
|
507
523
|
...(noteDragMode() === "trimStart" && {
|
|
508
524
|
ticks: ticks < note.ticks + note.durationTicks ? ticks : note.ticks + note.durationTicks,
|
|
509
|
-
durationTicks: ticks < note.ticks + note.durationTicks ? note.ticks + note.durationTicks - ticks : snapValueToGridIfEnabled(horiontalPosition - note.ticks, mouseMoveEvent.altKey)
|
|
525
|
+
durationTicks: ticks < note.ticks + note.durationTicks ? note.ticks + note.durationTicks - ticks : context.snapValueToGridIfEnabled(horiontalPosition - note.ticks, mouseMoveEvent.altKey)
|
|
510
526
|
}),
|
|
511
527
|
...(noteDragMode() === "trimEnd" && {
|
|
512
528
|
ticks: ticks < note.ticks ? ticks : note.ticks,
|
|
513
|
-
durationTicks: ticks < note.ticks ? note.ticks - ticks : snapValueToGridIfEnabled(horiontalPosition - note.ticks, mouseMoveEvent.altKey)
|
|
529
|
+
durationTicks: ticks < note.ticks ? note.ticks - ticks : context.snapValueToGridIfEnabled(horiontalPosition - note.ticks, mouseMoveEvent.altKey)
|
|
514
530
|
})
|
|
515
531
|
};
|
|
516
532
|
const previousTrackIndex = currentNoteTrackIndex();
|
|
@@ -550,7 +566,7 @@ const PianoRollNotes = props => {
|
|
|
550
566
|
midi,
|
|
551
567
|
horiontalPosition
|
|
552
568
|
} = calculateNoteDragValues(mouseDownEvent);
|
|
553
|
-
const ticks = snapValueToGridIfEnabled(horiontalPosition, mouseDownEvent.altKey);
|
|
569
|
+
const ticks = context.snapValueToGridIfEnabled(horiontalPosition, mouseDownEvent.altKey, context);
|
|
554
570
|
const durationTicks = gridDivisionTicks();
|
|
555
571
|
const newNote = {
|
|
556
572
|
midi,
|
|
@@ -617,17 +633,19 @@ const PianoRollNotes = props => {
|
|
|
617
633
|
web.setAttribute(_el$2, "draggable", false);
|
|
618
634
|
web.effect(_p$ => {
|
|
619
635
|
const _v$ = getClasses(noteDragMode()).join(" "),
|
|
620
|
-
_v$2 =
|
|
621
|
-
_v$3 =
|
|
622
|
-
_v$4 = `${verticalVirtualDimensions().
|
|
623
|
-
_v$5 = `${
|
|
624
|
-
_v$6 = `${horizontalDimensions().
|
|
636
|
+
_v$2 = `${track.color}`,
|
|
637
|
+
_v$3 = (note.velocity / 128 + 2) / 3,
|
|
638
|
+
_v$4 = `${verticalVirtualDimensions().offset}px`,
|
|
639
|
+
_v$5 = `${verticalVirtualDimensions().size}px`,
|
|
640
|
+
_v$6 = `${horizontalDimensions().offset}px`,
|
|
641
|
+
_v$7 = `${horizontalDimensions().size}px`;
|
|
625
642
|
_v$ !== _p$._v$ && web.className(_el$2, _p$._v$ = _v$);
|
|
626
643
|
_v$2 !== _p$._v$2 && _el$2.style.setProperty("background-color", _p$._v$2 = _v$2);
|
|
627
|
-
_v$3 !== _p$._v$3 && _el$2.style.setProperty("
|
|
628
|
-
_v$4 !== _p$._v$4 && _el$2.style.setProperty("
|
|
629
|
-
_v$5 !== _p$._v$5 && _el$2.style.setProperty("
|
|
630
|
-
_v$6 !== _p$._v$6 && _el$2.style.setProperty("
|
|
644
|
+
_v$3 !== _p$._v$3 && _el$2.style.setProperty("opacity", _p$._v$3 = _v$3);
|
|
645
|
+
_v$4 !== _p$._v$4 && _el$2.style.setProperty("top", _p$._v$4 = _v$4);
|
|
646
|
+
_v$5 !== _p$._v$5 && _el$2.style.setProperty("height", _p$._v$5 = _v$5);
|
|
647
|
+
_v$6 !== _p$._v$6 && _el$2.style.setProperty("left", _p$._v$6 = _v$6);
|
|
648
|
+
_v$7 !== _p$._v$7 && _el$2.style.setProperty("width", _p$._v$7 = _v$7);
|
|
631
649
|
return _p$;
|
|
632
650
|
}, {
|
|
633
651
|
_v$: undefined,
|
|
@@ -635,7 +653,8 @@ const PianoRollNotes = props => {
|
|
|
635
653
|
_v$3: undefined,
|
|
636
654
|
_v$4: undefined,
|
|
637
655
|
_v$5: undefined,
|
|
638
|
-
_v$6: undefined
|
|
656
|
+
_v$6: undefined,
|
|
657
|
+
_v$7: undefined
|
|
639
658
|
});
|
|
640
659
|
return _el$2;
|
|
641
660
|
}
|
|
@@ -1062,8 +1081,22 @@ const _tmpl$$2 = /*#__PURE__*/web.template(`<div></div>`, 2);
|
|
|
1062
1081
|
const PianoRollScale = () => {
|
|
1063
1082
|
const horizontalViewPort = solidJs.createMemo(() => useViewPortDimension("horizontal"));
|
|
1064
1083
|
const grid = usePianoRollGrid();
|
|
1084
|
+
const context = usePianoRollContext();
|
|
1085
|
+
const updatePlayheadPosition = event => {
|
|
1086
|
+
const position = horizontalViewPort().calculatePosition(event.clientX);
|
|
1087
|
+
context.onPlayHeadPositionChange(position, event);
|
|
1088
|
+
};
|
|
1065
1089
|
return (() => {
|
|
1066
1090
|
const _el$ = _tmpl$$2.cloneNode(true);
|
|
1091
|
+
_el$.$$mousedown = event => {
|
|
1092
|
+
updatePlayheadPosition(event);
|
|
1093
|
+
const handleMouseUp = () => {
|
|
1094
|
+
window.removeEventListener("mousemove", updatePlayheadPosition);
|
|
1095
|
+
window.removeEventListener("mouseup", handleMouseUp);
|
|
1096
|
+
};
|
|
1097
|
+
window.addEventListener("mousemove", updatePlayheadPosition);
|
|
1098
|
+
window.addEventListener("mouseup", handleMouseUp);
|
|
1099
|
+
};
|
|
1067
1100
|
web.insert(_el$, web.createComponent(solidJs.Index, {
|
|
1068
1101
|
get each() {
|
|
1069
1102
|
return grid();
|
|
@@ -1112,10 +1145,12 @@ const PianoRollScale = () => {
|
|
|
1112
1145
|
return _el$;
|
|
1113
1146
|
})();
|
|
1114
1147
|
};
|
|
1148
|
+
web.delegateEvents(["mousedown"]);
|
|
1115
1149
|
|
|
1116
1150
|
const _tmpl$$1 = /*#__PURE__*/web.template(`<div><button><div></div></button></div>`, 6),
|
|
1117
|
-
_tmpl$2 = /*#__PURE__*/web.template(`<div><div
|
|
1118
|
-
_tmpl$3 = /*#__PURE__*/web.template(`<div></div>`,
|
|
1151
|
+
_tmpl$2 = /*#__PURE__*/web.template(`<div><div></div><div></div></div>`, 6),
|
|
1152
|
+
_tmpl$3 = /*#__PURE__*/web.template(`<div><div><div></div></div></div>`, 6),
|
|
1153
|
+
_tmpl$4 = /*#__PURE__*/web.template(`<div></div>`, 2);
|
|
1119
1154
|
const PianoRoll = allProps => {
|
|
1120
1155
|
const propsWithDefaults = solidJs.mergeProps({
|
|
1121
1156
|
showAllTracks: false
|
|
@@ -1124,7 +1159,7 @@ const PianoRoll = allProps => {
|
|
|
1124
1159
|
return web.createComponent(PianoRollContextProvider, {
|
|
1125
1160
|
value: context,
|
|
1126
1161
|
get children() {
|
|
1127
|
-
const _el$ = _tmpl$
|
|
1162
|
+
const _el$ = _tmpl$4.cloneNode(true);
|
|
1128
1163
|
web.spread(_el$, web.mergeProps(divProps, {
|
|
1129
1164
|
get ["class"]() {
|
|
1130
1165
|
return styles$6.PianoRoll;
|
|
@@ -1133,11 +1168,9 @@ const PianoRoll = allProps => {
|
|
|
1133
1168
|
web.insert(_el$, web.createComponent(PianoRollScrollZoomViewPort, {
|
|
1134
1169
|
get children() {
|
|
1135
1170
|
return [(() => {
|
|
1136
|
-
const _el$2 = _tmpl$
|
|
1171
|
+
const _el$2 = _tmpl$3.cloneNode(true),
|
|
1137
1172
|
_el$3 = _el$2.firstChild,
|
|
1138
|
-
_el$7 = _el$3.firstChild
|
|
1139
|
-
_el$8 = _el$3.nextSibling,
|
|
1140
|
-
_el$9 = _el$8.firstChild;
|
|
1173
|
+
_el$7 = _el$3.firstChild;
|
|
1141
1174
|
web.insert(_el$2, web.createComponent(ZoomSliderControl, {
|
|
1142
1175
|
orientation: "vertical",
|
|
1143
1176
|
dimensionName: "verticalTracks"
|
|
@@ -1151,6 +1184,7 @@ const PianoRoll = allProps => {
|
|
|
1151
1184
|
_el$5 = _el$4.firstChild,
|
|
1152
1185
|
_el$6 = _el$5.firstChild;
|
|
1153
1186
|
_el$4.style.setProperty("height", "30px");
|
|
1187
|
+
_el$4.style.setProperty("border-right", "1px black solid");
|
|
1154
1188
|
_el$5.$$click = () => context.onModeChange(context.mode === "keys" ? "tracks" : "keys");
|
|
1155
1189
|
_el$5.style.setProperty("font-size", "16px");
|
|
1156
1190
|
_el$5.style.setProperty("line-height", "16px");
|
|
@@ -1184,16 +1218,26 @@ const PianoRoll = allProps => {
|
|
|
1184
1218
|
return web.createComponent(PianoRollKeys, {});
|
|
1185
1219
|
}
|
|
1186
1220
|
}), null);
|
|
1187
|
-
_el$
|
|
1188
|
-
_el$8.style.setProperty("display", "flex");
|
|
1189
|
-
_el$8.style.setProperty("height", "100%");
|
|
1190
|
-
_el$8.style.setProperty("flex-direction", "column");
|
|
1191
|
-
_el$8.style.setProperty("overflow", "hidden");
|
|
1192
|
-
_el$9.style.setProperty("height", "30px");
|
|
1193
|
-
web.insert(_el$9, web.createComponent(PianoRollScale, {}));
|
|
1194
|
-
web.insert(_el$8, web.createComponent(PianoRollNotesScroller, {
|
|
1221
|
+
web.insert(_el$2, web.createComponent(PianoRollNotesScroller, {
|
|
1195
1222
|
get children() {
|
|
1196
|
-
return [web.memo(() => allProps.children),
|
|
1223
|
+
return [web.memo(() => allProps.children), (() => {
|
|
1224
|
+
const _el$8 = _tmpl$2.cloneNode(true),
|
|
1225
|
+
_el$9 = _el$8.firstChild,
|
|
1226
|
+
_el$10 = _el$9.nextSibling;
|
|
1227
|
+
_el$8.style.setProperty("width", "100%");
|
|
1228
|
+
_el$8.style.setProperty("display", "flex");
|
|
1229
|
+
_el$8.style.setProperty("height", "100%");
|
|
1230
|
+
_el$8.style.setProperty("flex-direction", "column");
|
|
1231
|
+
_el$8.style.setProperty("overflow", "hidden");
|
|
1232
|
+
_el$9.style.setProperty("height", "30px");
|
|
1233
|
+
web.insert(_el$9, web.createComponent(PianoRollScale, {}));
|
|
1234
|
+
_el$10.style.setProperty("flex", "1");
|
|
1235
|
+
_el$10.style.setProperty("position", "relative");
|
|
1236
|
+
_el$10.style.setProperty("overflow", "hidden");
|
|
1237
|
+
web.insert(_el$10, web.createComponent(PianoRollGrid, {}), null);
|
|
1238
|
+
web.insert(_el$10, web.createComponent(PianoRollNotes, {}), null);
|
|
1239
|
+
return _el$8;
|
|
1240
|
+
})()];
|
|
1197
1241
|
}
|
|
1198
1242
|
}), null);
|
|
1199
1243
|
web.insert(_el$2, web.createComponent(ZoomSliderControl, {
|
|
@@ -1261,11 +1305,9 @@ const PlayHead = allProps => {
|
|
|
1261
1305
|
"onMouseDown": event => {
|
|
1262
1306
|
event.preventDefault();
|
|
1263
1307
|
event.stopPropagation();
|
|
1264
|
-
const handleMouseMove =
|
|
1265
|
-
clientX
|
|
1266
|
-
|
|
1267
|
-
const newPosition = viewPort.calculatePosition(clientX);
|
|
1268
|
-
props.onPositionChange?.(newPosition);
|
|
1308
|
+
const handleMouseMove = event => {
|
|
1309
|
+
const newPosition = viewPort.calculatePosition(event.clientX);
|
|
1310
|
+
props.onPositionChange?.(newPosition, event);
|
|
1269
1311
|
};
|
|
1270
1312
|
const handleMouseUp = () => {
|
|
1271
1313
|
window.removeEventListener("mousemove", handleMouseMove);
|