@minikeys/react 0.1.0 → 0.2.0

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/index.cjs CHANGED
@@ -97,12 +97,22 @@ function _object_spread_props(target, source) {
97
97
  }
98
98
  function _object_without_properties(source, excluded) {
99
99
  if (source == null) return {};
100
- var target = _object_without_properties_loose(source, excluded);
101
- var key, i;
100
+ var target = {}, sourceKeys, key, i;
101
+ if (typeof Reflect !== "undefined" && Reflect.ownKeys) {
102
+ sourceKeys = Reflect.ownKeys(source);
103
+ for(i = 0; i < sourceKeys.length; i++){
104
+ key = sourceKeys[i];
105
+ if (excluded.indexOf(key) >= 0) continue;
106
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
107
+ target[key] = source[key];
108
+ }
109
+ return target;
110
+ }
111
+ target = _object_without_properties_loose(source, excluded);
102
112
  if (Object.getOwnPropertySymbols) {
103
- var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
104
- for(i = 0; i < sourceSymbolKeys.length; i++){
105
- key = sourceSymbolKeys[i];
113
+ sourceKeys = Object.getOwnPropertySymbols(source);
114
+ for(i = 0; i < sourceKeys.length; i++){
115
+ key = sourceKeys[i];
106
116
  if (excluded.indexOf(key) >= 0) continue;
107
117
  if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
108
118
  target[key] = source[key];
@@ -112,12 +122,11 @@ function _object_without_properties(source, excluded) {
112
122
  }
113
123
  function _object_without_properties_loose(source, excluded) {
114
124
  if (source == null) return {};
115
- var target = {};
116
- var sourceKeys = Object.keys(source);
117
- var key, i;
125
+ var target = {}, sourceKeys = Object.getOwnPropertyNames(source), key, i;
118
126
  for(i = 0; i < sourceKeys.length; i++){
119
127
  key = sourceKeys[i];
120
128
  if (excluded.indexOf(key) >= 0) continue;
129
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
121
130
  target[key] = source[key];
122
131
  }
123
132
  return target;
@@ -203,7 +212,7 @@ function _templateObject5() {
203
212
  "px;\n --height: ",
204
213
  "px;\n width: var(--width);\n height: var(--height);\n /* opacity: ",
205
214
  "; */\n display: ",
206
- ";\n padding: calc(var(--height) * 0.05);\n\n transition: transform 0.3s ease, opacity 0.3s ease;\n opacity: 0;\n transform: translateY(calc(var(--height) * -0.1));\n ",
215
+ ";\n padding: calc(var(--height) * 0.05);\n\n transition:\n transform 0.3s ease,\n opacity 0.3s ease;\n opacity: 0;\n transform: translateY(calc(var(--height) * -0.1));\n ",
207
216
  "\n"
208
217
  ]);
209
218
  _templateObject5 = function _templateObject() {
@@ -231,7 +240,7 @@ function _templateObject7() {
231
240
  }
232
241
  function _templateObject8() {
233
242
  var data = _tagged_template_literal([
234
- "\n transform: translateY(calc(var(--height) * 0.03));\n box-shadow: 0 calc(var(--height) * 0.01) calc(var(--height) * 0.03)\n calc(var(--height) * 0.01) rgba(0, 0, 0, 0),\n rgba(255, 255, 255, 0.2) 0px calc(var(--height) * 0.03)\n calc(var(--height) * 0.04) 0px inset;\n"
243
+ "\n transform: translateY(calc(var(--height) * 0.03));\n box-shadow:\n 0 calc(var(--height) * 0.01) calc(var(--height) * 0.03)\n calc(var(--height) * 0.01) rgba(0, 0, 0, 0),\n rgba(255, 255, 255, 0.2) 0px calc(var(--height) * 0.03)\n calc(var(--height) * 0.04) 0px inset;\n"
235
244
  ]);
236
245
  _templateObject8 = function _templateObject() {
237
246
  return data;
@@ -312,7 +321,7 @@ function _templateObject15() {
312
321
  }
313
322
  function _templateObject16() {
314
323
  var data = _tagged_template_literal([
315
- "\n position: relative;\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n border-radius: calc(var(--height) * 0.06);\n font-family: sans-serif;\n padding: calc(var(--height) * 0.08);\n font-size: calc(var(--height) * 0.15);\n cursor: pointer;\n user-select: none;\n box-shadow: 0 calc(var(--height) * 0.01) calc(var(--height) * 0.03)\n calc(var(--height) * 0.01) rgba(0, 0, 0, 0.1),\n rgba(255, 255, 255, 0.1) 0px calc(var(--height) * 0.03)\n calc(var(--height) * 0.04) 0px inset;\n transition: all 0.3s ease;\n\n ",
324
+ "\n position: relative;\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n border-radius: calc(var(--height) * 0.06);\n font-family: sans-serif;\n padding: calc(var(--height) * 0.08);\n font-size: calc(var(--height) * 0.15);\n cursor: pointer;\n user-select: none;\n box-shadow:\n 0 calc(var(--height) * 0.01) calc(var(--height) * 0.03)\n calc(var(--height) * 0.01) rgba(0, 0, 0, 0.1),\n rgba(255, 255, 255, 0.1) 0px calc(var(--height) * 0.03)\n calc(var(--height) * 0.04) 0px inset;\n transition: all 0.3s ease;\n\n ",
316
325
  "\n\n ",
317
326
  "\n\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n\n ",
318
327
  "\n"
@@ -472,15 +481,16 @@ module.exports = __toCommonJS(index_exports);
472
481
  // src/hooks/useKeyboardControl.ts
473
482
  var import_minikeys = require("minikeys");
474
483
  var import_react = require("react");
475
- var useKeyboardControl = function(keyMap, playNoteFromMidi, modifierKeys) {
484
+ var useKeyboardControl = function(keyMap, playNoteFromMidi, liftNoteFromMidi, modifierKeys) {
476
485
  var _ref = _sliced_to_array((0, import_react.useState)([]), 2), activeKeys = _ref[0], setActiveKeys = _ref[1];
486
+ var activeKeysRef = (0, import_react.useRef)(activeKeys);
477
487
  (0, import_react.useEffect)(function() {
478
488
  var handleKeyDown = function(event) {
479
489
  var _keyMap_get;
480
490
  var modifierKey = modifierKeys === null || modifierKeys === void 0 ? void 0 : modifierKeys.find(function(modifierKey2) {
481
491
  return modifierKey2.keyCode === event.code;
482
492
  });
483
- if (!modifierKey && activeKeys.some(function(key) {
493
+ if (!modifierKey && activeKeysRef.current.some(function(key) {
484
494
  return key.keyCode === event.code;
485
495
  })) {
486
496
  return;
@@ -492,21 +502,26 @@ var useKeyboardControl = function(keyMap, playNoteFromMidi, modifierKeys) {
492
502
  if (note && playNoteFromMidi) {
493
503
  playNoteFromMidi(note);
494
504
  }
495
- setActiveKeys(function(prev) {
496
- return _to_consumable_array(prev).concat([
497
- {
498
- keyCode: event.code,
499
- note: note ? import_minikeys.midiToNote[note] : void 0
500
- }
501
- ]);
502
- });
505
+ var newActiveKeys = _to_consumable_array(activeKeysRef.current).concat([
506
+ {
507
+ keyCode: event.code,
508
+ note: note ? import_minikeys.midiToNote[note] : void 0
509
+ }
510
+ ]);
511
+ setActiveKeys(newActiveKeys);
512
+ activeKeysRef.current = newActiveKeys;
503
513
  };
504
514
  var handleKeyUp = function(event) {
505
- setActiveKeys(function(prev) {
506
- return prev.filter(function(key) {
507
- return key.keyCode !== event.code;
508
- });
515
+ var _keyMap_get;
516
+ var newActiveKeys = activeKeysRef.current.filter(function(key) {
517
+ return key.keyCode !== event.code;
509
518
  });
519
+ setActiveKeys(newActiveKeys);
520
+ activeKeysRef.current = newActiveKeys;
521
+ var note = keyMap === null || keyMap === void 0 ? void 0 : (_keyMap_get = keyMap.get(event.code)) === null || _keyMap_get === void 0 ? void 0 : _keyMap_get.midiNote;
522
+ if (note && liftNoteFromMidi) {
523
+ liftNoteFromMidi(note);
524
+ }
510
525
  var modifierKey = modifierKeys === null || modifierKeys === void 0 ? void 0 : modifierKeys.find(function(modifierKey2) {
511
526
  return modifierKey2.keyCode === event.code;
512
527
  });
@@ -570,6 +585,8 @@ var useMiniKeys = function(samples) {
570
585
  return {
571
586
  playNoteFromName: minikeysRef.current ? minikeysRef.current.playNoteFromName : void 0,
572
587
  playNoteFromMidi: minikeysRef.current ? minikeysRef.current.playNoteFromMidi : void 0,
588
+ liftNoteFromName: minikeysRef.current ? minikeysRef.current.liftNoteFromName : void 0,
589
+ liftNoteFromMidi: minikeysRef.current ? minikeysRef.current.liftNoteFromMidi : void 0,
573
590
  setSustain: setMiniKeysSustain,
574
591
  sustain: sustain,
575
592
  isLoading: isLoading,
@@ -653,11 +670,9 @@ var Container = import_styled_components.default.div(_templateObject3(), functio
653
670
  // src/Keyboard/Key.tsx
654
671
  var import_jsx_runtime2 = require("react/jsx-runtime");
655
672
  var Key = function(param) {
656
- var label = param.label, size = param.size, hidden = param.hidden, hiddenOpacity = param.hiddenOpacity, baseWidth = param.baseWidth, active = param.active, keyType = param.keyType, modifier = param.modifier, delayDisplay = param.delayDisplay, indicator = param.indicator, onClick = param.onClick;
673
+ var label = param.label, size = param.size, hidden = param.hidden, hiddenOpacity = param.hiddenOpacity, baseWidth = param.baseWidth, active = param.active, keyType = param.keyType, modifier = param.modifier, delayDisplay = param.delayDisplay, indicator = param.indicator, onClick = param.onClick, onMouseUp = param.onMouseUp;
657
674
  var _ref = _sliced_to_array((0, import_react4.useState)(delayDisplay !== void 0 && delayDisplay !== null), 2), hide = _ref[0], setHide = _ref[1];
658
- if (active) {
659
- console.log(active);
660
- }
675
+ if (active) {}
661
676
  (0, import_react4.useEffect)(function() {
662
677
  if (hide) {
663
678
  setTimeout(function() {
@@ -677,6 +692,7 @@ var Key = function(param) {
677
692
  $active: active || false,
678
693
  $keyType: modifier ? "modifier" : keyType,
679
694
  onMouseDown: modifier ? modifier.action : onClick,
695
+ onMouseUp: onMouseUp,
680
696
  $bgColour: modifier === null || modifier === void 0 ? void 0 : modifier.bgColour,
681
697
  $colour: modifier === null || modifier === void 0 ? void 0 : modifier.colour,
682
698
  children: [
@@ -1053,7 +1069,7 @@ var activeKeysIncludes = function(activeKeys, key) {
1053
1069
  }).includes(key);
1054
1070
  };
1055
1071
  var Keyboard = function(param) {
1056
- var _param_width = param.width, width = _param_width === void 0 ? 1200 : _param_width, _param_dualMode = param.dualMode, dualMode = _param_dualMode === void 0 ? false : _param_dualMode, _param_showFullKeyboard = param.showFullKeyboard, showFullKeyboard = _param_showFullKeyboard === void 0 ? false : _param_showFullKeyboard, modifierKeys = param.modifierKeys, activeKeys = param.activeKeys, keyMap = param.keyMap, _param_animate = param.animate, animate = _param_animate === void 0 ? false : _param_animate, onKeyClick = param.onKeyClick;
1072
+ var _param_width = param.width, width = _param_width === void 0 ? 1200 : _param_width, _param_dualMode = param.dualMode, dualMode = _param_dualMode === void 0 ? false : _param_dualMode, _param_showFullKeyboard = param.showFullKeyboard, showFullKeyboard = _param_showFullKeyboard === void 0 ? false : _param_showFullKeyboard, modifierKeys = param.modifierKeys, activeKeys = param.activeKeys, keyMap = param.keyMap, _param_animate = param.animate, animate = _param_animate === void 0 ? false : _param_animate, onKeyClick = param.onKeyClick, onKeyUp = param.onKeyUp;
1057
1073
  var nonPlayableModifierKey = modifierKeys === null || modifierKeys === void 0 ? void 0 : modifierKeys.some(function(modifierKey) {
1058
1074
  return !Array.from(keyCodeToLabel.keys()).includes(modifierKey.keyCode);
1059
1075
  });
@@ -1074,6 +1090,11 @@ var Keyboard = function(param) {
1074
1090
  onKeyClick(midiNote);
1075
1091
  }
1076
1092
  };
1093
+ var onMouseUp = function(midiNote) {
1094
+ if (onKeyUp && midiNote !== null && midiNote !== void 0) {
1095
+ onKeyUp(midiNote);
1096
+ }
1097
+ };
1077
1098
  var displayMap = (0, import_react5.useMemo)(function() {
1078
1099
  return getDisplayMap(showFullKeyboard, dualMode, modifierKeys);
1079
1100
  }, [
@@ -1081,7 +1102,6 @@ var Keyboard = function(param) {
1081
1102
  dualMode,
1082
1103
  modifierKeys
1083
1104
  ]);
1084
- console.log(activeKeys, keyboardRows[0][1], activeKeysIncludes(activeKeys, keyboardRows[0][1]));
1085
1105
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Container3, {
1086
1106
  $width: width,
1087
1107
  children: [
@@ -1122,6 +1142,10 @@ var Keyboard = function(param) {
1122
1142
  var _keyMap_get;
1123
1143
  return handleClick(keyMap === null || keyMap === void 0 ? void 0 : (_keyMap_get = keyMap.get(keyboardRows[0][i])) === null || _keyMap_get === void 0 ? void 0 : _keyMap_get.midiNote);
1124
1144
  },
1145
+ onMouseUp: function() {
1146
+ var _keyMap_get;
1147
+ return onMouseUp(keyMap === null || keyMap === void 0 ? void 0 : (_keyMap_get = keyMap.get(keyboardRows[0][i])) === null || _keyMap_get === void 0 ? void 0 : _keyMap_get.midiNote);
1148
+ },
1125
1149
  hiddenOpacity: !displayMap.get(keyboardRows[0][i]),
1126
1150
  modifier: dualMode ? void 0 : optionalModifier([
1127
1151
  keyboardRows[0][i]
@@ -1173,6 +1197,10 @@ var Keyboard = function(param) {
1173
1197
  onClick: function() {
1174
1198
  var _keyMap_get;
1175
1199
  return handleClick(keyMap === null || keyMap === void 0 ? void 0 : (_keyMap_get = keyMap.get(keyboardRows[1][i])) === null || _keyMap_get === void 0 ? void 0 : _keyMap_get.midiNote);
1200
+ },
1201
+ onMouseUp: function() {
1202
+ var _keyMap_get;
1203
+ return onMouseUp(keyMap === null || keyMap === void 0 ? void 0 : (_keyMap_get = keyMap.get(keyboardRows[1][i])) === null || _keyMap_get === void 0 ? void 0 : _keyMap_get.midiNote);
1176
1204
  }
1177
1205
  }, i);
1178
1206
  }),
@@ -1224,6 +1252,10 @@ var Keyboard = function(param) {
1224
1252
  onClick: function() {
1225
1253
  var _keyMap_get;
1226
1254
  return handleClick(keyMap === null || keyMap === void 0 ? void 0 : (_keyMap_get = keyMap.get(keyboardRows[2][i])) === null || _keyMap_get === void 0 ? void 0 : _keyMap_get.midiNote);
1255
+ },
1256
+ onMouseUp: function() {
1257
+ var _keyMap_get;
1258
+ return onMouseUp(keyMap === null || keyMap === void 0 ? void 0 : (_keyMap_get = keyMap.get(keyboardRows[2][i])) === null || _keyMap_get === void 0 ? void 0 : _keyMap_get.midiNote);
1227
1259
  }
1228
1260
  }, i);
1229
1261
  }),
@@ -1273,6 +1305,10 @@ var Keyboard = function(param) {
1273
1305
  var _keyMap_get;
1274
1306
  return handleClick(keyMap === null || keyMap === void 0 ? void 0 : (_keyMap_get = keyMap.get(keyboardRows[3][i])) === null || _keyMap_get === void 0 ? void 0 : _keyMap_get.midiNote);
1275
1307
  },
1308
+ onMouseUp: function() {
1309
+ var _keyMap_get;
1310
+ return onMouseUp(keyMap === null || keyMap === void 0 ? void 0 : (_keyMap_get = keyMap.get(keyboardRows[3][i])) === null || _keyMap_get === void 0 ? void 0 : _keyMap_get.midiNote);
1311
+ },
1276
1312
  hiddenOpacity: !displayMap.get(keyboardRows[3][i]),
1277
1313
  modifier: dualMode ? void 0 : optionalModifier([
1278
1314
  keyboardRows[3][i]
@@ -1335,7 +1371,7 @@ var NoteLabel = import_styled_components5.default.text(_templateObject22());
1335
1371
  // src/Piano/BlackNotes.tsx
1336
1372
  var import_jsx_runtime5 = require("react/jsx-runtime");
1337
1373
  var BlackNotes = function(param) {
1338
- var numKeys = param.numKeys, width = param.width, height = param.height, strokeWidth = param.strokeWidth, baseNoteOffset = param.baseNoteOffset, showLabels = param.showLabels, highlights = param.highlights, noBorder = param.noBorder, handleClick = param.handleClick;
1374
+ var numKeys = param.numKeys, width = param.width, height = param.height, strokeWidth = param.strokeWidth, baseNoteOffset = param.baseNoteOffset, showLabels = param.showLabels, highlights = param.highlights, noBorder = param.noBorder, handleClick = param.handleClick, handleKeyUp = param.handleKeyUp;
1339
1375
  var keyWidth = (width - strokeWidth / 2) / numKeys + strokeWidth / 2 * ((numKeys - 1) / numKeys);
1340
1376
  var getFill = function(i) {
1341
1377
  var note = import_minikeys4.keyboardBlackNotes[baseNoteOffset + i];
@@ -1375,6 +1411,13 @@ var BlackNotes = function(param) {
1375
1411
  onMouseDown: function() {
1376
1412
  return handleNoteClick(i);
1377
1413
  },
1414
+ onMouseUp: function() {
1415
+ var note = import_minikeys4.keyboardBlackNotes[baseNoteOffset + i];
1416
+ if (note === null) {
1417
+ return;
1418
+ }
1419
+ return handleKeyUp && handleKeyUp(import_minikeys4.noteToMidi[note]);
1420
+ },
1378
1421
  children: [
1379
1422
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PianoKeyRect, {
1380
1423
  width: keyWidth * 0.65,
@@ -1478,17 +1521,17 @@ var prevWhiteNoteIndex = function(note) {
1478
1521
  // src/Piano/WhiteNotes.tsx
1479
1522
  var import_jsx_runtime6 = require("react/jsx-runtime");
1480
1523
  var WhiteNotes = function(param) {
1481
- var numKeys = param.numKeys, width = param.width, height = param.height, strokeWidth = param.strokeWidth, strokeColour = param.strokeColour, baseNoteOffset = param.baseNoteOffset, showLabels = param.showLabels, highlights = param.highlights, noBorder = param.noBorder, handleClick = param.handleClick;
1524
+ var numKeys = param.numKeys, width = param.width, height = param.height, strokeWidth = param.strokeWidth, strokeColour = param.strokeColour, baseNoteOffset = param.baseNoteOffset, showLabels = param.showLabels, highlights = param.highlights, noBorder = param.noBorder, handleClick = param.handleClick, handleKeyUp = param.handleKeyUp;
1482
1525
  var keyWidth = (width - strokeWidth / 2) / numKeys + strokeWidth / 2 * ((numKeys - 1) / numKeys);
1483
1526
  var getFill = function(i) {
1484
1527
  var _highlights_activeNotes;
1485
1528
  if (highlights === null || highlights === void 0 ? void 0 : (_highlights_activeNotes = highlights.activeNotes) === null || _highlights_activeNotes === void 0 ? void 0 : _highlights_activeNotes.includes(import_minikeys5.keyboardWhiteNotes[baseNoteOffset + i])) {
1486
1529
  return "#ccc";
1487
1530
  } else if ((highlights === null || highlights === void 0 ? void 0 : highlights.rangeStart) || (highlights === null || highlights === void 0 ? void 0 : highlights.rangeEnd)) {
1488
- var _highlights_rangeStart, _highlights_rangeEnd;
1489
- if (import_minikeys5.keyboardWhiteNotes.slice(nextWhiteNoteIndex((_highlights_rangeStart = highlights === null || highlights === void 0 ? void 0 : highlights.rangeStart) !== null && _highlights_rangeStart !== void 0 ? _highlights_rangeStart : "A0"), prevWhiteNoteIndex((_highlights_rangeEnd = highlights === null || highlights === void 0 ? void 0 : highlights.rangeEnd) !== null && _highlights_rangeEnd !== void 0 ? _highlights_rangeEnd : "C8") + 1).includes(import_minikeys5.keyboardWhiteNotes[baseNoteOffset + i])) {
1490
- var _highlights_rangeColor;
1491
- return (_highlights_rangeColor = highlights === null || highlights === void 0 ? void 0 : highlights.rangeColor) !== null && _highlights_rangeColor !== void 0 ? _highlights_rangeColor : "#eee";
1531
+ var _ref, _ref1;
1532
+ if (import_minikeys5.keyboardWhiteNotes.slice(nextWhiteNoteIndex((_ref = highlights === null || highlights === void 0 ? void 0 : highlights.rangeStart) !== null && _ref !== void 0 ? _ref : "A0"), prevWhiteNoteIndex((_ref1 = highlights === null || highlights === void 0 ? void 0 : highlights.rangeEnd) !== null && _ref1 !== void 0 ? _ref1 : "C8") + 1).includes(import_minikeys5.keyboardWhiteNotes[baseNoteOffset + i])) {
1533
+ var _ref2;
1534
+ return (_ref2 = highlights === null || highlights === void 0 ? void 0 : highlights.rangeColor) !== null && _ref2 !== void 0 ? _ref2 : "#eee";
1492
1535
  }
1493
1536
  }
1494
1537
  return "white";
@@ -1508,6 +1551,9 @@ var WhiteNotes = function(param) {
1508
1551
  onMouseDown: function() {
1509
1552
  return handleNoteClick(i);
1510
1553
  },
1554
+ onMouseUp: function() {
1555
+ return handleKeyUp && handleKeyUp(import_minikeys5.noteToMidi[import_minikeys5.keyboardWhiteNotes[baseNoteOffset + i]]);
1556
+ },
1511
1557
  children: [
1512
1558
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PianoKeyRect, {
1513
1559
  width: keyWidth,
@@ -1534,8 +1580,8 @@ var WhiteNotes = function(param) {
1534
1580
  };
1535
1581
  // src/Piano/Piano.tsx
1536
1582
  var import_jsx_runtime7 = require("react/jsx-runtime");
1537
- var Piano = function(_param) {
1538
- var width = _param.width, _param_numKeys = _param.numKeys, numKeys = _param_numKeys === void 0 ? 15 : _param_numKeys, height = _param.height, _param_strokeWidth = _param.strokeWidth, strokeWidth = _param_strokeWidth === void 0 ? 1.5 : _param_strokeWidth, strokeColour = _param.strokeColour, _param_baseNote = _param.baseNote, baseNote = _param_baseNote === void 0 ? "C4" : _param_baseNote, _param_showLabels = _param.showLabels, showLabels = _param_showLabels === void 0 ? false : _param_showLabels, _param_noBorder = _param.noBorder, noBorder = _param_noBorder === void 0 ? false : _param_noBorder, highlights = _param.highlights, onClick = _param.onClick, props = _object_without_properties(_param, [
1583
+ var Piano = function(_0) {
1584
+ var width = _0.width, _0_numKeys = _0.numKeys, numKeys = _0_numKeys === void 0 ? 15 : _0_numKeys, height = _0.height, _0_strokeWidth = _0.strokeWidth, strokeWidth = _0_strokeWidth === void 0 ? 1.5 : _0_strokeWidth, strokeColour = _0.strokeColour, _0_baseNote = _0.baseNote, baseNote = _0_baseNote === void 0 ? "C4" : _0_baseNote, _0_showLabels = _0.showLabels, showLabels = _0_showLabels === void 0 ? false : _0_showLabels, _0_noBorder = _0.noBorder, noBorder = _0_noBorder === void 0 ? false : _0_noBorder, highlights = _0.highlights, onClick = _0.onClick, onKeyUp = _0.onKeyUp, props = _object_without_properties(_0, [
1539
1585
  "width",
1540
1586
  "numKeys",
1541
1587
  "height",
@@ -1545,7 +1591,8 @@ var Piano = function(_param) {
1545
1591
  "showLabels",
1546
1592
  "noBorder",
1547
1593
  "highlights",
1548
- "onClick"
1594
+ "onClick",
1595
+ "onKeyUp"
1549
1596
  ]);
1550
1597
  var keyHeight = height !== null && height !== void 0 ? height : Math.min(width / numKeys * 5, width / 4);
1551
1598
  var maxNumKeys = Math.min(numKeys, 52);
@@ -1555,6 +1602,11 @@ var Piano = function(_param) {
1555
1602
  onClick(midiNote);
1556
1603
  }
1557
1604
  };
1605
+ var handleKeyUp = function(midiNote) {
1606
+ if (onKeyUp && midiNote !== null && midiNote !== void 0) {
1607
+ onKeyUp(midiNote);
1608
+ }
1609
+ };
1558
1610
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Svg, _object_spread_props(_object_spread({
1559
1611
  viewBox: "0 0 ".concat(width, " ").concat(keyHeight),
1560
1612
  width: width,
@@ -1573,6 +1625,7 @@ var Piano = function(_param) {
1573
1625
  showLabels: showLabels,
1574
1626
  highlights: highlights,
1575
1627
  handleClick: handleClick,
1628
+ handleKeyUp: handleKeyUp,
1576
1629
  noBorder: noBorder
1577
1630
  })
1578
1631
  }),
@@ -1586,6 +1639,7 @@ var Piano = function(_param) {
1586
1639
  showLabels: showLabels,
1587
1640
  highlights: highlights,
1588
1641
  handleClick: handleClick,
1642
+ handleKeyUp: handleKeyUp,
1589
1643
  noBorder: noBorder
1590
1644
  })
1591
1645
  })
package/dist/index.d.cts CHANGED
@@ -30,16 +30,19 @@ type KeyboardProps = {
30
30
  keyMap: KeyMap | undefined;
31
31
  animate?: boolean;
32
32
  onKeyClick?: (midiNote: number) => void;
33
+ onKeyUp?: (midiNote: number) => void;
33
34
  };
34
- declare const Keyboard: ({ width, dualMode, showFullKeyboard, modifierKeys, activeKeys, keyMap, animate, onKeyClick, }: KeyboardProps) => react_jsx_runtime.JSX.Element;
35
+ declare const Keyboard: ({ width, dualMode, showFullKeyboard, modifierKeys, activeKeys, keyMap, animate, onKeyClick, onKeyUp, }: KeyboardProps) => react_jsx_runtime.JSX.Element;
35
36
 
36
- declare const useKeyboardControl: (keyMap: KeyMap | undefined, playNoteFromMidi?: (midiNote: number, velocity?: number) => void, modifierKeys?: ModifierKey[]) => {
37
+ declare const useKeyboardControl: (keyMap: KeyMap | undefined, playNoteFromMidi?: (midiNote: number, velocity?: number) => void, liftNoteFromMidi?: (midiNote: number) => void, modifierKeys?: ModifierKey[]) => {
37
38
  activeKeys: ActiveKey[];
38
39
  };
39
40
 
40
41
  declare const useMiniKeys: (samples: Sample[]) => {
41
42
  playNoteFromName: ((noteName: minikeys.NoteName, velocity?: number) => void) | undefined;
42
43
  playNoteFromMidi: ((midiNote: number, velocity?: number) => void) | undefined;
44
+ liftNoteFromName: ((noteName: minikeys.NoteName, velocity?: number) => void) | undefined;
45
+ liftNoteFromMidi: ((midiNote: number) => void) | undefined;
43
46
  setSustain: (sustain: boolean) => void;
44
47
  sustain: boolean;
45
48
  isLoading: boolean;
@@ -72,7 +75,8 @@ type PianoProps = {
72
75
  highlights?: Highlights;
73
76
  noBorder?: boolean;
74
77
  onClick?: (midiNote: number) => void;
78
+ onKeyUp?: (midiNote: number) => void;
75
79
  };
76
- declare const Piano: ({ width, numKeys, height, strokeWidth, strokeColour, baseNote, showLabels, noBorder, highlights, onClick, ...props }: PianoProps) => react_jsx_runtime.JSX.Element;
80
+ declare const Piano: ({ width, numKeys, height, strokeWidth, strokeColour, baseNote, showLabels, noBorder, highlights, onClick, onKeyUp, ...props }: PianoProps) => react_jsx_runtime.JSX.Element;
77
81
 
78
82
  export { type Highlights, Keyboard, type KeyboardProps, type ModifierKey, Piano, type PianoProps, useKeyboardControl, useMiniKeys, useMiniKeysKeyboard };
package/dist/index.d.ts CHANGED
@@ -30,16 +30,19 @@ type KeyboardProps = {
30
30
  keyMap: KeyMap | undefined;
31
31
  animate?: boolean;
32
32
  onKeyClick?: (midiNote: number) => void;
33
+ onKeyUp?: (midiNote: number) => void;
33
34
  };
34
- declare const Keyboard: ({ width, dualMode, showFullKeyboard, modifierKeys, activeKeys, keyMap, animate, onKeyClick, }: KeyboardProps) => react_jsx_runtime.JSX.Element;
35
+ declare const Keyboard: ({ width, dualMode, showFullKeyboard, modifierKeys, activeKeys, keyMap, animate, onKeyClick, onKeyUp, }: KeyboardProps) => react_jsx_runtime.JSX.Element;
35
36
 
36
- declare const useKeyboardControl: (keyMap: KeyMap | undefined, playNoteFromMidi?: (midiNote: number, velocity?: number) => void, modifierKeys?: ModifierKey[]) => {
37
+ declare const useKeyboardControl: (keyMap: KeyMap | undefined, playNoteFromMidi?: (midiNote: number, velocity?: number) => void, liftNoteFromMidi?: (midiNote: number) => void, modifierKeys?: ModifierKey[]) => {
37
38
  activeKeys: ActiveKey[];
38
39
  };
39
40
 
40
41
  declare const useMiniKeys: (samples: Sample[]) => {
41
42
  playNoteFromName: ((noteName: minikeys.NoteName, velocity?: number) => void) | undefined;
42
43
  playNoteFromMidi: ((midiNote: number, velocity?: number) => void) | undefined;
44
+ liftNoteFromName: ((noteName: minikeys.NoteName, velocity?: number) => void) | undefined;
45
+ liftNoteFromMidi: ((midiNote: number) => void) | undefined;
43
46
  setSustain: (sustain: boolean) => void;
44
47
  sustain: boolean;
45
48
  isLoading: boolean;
@@ -72,7 +75,8 @@ type PianoProps = {
72
75
  highlights?: Highlights;
73
76
  noBorder?: boolean;
74
77
  onClick?: (midiNote: number) => void;
78
+ onKeyUp?: (midiNote: number) => void;
75
79
  };
76
- declare const Piano: ({ width, numKeys, height, strokeWidth, strokeColour, baseNote, showLabels, noBorder, highlights, onClick, ...props }: PianoProps) => react_jsx_runtime.JSX.Element;
80
+ declare const Piano: ({ width, numKeys, height, strokeWidth, strokeColour, baseNote, showLabels, noBorder, highlights, onClick, onKeyUp, ...props }: PianoProps) => react_jsx_runtime.JSX.Element;
77
81
 
78
82
  export { type Highlights, Keyboard, type KeyboardProps, type ModifierKey, Piano, type PianoProps, useKeyboardControl, useMiniKeys, useMiniKeysKeyboard };
package/dist/index.js CHANGED
@@ -1,4 +1,3 @@
1
- // src/hooks/useKeyboardControl.ts
2
1
  function _array_like_to_array(arr, len) {
3
2
  if (len == null || len > arr.length) len = arr.length;
4
3
  for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
@@ -97,12 +96,22 @@ function _object_spread_props(target, source) {
97
96
  }
98
97
  function _object_without_properties(source, excluded) {
99
98
  if (source == null) return {};
100
- var target = _object_without_properties_loose(source, excluded);
101
- var key, i;
99
+ var target = {}, sourceKeys, key, i;
100
+ if (typeof Reflect !== "undefined" && Reflect.ownKeys) {
101
+ sourceKeys = Reflect.ownKeys(source);
102
+ for(i = 0; i < sourceKeys.length; i++){
103
+ key = sourceKeys[i];
104
+ if (excluded.indexOf(key) >= 0) continue;
105
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
106
+ target[key] = source[key];
107
+ }
108
+ return target;
109
+ }
110
+ target = _object_without_properties_loose(source, excluded);
102
111
  if (Object.getOwnPropertySymbols) {
103
- var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
104
- for(i = 0; i < sourceSymbolKeys.length; i++){
105
- key = sourceSymbolKeys[i];
112
+ sourceKeys = Object.getOwnPropertySymbols(source);
113
+ for(i = 0; i < sourceKeys.length; i++){
114
+ key = sourceKeys[i];
106
115
  if (excluded.indexOf(key) >= 0) continue;
107
116
  if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
108
117
  target[key] = source[key];
@@ -112,12 +121,11 @@ function _object_without_properties(source, excluded) {
112
121
  }
113
122
  function _object_without_properties_loose(source, excluded) {
114
123
  if (source == null) return {};
115
- var target = {};
116
- var sourceKeys = Object.keys(source);
117
- var key, i;
124
+ var target = {}, sourceKeys = Object.getOwnPropertyNames(source), key, i;
118
125
  for(i = 0; i < sourceKeys.length; i++){
119
126
  key = sourceKeys[i];
120
127
  if (excluded.indexOf(key) >= 0) continue;
128
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
121
129
  target[key] = source[key];
122
130
  }
123
131
  return target;
@@ -199,7 +207,7 @@ function _templateObject5() {
199
207
  "px;\n --height: ",
200
208
  "px;\n width: var(--width);\n height: var(--height);\n /* opacity: ",
201
209
  "; */\n display: ",
202
- ";\n padding: calc(var(--height) * 0.05);\n\n transition: transform 0.3s ease, opacity 0.3s ease;\n opacity: 0;\n transform: translateY(calc(var(--height) * -0.1));\n ",
210
+ ";\n padding: calc(var(--height) * 0.05);\n\n transition:\n transform 0.3s ease,\n opacity 0.3s ease;\n opacity: 0;\n transform: translateY(calc(var(--height) * -0.1));\n ",
203
211
  "\n"
204
212
  ]);
205
213
  _templateObject5 = function _templateObject() {
@@ -227,7 +235,7 @@ function _templateObject7() {
227
235
  }
228
236
  function _templateObject8() {
229
237
  var data = _tagged_template_literal([
230
- "\n transform: translateY(calc(var(--height) * 0.03));\n box-shadow: 0 calc(var(--height) * 0.01) calc(var(--height) * 0.03)\n calc(var(--height) * 0.01) rgba(0, 0, 0, 0),\n rgba(255, 255, 255, 0.2) 0px calc(var(--height) * 0.03)\n calc(var(--height) * 0.04) 0px inset;\n"
238
+ "\n transform: translateY(calc(var(--height) * 0.03));\n box-shadow:\n 0 calc(var(--height) * 0.01) calc(var(--height) * 0.03)\n calc(var(--height) * 0.01) rgba(0, 0, 0, 0),\n rgba(255, 255, 255, 0.2) 0px calc(var(--height) * 0.03)\n calc(var(--height) * 0.04) 0px inset;\n"
231
239
  ]);
232
240
  _templateObject8 = function _templateObject() {
233
241
  return data;
@@ -308,7 +316,7 @@ function _templateObject15() {
308
316
  }
309
317
  function _templateObject16() {
310
318
  var data = _tagged_template_literal([
311
- "\n position: relative;\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n border-radius: calc(var(--height) * 0.06);\n font-family: sans-serif;\n padding: calc(var(--height) * 0.08);\n font-size: calc(var(--height) * 0.15);\n cursor: pointer;\n user-select: none;\n box-shadow: 0 calc(var(--height) * 0.01) calc(var(--height) * 0.03)\n calc(var(--height) * 0.01) rgba(0, 0, 0, 0.1),\n rgba(255, 255, 255, 0.1) 0px calc(var(--height) * 0.03)\n calc(var(--height) * 0.04) 0px inset;\n transition: all 0.3s ease;\n\n ",
319
+ "\n position: relative;\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n border-radius: calc(var(--height) * 0.06);\n font-family: sans-serif;\n padding: calc(var(--height) * 0.08);\n font-size: calc(var(--height) * 0.15);\n cursor: pointer;\n user-select: none;\n box-shadow:\n 0 calc(var(--height) * 0.01) calc(var(--height) * 0.03)\n calc(var(--height) * 0.01) rgba(0, 0, 0, 0.1),\n rgba(255, 255, 255, 0.1) 0px calc(var(--height) * 0.03)\n calc(var(--height) * 0.04) 0px inset;\n transition: all 0.3s ease;\n\n ",
312
320
  "\n\n ",
313
321
  "\n\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n\n ",
314
322
  "\n"
@@ -387,17 +395,19 @@ function _templateObject23() {
387
395
  };
388
396
  return data;
389
397
  }
398
+ // src/hooks/useKeyboardControl.ts
390
399
  import { midiToNote } from "minikeys";
391
- import { useEffect, useState } from "react";
392
- var useKeyboardControl = function(keyMap, playNoteFromMidi, modifierKeys) {
400
+ import { useEffect, useRef, useState } from "react";
401
+ var useKeyboardControl = function(keyMap, playNoteFromMidi, liftNoteFromMidi, modifierKeys) {
393
402
  var _useState = _sliced_to_array(useState([]), 2), activeKeys = _useState[0], setActiveKeys = _useState[1];
403
+ var activeKeysRef = useRef(activeKeys);
394
404
  useEffect(function() {
395
405
  var handleKeyDown = function(event) {
396
406
  var _keyMap_get;
397
407
  var modifierKey = modifierKeys === null || modifierKeys === void 0 ? void 0 : modifierKeys.find(function(modifierKey2) {
398
408
  return modifierKey2.keyCode === event.code;
399
409
  });
400
- if (!modifierKey && activeKeys.some(function(key) {
410
+ if (!modifierKey && activeKeysRef.current.some(function(key) {
401
411
  return key.keyCode === event.code;
402
412
  })) {
403
413
  return;
@@ -409,21 +419,26 @@ var useKeyboardControl = function(keyMap, playNoteFromMidi, modifierKeys) {
409
419
  if (note && playNoteFromMidi) {
410
420
  playNoteFromMidi(note);
411
421
  }
412
- setActiveKeys(function(prev) {
413
- return _to_consumable_array(prev).concat([
414
- {
415
- keyCode: event.code,
416
- note: note ? midiToNote[note] : void 0
417
- }
418
- ]);
419
- });
422
+ var newActiveKeys = _to_consumable_array(activeKeysRef.current).concat([
423
+ {
424
+ keyCode: event.code,
425
+ note: note ? midiToNote[note] : void 0
426
+ }
427
+ ]);
428
+ setActiveKeys(newActiveKeys);
429
+ activeKeysRef.current = newActiveKeys;
420
430
  };
421
431
  var handleKeyUp = function(event) {
422
- setActiveKeys(function(prev) {
423
- return prev.filter(function(key) {
424
- return key.keyCode !== event.code;
425
- });
432
+ var _keyMap_get;
433
+ var newActiveKeys = activeKeysRef.current.filter(function(key) {
434
+ return key.keyCode !== event.code;
426
435
  });
436
+ setActiveKeys(newActiveKeys);
437
+ activeKeysRef.current = newActiveKeys;
438
+ var note = keyMap === null || keyMap === void 0 ? void 0 : (_keyMap_get = keyMap.get(event.code)) === null || _keyMap_get === void 0 ? void 0 : _keyMap_get.midiNote;
439
+ if (note && liftNoteFromMidi) {
440
+ liftNoteFromMidi(note);
441
+ }
427
442
  var modifierKey = modifierKeys === null || modifierKeys === void 0 ? void 0 : modifierKeys.find(function(modifierKey2) {
428
443
  return modifierKey2.keyCode === event.code;
429
444
  });
@@ -448,9 +463,9 @@ var useKeyboardControl = function(keyMap, playNoteFromMidi, modifierKeys) {
448
463
  };
449
464
  // src/hooks/useMiniKeys.ts
450
465
  import { MiniKeys } from "minikeys";
451
- import { useEffect as useEffect2, useRef, useState as useState2 } from "react";
466
+ import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
452
467
  var useMiniKeys = function(samples) {
453
- var minikeysRef = useRef(null);
468
+ var minikeysRef = useRef2(null);
454
469
  var _useState2 = _sliced_to_array(useState2(0), 2), progress = _useState2[0], setProgress = _useState2[1];
455
470
  var _useState21 = _sliced_to_array(useState2(true), 2), isLoading = _useState21[0], setIsLoading = _useState21[1];
456
471
  var _useState22 = _sliced_to_array(useState2(false), 2), isSuccess = _useState22[0], setIsSuccess = _useState22[1];
@@ -487,6 +502,8 @@ var useMiniKeys = function(samples) {
487
502
  return {
488
503
  playNoteFromName: minikeysRef.current ? minikeysRef.current.playNoteFromName : void 0,
489
504
  playNoteFromMidi: minikeysRef.current ? minikeysRef.current.playNoteFromMidi : void 0,
505
+ liftNoteFromName: minikeysRef.current ? minikeysRef.current.liftNoteFromName : void 0,
506
+ liftNoteFromMidi: minikeysRef.current ? minikeysRef.current.liftNoteFromMidi : void 0,
490
507
  setSustain: setMiniKeysSustain,
491
508
  sustain: sustain,
492
509
  isLoading: isLoading,
@@ -497,10 +514,10 @@ var useMiniKeys = function(samples) {
497
514
  };
498
515
  // src/hooks/useMiniKeysKeyboard.ts
499
516
  import { MiniKeysKeyboard } from "minikeys";
500
- import { useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
517
+ import { useEffect as useEffect3, useRef as useRef3, useState as useState3 } from "react";
501
518
  var useMiniKeysKeyboard = function(mode) {
502
519
  var _miniKeysKeyboardRef_current;
503
- var miniKeysKeyboardRef = useRef2(null);
520
+ var miniKeysKeyboardRef = useRef3(null);
504
521
  var _useState3 = _sliced_to_array(useState3(), 2), keyMap = _useState3[0], setKeyMap = _useState3[1];
505
522
  var noteRange = (_miniKeysKeyboardRef_current = miniKeysKeyboardRef.current) === null || _miniKeysKeyboardRef_current === void 0 ? void 0 : _miniKeysKeyboardRef_current.getNoteRange();
506
523
  useEffect3(function() {
@@ -570,11 +587,9 @@ var Container = styled.div(_templateObject3(), function(param) {
570
587
  // src/Keyboard/Key.tsx
571
588
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
572
589
  var Key = function(param) {
573
- var label = param.label, size = param.size, hidden = param.hidden, hiddenOpacity = param.hiddenOpacity, baseWidth = param.baseWidth, active = param.active, keyType = param.keyType, modifier = param.modifier, delayDisplay = param.delayDisplay, indicator = param.indicator, onClick = param.onClick;
590
+ var label = param.label, size = param.size, hidden = param.hidden, hiddenOpacity = param.hiddenOpacity, baseWidth = param.baseWidth, active = param.active, keyType = param.keyType, modifier = param.modifier, delayDisplay = param.delayDisplay, indicator = param.indicator, onClick = param.onClick, onMouseUp = param.onMouseUp;
574
591
  var _useState4 = _sliced_to_array(useState4(delayDisplay !== void 0 && delayDisplay !== null), 2), hide = _useState4[0], setHide = _useState4[1];
575
- if (active) {
576
- console.log(active);
577
- }
592
+ if (active) {}
578
593
  useEffect4(function() {
579
594
  if (hide) {
580
595
  setTimeout(function() {
@@ -594,6 +609,7 @@ var Key = function(param) {
594
609
  $active: active || false,
595
610
  $keyType: modifier ? "modifier" : keyType,
596
611
  onMouseDown: modifier ? modifier.action : onClick,
612
+ onMouseUp: onMouseUp,
597
613
  $bgColour: modifier === null || modifier === void 0 ? void 0 : modifier.bgColour,
598
614
  $colour: modifier === null || modifier === void 0 ? void 0 : modifier.colour,
599
615
  children: [
@@ -970,7 +986,7 @@ var activeKeysIncludes = function(activeKeys, key) {
970
986
  }).includes(key);
971
987
  };
972
988
  var Keyboard = function(param) {
973
- var _param_width = param.width, width = _param_width === void 0 ? 1200 : _param_width, _param_dualMode = param.dualMode, dualMode = _param_dualMode === void 0 ? false : _param_dualMode, _param_showFullKeyboard = param.showFullKeyboard, showFullKeyboard = _param_showFullKeyboard === void 0 ? false : _param_showFullKeyboard, modifierKeys = param.modifierKeys, activeKeys = param.activeKeys, keyMap = param.keyMap, _param_animate = param.animate, animate = _param_animate === void 0 ? false : _param_animate, onKeyClick = param.onKeyClick;
989
+ var _param_width = param.width, width = _param_width === void 0 ? 1200 : _param_width, _param_dualMode = param.dualMode, dualMode = _param_dualMode === void 0 ? false : _param_dualMode, _param_showFullKeyboard = param.showFullKeyboard, showFullKeyboard = _param_showFullKeyboard === void 0 ? false : _param_showFullKeyboard, modifierKeys = param.modifierKeys, activeKeys = param.activeKeys, keyMap = param.keyMap, _param_animate = param.animate, animate = _param_animate === void 0 ? false : _param_animate, onKeyClick = param.onKeyClick, onKeyUp = param.onKeyUp;
974
990
  var nonPlayableModifierKey = modifierKeys === null || modifierKeys === void 0 ? void 0 : modifierKeys.some(function(modifierKey) {
975
991
  return !Array.from(keyCodeToLabel.keys()).includes(modifierKey.keyCode);
976
992
  });
@@ -991,6 +1007,11 @@ var Keyboard = function(param) {
991
1007
  onKeyClick(midiNote);
992
1008
  }
993
1009
  };
1010
+ var onMouseUp = function(midiNote) {
1011
+ if (onKeyUp && midiNote !== null && midiNote !== void 0) {
1012
+ onKeyUp(midiNote);
1013
+ }
1014
+ };
994
1015
  var displayMap = useMemo(function() {
995
1016
  return getDisplayMap(showFullKeyboard, dualMode, modifierKeys);
996
1017
  }, [
@@ -998,7 +1019,6 @@ var Keyboard = function(param) {
998
1019
  dualMode,
999
1020
  modifierKeys
1000
1021
  ]);
1001
- console.log(activeKeys, keyboardRows[0][1], activeKeysIncludes(activeKeys, keyboardRows[0][1]));
1002
1022
  return /* @__PURE__ */ jsxs2(Container3, {
1003
1023
  $width: width,
1004
1024
  children: [
@@ -1039,6 +1059,10 @@ var Keyboard = function(param) {
1039
1059
  var _keyMap_get;
1040
1060
  return handleClick(keyMap === null || keyMap === void 0 ? void 0 : (_keyMap_get = keyMap.get(keyboardRows[0][i])) === null || _keyMap_get === void 0 ? void 0 : _keyMap_get.midiNote);
1041
1061
  },
1062
+ onMouseUp: function() {
1063
+ var _keyMap_get;
1064
+ return onMouseUp(keyMap === null || keyMap === void 0 ? void 0 : (_keyMap_get = keyMap.get(keyboardRows[0][i])) === null || _keyMap_get === void 0 ? void 0 : _keyMap_get.midiNote);
1065
+ },
1042
1066
  hiddenOpacity: !displayMap.get(keyboardRows[0][i]),
1043
1067
  modifier: dualMode ? void 0 : optionalModifier([
1044
1068
  keyboardRows[0][i]
@@ -1090,6 +1114,10 @@ var Keyboard = function(param) {
1090
1114
  onClick: function() {
1091
1115
  var _keyMap_get;
1092
1116
  return handleClick(keyMap === null || keyMap === void 0 ? void 0 : (_keyMap_get = keyMap.get(keyboardRows[1][i])) === null || _keyMap_get === void 0 ? void 0 : _keyMap_get.midiNote);
1117
+ },
1118
+ onMouseUp: function() {
1119
+ var _keyMap_get;
1120
+ return onMouseUp(keyMap === null || keyMap === void 0 ? void 0 : (_keyMap_get = keyMap.get(keyboardRows[1][i])) === null || _keyMap_get === void 0 ? void 0 : _keyMap_get.midiNote);
1093
1121
  }
1094
1122
  }, i);
1095
1123
  }),
@@ -1141,6 +1169,10 @@ var Keyboard = function(param) {
1141
1169
  onClick: function() {
1142
1170
  var _keyMap_get;
1143
1171
  return handleClick(keyMap === null || keyMap === void 0 ? void 0 : (_keyMap_get = keyMap.get(keyboardRows[2][i])) === null || _keyMap_get === void 0 ? void 0 : _keyMap_get.midiNote);
1172
+ },
1173
+ onMouseUp: function() {
1174
+ var _keyMap_get;
1175
+ return onMouseUp(keyMap === null || keyMap === void 0 ? void 0 : (_keyMap_get = keyMap.get(keyboardRows[2][i])) === null || _keyMap_get === void 0 ? void 0 : _keyMap_get.midiNote);
1144
1176
  }
1145
1177
  }, i);
1146
1178
  }),
@@ -1190,6 +1222,10 @@ var Keyboard = function(param) {
1190
1222
  var _keyMap_get;
1191
1223
  return handleClick(keyMap === null || keyMap === void 0 ? void 0 : (_keyMap_get = keyMap.get(keyboardRows[3][i])) === null || _keyMap_get === void 0 ? void 0 : _keyMap_get.midiNote);
1192
1224
  },
1225
+ onMouseUp: function() {
1226
+ var _keyMap_get;
1227
+ return onMouseUp(keyMap === null || keyMap === void 0 ? void 0 : (_keyMap_get = keyMap.get(keyboardRows[3][i])) === null || _keyMap_get === void 0 ? void 0 : _keyMap_get.midiNote);
1228
+ },
1193
1229
  hiddenOpacity: !displayMap.get(keyboardRows[3][i]),
1194
1230
  modifier: dualMode ? void 0 : optionalModifier([
1195
1231
  keyboardRows[3][i]
@@ -1252,7 +1288,7 @@ var NoteLabel = styled5.text(_templateObject22());
1252
1288
  // src/Piano/BlackNotes.tsx
1253
1289
  import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
1254
1290
  var BlackNotes = function(param) {
1255
- var numKeys = param.numKeys, width = param.width, height = param.height, strokeWidth = param.strokeWidth, baseNoteOffset = param.baseNoteOffset, showLabels = param.showLabels, highlights = param.highlights, noBorder = param.noBorder, handleClick = param.handleClick;
1291
+ var numKeys = param.numKeys, width = param.width, height = param.height, strokeWidth = param.strokeWidth, baseNoteOffset = param.baseNoteOffset, showLabels = param.showLabels, highlights = param.highlights, noBorder = param.noBorder, handleClick = param.handleClick, handleKeyUp = param.handleKeyUp;
1256
1292
  var keyWidth = (width - strokeWidth / 2) / numKeys + strokeWidth / 2 * ((numKeys - 1) / numKeys);
1257
1293
  var getFill = function(i) {
1258
1294
  var note = keyboardBlackNotes[baseNoteOffset + i];
@@ -1292,6 +1328,13 @@ var BlackNotes = function(param) {
1292
1328
  onMouseDown: function() {
1293
1329
  return handleNoteClick(i);
1294
1330
  },
1331
+ onMouseUp: function() {
1332
+ var note = keyboardBlackNotes[baseNoteOffset + i];
1333
+ if (note === null) {
1334
+ return;
1335
+ }
1336
+ return handleKeyUp && handleKeyUp(noteToMidi[note]);
1337
+ },
1295
1338
  children: [
1296
1339
  /* @__PURE__ */ jsx5(PianoKeyRect, {
1297
1340
  width: keyWidth * 0.65,
@@ -1395,17 +1438,17 @@ var prevWhiteNoteIndex = function(note) {
1395
1438
  // src/Piano/WhiteNotes.tsx
1396
1439
  import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1397
1440
  var WhiteNotes = function(param) {
1398
- var numKeys = param.numKeys, width = param.width, height = param.height, strokeWidth = param.strokeWidth, strokeColour = param.strokeColour, baseNoteOffset = param.baseNoteOffset, showLabels = param.showLabels, highlights = param.highlights, noBorder = param.noBorder, handleClick = param.handleClick;
1441
+ var numKeys = param.numKeys, width = param.width, height = param.height, strokeWidth = param.strokeWidth, strokeColour = param.strokeColour, baseNoteOffset = param.baseNoteOffset, showLabels = param.showLabels, highlights = param.highlights, noBorder = param.noBorder, handleClick = param.handleClick, handleKeyUp = param.handleKeyUp;
1399
1442
  var keyWidth = (width - strokeWidth / 2) / numKeys + strokeWidth / 2 * ((numKeys - 1) / numKeys);
1400
1443
  var getFill = function(i) {
1401
1444
  var _highlights_activeNotes;
1402
1445
  if (highlights === null || highlights === void 0 ? void 0 : (_highlights_activeNotes = highlights.activeNotes) === null || _highlights_activeNotes === void 0 ? void 0 : _highlights_activeNotes.includes(keyboardWhiteNotes2[baseNoteOffset + i])) {
1403
1446
  return "#ccc";
1404
1447
  } else if ((highlights === null || highlights === void 0 ? void 0 : highlights.rangeStart) || (highlights === null || highlights === void 0 ? void 0 : highlights.rangeEnd)) {
1405
- var _highlights_rangeStart, _highlights_rangeEnd;
1406
- if (keyboardWhiteNotes2.slice(nextWhiteNoteIndex((_highlights_rangeStart = highlights === null || highlights === void 0 ? void 0 : highlights.rangeStart) !== null && _highlights_rangeStart !== void 0 ? _highlights_rangeStart : "A0"), prevWhiteNoteIndex((_highlights_rangeEnd = highlights === null || highlights === void 0 ? void 0 : highlights.rangeEnd) !== null && _highlights_rangeEnd !== void 0 ? _highlights_rangeEnd : "C8") + 1).includes(keyboardWhiteNotes2[baseNoteOffset + i])) {
1407
- var _highlights_rangeColor;
1408
- return (_highlights_rangeColor = highlights === null || highlights === void 0 ? void 0 : highlights.rangeColor) !== null && _highlights_rangeColor !== void 0 ? _highlights_rangeColor : "#eee";
1448
+ var _ref, _ref1;
1449
+ if (keyboardWhiteNotes2.slice(nextWhiteNoteIndex((_ref = highlights === null || highlights === void 0 ? void 0 : highlights.rangeStart) !== null && _ref !== void 0 ? _ref : "A0"), prevWhiteNoteIndex((_ref1 = highlights === null || highlights === void 0 ? void 0 : highlights.rangeEnd) !== null && _ref1 !== void 0 ? _ref1 : "C8") + 1).includes(keyboardWhiteNotes2[baseNoteOffset + i])) {
1450
+ var _ref2;
1451
+ return (_ref2 = highlights === null || highlights === void 0 ? void 0 : highlights.rangeColor) !== null && _ref2 !== void 0 ? _ref2 : "#eee";
1409
1452
  }
1410
1453
  }
1411
1454
  return "white";
@@ -1425,6 +1468,9 @@ var WhiteNotes = function(param) {
1425
1468
  onMouseDown: function() {
1426
1469
  return handleNoteClick(i);
1427
1470
  },
1471
+ onMouseUp: function() {
1472
+ return handleKeyUp && handleKeyUp(noteToMidi2[keyboardWhiteNotes2[baseNoteOffset + i]]);
1473
+ },
1428
1474
  children: [
1429
1475
  /* @__PURE__ */ jsx6(PianoKeyRect, {
1430
1476
  width: keyWidth,
@@ -1451,8 +1497,8 @@ var WhiteNotes = function(param) {
1451
1497
  };
1452
1498
  // src/Piano/Piano.tsx
1453
1499
  import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
1454
- var Piano = function(_param) {
1455
- var width = _param.width, _param_numKeys = _param.numKeys, numKeys = _param_numKeys === void 0 ? 15 : _param_numKeys, height = _param.height, _param_strokeWidth = _param.strokeWidth, strokeWidth = _param_strokeWidth === void 0 ? 1.5 : _param_strokeWidth, strokeColour = _param.strokeColour, _param_baseNote = _param.baseNote, baseNote = _param_baseNote === void 0 ? "C4" : _param_baseNote, _param_showLabels = _param.showLabels, showLabels = _param_showLabels === void 0 ? false : _param_showLabels, _param_noBorder = _param.noBorder, noBorder = _param_noBorder === void 0 ? false : _param_noBorder, highlights = _param.highlights, onClick = _param.onClick, props = _object_without_properties(_param, [
1500
+ var Piano = function(_0) {
1501
+ var width = _0.width, _0_numKeys = _0.numKeys, numKeys = _0_numKeys === void 0 ? 15 : _0_numKeys, height = _0.height, _0_strokeWidth = _0.strokeWidth, strokeWidth = _0_strokeWidth === void 0 ? 1.5 : _0_strokeWidth, strokeColour = _0.strokeColour, _0_baseNote = _0.baseNote, baseNote = _0_baseNote === void 0 ? "C4" : _0_baseNote, _0_showLabels = _0.showLabels, showLabels = _0_showLabels === void 0 ? false : _0_showLabels, _0_noBorder = _0.noBorder, noBorder = _0_noBorder === void 0 ? false : _0_noBorder, highlights = _0.highlights, onClick = _0.onClick, onKeyUp = _0.onKeyUp, props = _object_without_properties(_0, [
1456
1502
  "width",
1457
1503
  "numKeys",
1458
1504
  "height",
@@ -1462,7 +1508,8 @@ var Piano = function(_param) {
1462
1508
  "showLabels",
1463
1509
  "noBorder",
1464
1510
  "highlights",
1465
- "onClick"
1511
+ "onClick",
1512
+ "onKeyUp"
1466
1513
  ]);
1467
1514
  var keyHeight = height !== null && height !== void 0 ? height : Math.min(width / numKeys * 5, width / 4);
1468
1515
  var maxNumKeys = Math.min(numKeys, 52);
@@ -1472,6 +1519,11 @@ var Piano = function(_param) {
1472
1519
  onClick(midiNote);
1473
1520
  }
1474
1521
  };
1522
+ var handleKeyUp = function(midiNote) {
1523
+ if (onKeyUp && midiNote !== null && midiNote !== void 0) {
1524
+ onKeyUp(midiNote);
1525
+ }
1526
+ };
1475
1527
  return /* @__PURE__ */ jsxs5(Svg, _object_spread_props(_object_spread({
1476
1528
  viewBox: "0 0 ".concat(width, " ").concat(keyHeight),
1477
1529
  width: width,
@@ -1490,6 +1542,7 @@ var Piano = function(_param) {
1490
1542
  showLabels: showLabels,
1491
1543
  highlights: highlights,
1492
1544
  handleClick: handleClick,
1545
+ handleKeyUp: handleKeyUp,
1493
1546
  noBorder: noBorder
1494
1547
  })
1495
1548
  }),
@@ -1503,6 +1556,7 @@ var Piano = function(_param) {
1503
1556
  showLabels: showLabels,
1504
1557
  highlights: highlights,
1505
1558
  handleClick: handleClick,
1559
+ handleKeyUp: handleKeyUp,
1506
1560
  noBorder: noBorder
1507
1561
  })
1508
1562
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minikeys/react",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "homepage": "https://liamp.uk/minikeys-react",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -15,10 +15,9 @@
15
15
  "dist"
16
16
  ],
17
17
  "scripts": {
18
- "build": "tsup",
19
- "storybook": "storybook dev -p 6006",
20
- "build-storybook": "storybook build",
21
- "deploy-storybook": "storybook build && gh-pages -d storybook-static"
18
+ "build": "tsup src/index.ts --out-dir dist",
19
+ "dev": "storybook dev -p 6006",
20
+ "build:storybook": "storybook build -o storybook-static"
22
21
  },
23
22
  "author": "liamp.uk",
24
23
  "type": "module",
@@ -50,6 +49,6 @@
50
49
  "typescript": "^5.7.3"
51
50
  },
52
51
  "dependencies": {
53
- "minikeys": "0.2.0"
52
+ "minikeys": "0.3.0"
54
53
  }
55
54
  }