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