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 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
- return [propNameToHandlerName(entry[0]), value => setState(entry[0], value)];
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 = `rgba(255,0,0, ${(128 + note.velocity) / 256})`,
621
- _v$3 = `${verticalVirtualDimensions().offset}px`,
622
- _v$4 = `${verticalVirtualDimensions().size}px`,
623
- _v$5 = `${horizontalDimensions().offset}px`,
624
- _v$6 = `${horizontalDimensions().size}px`;
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("top", _p$._v$3 = _v$3);
628
- _v$4 !== _p$._v$4 && _el$2.style.setProperty("height", _p$._v$4 = _v$4);
629
- _v$5 !== _p$._v$5 && _el$2.style.setProperty("left", _p$._v$5 = _v$5);
630
- _v$6 !== _p$._v$6 && _el$2.style.setProperty("width", _p$._v$6 = _v$6);
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><div></div></div><div><div></div></div></div>`, 10),
1118
- _tmpl$3 = /*#__PURE__*/web.template(`<div></div>`, 2);
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$3.cloneNode(true);
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$2.cloneNode(true),
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$8.style.setProperty("width", "100%");
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), web.createComponent(PianoRollGrid, {}), web.createComponent(PianoRollNotes, {})];
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);