solid-pianoroll 0.0.22 → 0.0.23

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
@@ -27,9 +27,9 @@ function styleInject(css, ref) {
27
27
  }
28
28
  }
29
29
 
30
- var css_248z$5 = ".PianoRoll-module_PianoRoll__rkRYx {\n box-sizing: border-box;\n display: flex;\n overflow: hidden;\n flex-direction: column;\n height: 100%;\n}\n\n.PianoRoll-module_PianoRollContainer__Oyxr7 {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: row;\n}\n\n.PianoRoll-module_PianoRollLeftColumn__S6SZQ {\n display: flex;\n width: 30%;\n max-width: 250px;\n}\n";
31
- var styles$5 = {"PianoRoll":"PianoRoll-module_PianoRoll__rkRYx","PianoRollContainer":"PianoRoll-module_PianoRollContainer__Oyxr7","PianoRollLeftColumn":"PianoRoll-module_PianoRollLeftColumn__S6SZQ"};
32
- styleInject(css_248z$5);
30
+ var css_248z$6 = ".PianoRoll-module_PianoRoll__rkRYx {\n box-sizing: border-box;\n display: flex;\n overflow: hidden;\n flex-direction: column;\n height: 100%;\n user-select: none;\n}\n\n.PianoRoll-module_PianoRollContainer__Oyxr7 {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: row;\n}\n\n.PianoRoll-module_PianoRollLeftColumn__S6SZQ {\n display: flex;\n overflow: hidden;\n flex-direction: column;\n max-width: 250px;\n margin-top: 30px;\n}\n.PianoRoll-module_PianoRollLeftColumn__S6SZQ.PianoRoll-module_showTrackList__mqsrT {\n width: 30%;\n margin-top: 0;\n}\n\n.PianoRoll-module_PianoRollRightColumn__V98HV {\n display: flex;\n position: relative;\n flex-direction: column;\n flex: 1;\n height: 100%;\n}\n";
31
+ var styles$6 = {"PianoRoll":"PianoRoll-module_PianoRoll__rkRYx","PianoRollContainer":"PianoRoll-module_PianoRollContainer__Oyxr7","PianoRollLeftColumn":"PianoRoll-module_PianoRollLeftColumn__S6SZQ","showTrackList":"PianoRoll-module_showTrackList__mqsrT","PianoRollRightColumn":"PianoRoll-module_PianoRollRightColumn__V98HV"};
32
+ styleInject(css_248z$6);
33
33
 
34
34
  const defaultState = {
35
35
  ppq: 0,
@@ -45,7 +45,19 @@ const defaultState = {
45
45
  duration: 0,
46
46
  tracks: [],
47
47
  selectedTrackIndex: 0,
48
- pressedKeys: {}
48
+ pressedKeys: {},
49
+ notesScrollerClientRect: {
50
+ left: 0,
51
+ width: 0,
52
+ top: 0,
53
+ height: 0
54
+ },
55
+ tracksScrollerClientRect: {
56
+ left: 0,
57
+ width: 0,
58
+ top: 0,
59
+ height: 0
60
+ }
49
61
  };
50
62
  const propNameToHandlerName = name => `on${name[0]?.toUpperCase()}${name.slice(1)}Change`;
51
63
  const pianoRollStatePropNames = [...Object.keys(defaultState), ...Object.keys(defaultState).map(propNameToHandlerName), "onNoteChange", "onInsertNote", "onRemoveNote", "onNoteDown", "onNoteUp", "isKeyDown"];
@@ -118,9 +130,9 @@ const usePianoRollContext = () => {
118
130
  };
119
131
  const splitContextProps = allProps => splitProps(allProps, [...pianoRollStatePropNames, "showAllTracks", "showTrackList"]);
120
132
 
121
- var css_248z$4 = ".PianoRollKeys-module_PianoRollKeys__5vnQ0 {\n position: relative;\n height: 100%;\n border-width: 0;\n border-color: #000;\n border-style: solid;\n border-right-width: 1px;\n border-left-width: 1px;\n background: white;\n cursor: pointer;\n}\n\n.PianoRollKeys-module_Key__jybNC {\n transition-property: background-color, box-shadow;\n transition-duration: 200ms;\n transition-timing-function: ease-out;\n border-width: 0px;\n position: absolute;\n box-sizing: border-box;\n width: 120%;\n left: -20%;\n border-color: #000;\n border-style: solid;\n transform: rotateX(0deg);\n perspective: 100px;\n}\n\n.PianoRollKeys-module_black__7rncB {\n background: black;\n border-top-right-radius: 12%;\n border-bottom-right-radius: 12%;\n margin-left: -20%;\n z-index: 1;\n border: 1px black outset;\n}\n\n.PianoRollKeys-module_white__fR2Lm {\n background: white;\n border-top-width: 0.5px;\n border-bottom-width: 0.5px;\n border-top-right-radius: 4%;\n border-bottom-right-radius: 4%;\n}\n\n.PianoRollKeys-module_down__GcNeZ {\n transition: none;\n background: red;\n transform: rotateX(0deg) rotateY(20deg);\n}\n";
122
- var styles$4 = {"PianoRollKeys":"PianoRollKeys-module_PianoRollKeys__5vnQ0","Key":"PianoRollKeys-module_Key__jybNC","black":"PianoRollKeys-module_black__7rncB","white":"PianoRollKeys-module_white__fR2Lm","down":"PianoRollKeys-module_down__GcNeZ"};
123
- styleInject(css_248z$4);
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";
134
+ 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
+ styleInject(css_248z$5);
124
136
 
125
137
  function createViewPortDimension(getState) {
126
138
  const getStateWithFunctions = () => {
@@ -210,11 +222,11 @@ const useViewPortDimension = name => {
210
222
  return viewPort;
211
223
  };
212
224
 
213
- var css_248z$3 = ".ScrollZoomContainer-module_ScrollZoomContainer__o2bRt {\n height: 100%;\n width: 100%;\n z-index: 4;\n}\n";
214
- var styles$3 = {"ScrollZoomContainer":"ScrollZoomContainer-module_ScrollZoomContainer__o2bRt"};
215
- styleInject(css_248z$3);
225
+ var css_248z$4 = ".ScrollZoomContainer-module_ScrollZoomContainer__o2bRt {\n height: 100%;\n width: 100%;\n z-index: 4;\n}\n";
226
+ var styles$4 = {"ScrollZoomContainer":"ScrollZoomContainer-module_ScrollZoomContainer__o2bRt"};
227
+ styleInject(css_248z$4);
216
228
 
217
- const _tmpl$$7 = /*#__PURE__*/template(`<div><div><div><div></div></div></div></div>`, 8);
229
+ const _tmpl$$8 = /*#__PURE__*/template(`<div><div><div><div></div></div></div></div>`, 8);
218
230
  const ScrollZoomContainer = props => {
219
231
  let scrollContentRef;
220
232
  const [ownProps, divProps] = splitProps(props, ["ref", "verticalDimensionName", "horizontalDimensionName", "showScrollbar"]);
@@ -250,11 +262,11 @@ const ScrollZoomContainer = props => {
250
262
  if (event.altKey) {
251
263
  event.preventDefault();
252
264
  if (Math.abs(event.deltaX) > Math.abs(event.deltaY)) {
253
- horizontalViewPort()?.onZoomChange?.(horizontalViewPort().zoom * (1 + event.deltaX / horizontalViewPort().pixelSize));
265
+ horizontalViewPort()?.onZoomChange?.(horizontalViewPort().zoom / (1 + event.deltaX / horizontalViewPort().pixelSize));
254
266
  const maxPosition = horizontalViewPort().calculateMaxPosition();
255
267
  horizontalViewPort()?.onPositionChange?.(Math.min(maxPosition, horizontalViewPort()?.position));
256
268
  } else {
257
- verticalViewPort()?.onZoomChange?.(verticalViewPort().zoom * (1 + event.deltaY / verticalViewPort().pixelSize));
269
+ verticalViewPort()?.onZoomChange?.(verticalViewPort().zoom / (1 + event.deltaY / verticalViewPort().pixelSize));
258
270
  const maxVerticalPosition = verticalViewPort().calculateMaxPosition();
259
271
  verticalViewPort()?.onPositionChange?.(Math.min(maxVerticalPosition, verticalViewPort()?.position));
260
272
  }
@@ -286,7 +298,7 @@ const ScrollZoomContainer = props => {
286
298
  });
287
299
  });
288
300
  return (() => {
289
- const _el$ = _tmpl$$7.cloneNode(true),
301
+ const _el$ = _tmpl$$8.cloneNode(true),
290
302
  _el$2 = _el$.firstChild,
291
303
  _el$3 = _el$2.firstChild,
292
304
  _el$4 = _el$3.firstChild;
@@ -303,7 +315,7 @@ const ScrollZoomContainer = props => {
303
315
  },
304
316
  get classList() {
305
317
  return {
306
- [styles$3.ScrollZoomContainer]: true,
318
+ [styles$4.ScrollZoomContainer]: true,
307
319
  ...divProps.classList
308
320
  };
309
321
  }
@@ -336,7 +348,7 @@ const ScrollZoomContainer = props => {
336
348
  })();
337
349
  };
338
350
 
339
- const _tmpl$$6 = /*#__PURE__*/template(`<div></div>`, 2);
351
+ const _tmpl$$7 = /*#__PURE__*/template(`<div></div>`, 2);
340
352
  const PianoRollKeys = () => {
341
353
  const verticalViewPort = createMemo(() => useViewPortDimension("vertical"));
342
354
  const horizontalViewPort = createMemo(() => useViewPortDimension("horizontalKeys"));
@@ -353,7 +365,7 @@ const PianoRollKeys = () => {
353
365
  }
354
366
  });
355
367
  return (() => {
356
- const _el$ = _tmpl$$6.cloneNode(true);
368
+ const _el$ = _tmpl$$7.cloneNode(true);
357
369
  insert(_el$, createComponent(ScrollZoomContainer, {
358
370
  horizontalDimensionName: "horizontalKeys",
359
371
  showScrollbar: false,
@@ -367,10 +379,10 @@ const PianoRollKeys = () => {
367
379
  const nextIsBlack = blackKeys.includes((key().number + 1) % 12);
368
380
  return createComponent(Show, {
369
381
  get when() {
370
- return virtualDimensions().size > 0;
382
+ return verticalViewPort().isVisible(virtualDimensions());
371
383
  },
372
384
  get children() {
373
- const _el$2 = _tmpl$$6.cloneNode(true);
385
+ const _el$2 = _tmpl$$7.cloneNode(true);
374
386
  _el$2.addEventListener("mouseleave", () => {
375
387
  if (isMouseDown()) {
376
388
  context.onNoteUp(context.selectedTrackIndex, key().number);
@@ -390,16 +402,16 @@ const PianoRollKeys = () => {
390
402
  };
391
403
  effect(_p$ => {
392
404
  const _v$3 = {
393
- [styles$4["Key"]]: true,
394
- [styles$4["black"]]: key().isBlack,
395
- [styles$4["white"]]: !key().isBlack,
396
- [styles$4["down"]]: isDown()
405
+ [styles$5["Key"]]: true,
406
+ [styles$5["black"]]: key().isBlack,
407
+ [styles$5["white"]]: !key().isBlack,
408
+ [styles$5["down"]]: isDown()
397
409
  },
398
410
  _v$4 = key().name,
399
411
  _v$5 = key().number % 12,
400
412
  _v$6 = `${virtualDimensions().offset - virtualDimensions().size * (!key().isBlack ? nextIsBlack ? 1 / 2 : 0 : 0)}px`,
401
413
  _v$7 = `${virtualDimensions().size + (!key().isBlack && nextIsBlack ? virtualDimensions().size / 2 : 0) + (!key().isBlack && previousIsBlack ? virtualDimensions().size / 2 : 0)}px`,
402
- _v$8 = [`0px 0px ${Math.min(virtualDimensions().size / 20, 1)}px ${Math.min(virtualDimensions().size / 50, 1)}px rgba(0, 0, 0, 0.5) ${key().isBlack ? "" : "inset"}`, isDown() && `0px 0px ${Math.min(virtualDimensions().size / 8, 2)}px ${Math.min(virtualDimensions().size / 20, 2)}px rgba(0, 0, 0, 0.5) inset`].filter(item => !!item).join(", ");
414
+ _v$8 = `0px 0px ${Math.min(virtualDimensions().size / 20, 1)}px ${Math.min(virtualDimensions().size / 50, 1)}px rgba(0, 0, 0, 0.5) ${key().isBlack ? "" : "inset"}` + isDown() ? `0px 0px ${Math.min(virtualDimensions().size / 8, 2)}px ${Math.min(virtualDimensions().size / 20, 2)}px rgba(0, 0, 0, 0.5) inset` : "";
403
415
  _p$._v$3 = classList(_el$2, _v$3, _p$._v$3);
404
416
  _v$4 !== _p$._v$4 && setAttribute(_el$2, "title", _p$._v$4 = _v$4);
405
417
  _v$5 !== _p$._v$5 && setAttribute(_el$2, "data-index", _p$._v$5 = _v$5);
@@ -423,7 +435,7 @@ const PianoRollKeys = () => {
423
435
  }
424
436
  }));
425
437
  effect(_p$ => {
426
- const _v$ = styles$4.PianoRollKeys,
438
+ const _v$ = styles$5.PianoRollKeys,
427
439
  _v$2 = `${horizontalViewPort().pixelSize}px`;
428
440
  _v$ !== _p$._v$ && className(_el$, _p$._v$ = _v$);
429
441
  _v$2 !== _p$._v$2 && _el$.style.setProperty("width", _p$._v$2 = _v$2);
@@ -446,11 +458,11 @@ const keys = Array.from({
446
458
  }));
447
459
  delegateEvents(["mousedown", "mouseup"]);
448
460
 
449
- var css_248z$2 = ".PianoRollNotes-module_PianoRollNotes__6pF-y {\n position: absolute;\n flex: 1;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 1;\n cursor: grab;\n}\n.PianoRollNotes-module_PianoRollNotes__6pF-y .PianoRollNotes-module_Note__-jxLb {\n position: absolute;\n box-sizing: border-box;\n border-width: 0.5px;\n border-style: solid;\n border-color: #a00;\n cursor: move;\n}\n.PianoRollNotes-module_PianoRollNotes__6pF-y .PianoRollNotes-module_Note__-jxLb.PianoRollNotes-module_trimStart__vuBlj {\n cursor: w-resize;\n}\n.PianoRollNotes-module_PianoRollNotes__6pF-y .PianoRollNotes-module_Note__-jxLb.PianoRollNotes-module_trimEnd__zPdjr {\n cursor: e-resize;\n}";
450
- var styles$2 = {"PianoRollNotes":"PianoRollNotes-module_PianoRollNotes__6pF-y","Note":"PianoRollNotes-module_Note__-jxLb","trimStart":"PianoRollNotes-module_trimStart__vuBlj","trimEnd":"PianoRollNotes-module_trimEnd__zPdjr"};
451
- styleInject(css_248z$2);
461
+ var css_248z$3 = ".PianoRollNotes-module_PianoRollNotes__6pF-y {\n position: absolute;\n flex: 1;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 1;\n cursor: grab;\n}\n.PianoRollNotes-module_PianoRollNotes__6pF-y .PianoRollNotes-module_Note__-jxLb {\n position: absolute;\n box-sizing: border-box;\n border-width: 0.5px;\n border-style: solid;\n border-color: #a00;\n cursor: move;\n}\n.PianoRollNotes-module_PianoRollNotes__6pF-y .PianoRollNotes-module_Note__-jxLb.PianoRollNotes-module_trimStart__vuBlj {\n cursor: w-resize;\n}\n.PianoRollNotes-module_PianoRollNotes__6pF-y .PianoRollNotes-module_Note__-jxLb.PianoRollNotes-module_trimEnd__zPdjr {\n cursor: e-resize;\n}";
462
+ var styles$3 = {"PianoRollNotes":"PianoRollNotes-module_PianoRollNotes__6pF-y","Note":"PianoRollNotes-module_Note__-jxLb","trimStart":"PianoRollNotes-module_trimStart__vuBlj","trimEnd":"PianoRollNotes-module_trimEnd__zPdjr"};
463
+ styleInject(css_248z$3);
452
464
 
453
- const _tmpl$$5 = /*#__PURE__*/template(`<div></div>`, 2);
465
+ const _tmpl$$6 = /*#__PURE__*/template(`<div></div>`, 2);
454
466
  const PianoRollNotes = props => {
455
467
  const context = usePianoRollContext();
456
468
  const verticalViewPort = createMemo(() => useViewPortDimension(context.mode === "keys" ? "vertical" : "verticalTracks"));
@@ -474,6 +486,8 @@ const PianoRollNotes = props => {
474
486
  };
475
487
  };
476
488
  const handleMouseMove = mouseMoveEvent => {
489
+ mouseMoveEvent.preventDefault();
490
+ mouseMoveEvent.stopPropagation();
477
491
  const note = getInitialNote();
478
492
  if (!note) return;
479
493
  const {
@@ -514,17 +528,21 @@ const PianoRollNotes = props => {
514
528
  window.removeEventListener("mousemove", handleMouseMove);
515
529
  window.removeEventListener("mouseup", stopDragging);
516
530
  setIsDragging(false);
531
+ setCurrentNoteIndex(-1);
532
+ setCurrentNoteTrackIndex(-1);
517
533
  };
518
534
  const startDragging = () => {
519
535
  window.addEventListener("mousemove", handleMouseMove);
520
536
  window.addEventListener("mouseup", stopDragging);
521
537
  };
522
538
  const getClasses = noteDragMode => {
523
- return noteDragMode ? [styles$2.Note, styles$2[noteDragMode]] : [styles$2.Note];
539
+ return noteDragMode ? [styles$3.Note, styles$3[noteDragMode]] : [styles$3.Note];
524
540
  };
525
541
  return (() => {
526
- const _el$ = _tmpl$$5.cloneNode(true);
542
+ const _el$ = _tmpl$$6.cloneNode(true);
527
543
  _el$.$$mousedown = mouseDownEvent => {
544
+ mouseDownEvent.preventDefault();
545
+ mouseDownEvent.stopPropagation();
528
546
  const {
529
547
  targetTrackIndex,
530
548
  midi,
@@ -571,7 +589,7 @@ const PianoRollNotes = props => {
571
589
  return memo(() => !!verticalViewPort().isVisible(verticalVirtualDimensions()))() && horizontalViewPort().isVisible(horizontalDimensions());
572
590
  },
573
591
  get children() {
574
- const _el$2 = _tmpl$$5.cloneNode(true);
592
+ const _el$2 = _tmpl$$6.cloneNode(true);
575
593
  _el$2.$$mousedown = event => {
576
594
  event.stopPropagation();
577
595
  const initialPosition = horizontalViewPort().calculatePosition(event.clientX);
@@ -627,21 +645,19 @@ const PianoRollNotes = props => {
627
645
  }
628
646
  }));
629
647
  effect(_$p => classList(_el$, {
630
- [styles$2.PianoRollNotes]: true
648
+ [styles$3.PianoRollNotes]: true
631
649
  }, _$p));
632
650
  return _el$;
633
651
  })();
634
652
  };
635
653
  delegateEvents(["mousedown", "mousemove", "dblclick"]);
636
654
 
637
- var css_248z$1 = ".PianoRollGrid-module_PianoRollGrid__tG119 {\n position: relative;\n width: 100%;\n height: 100%;\n}\n\n.PianoRollGrid-module_PianoRollGrid-Row__nRMCs {\n position: absolute;\n border-style: solid;\n border-color: gray;\n}\n\n.PianoRollGrid-module_PianoRollGrid-Time__jLz3E {\n position: absolute;\n box-sizing: border-box;\n top: 0px;\n height: 100%;\n border-left-style: solid;\n border-left-width: 0.5px;\n}\n";
638
- var styles$1 = {"PianoRollGrid":"PianoRollGrid-module_PianoRollGrid__tG119","PianoRollGrid-Row":"PianoRollGrid-module_PianoRollGrid-Row__nRMCs","PianoRollGrid-Time":"PianoRollGrid-module_PianoRollGrid-Time__jLz3E"};
639
- styleInject(css_248z$1);
655
+ var css_248z$2 = ".PianoRollGrid-module_PianoRollGrid__tG119 {\n position: relative;\n width: 100%;\n height: 100%;\n}\n\n.PianoRollGrid-module_PianoRollGrid-Row__nRMCs {\n position: absolute;\n border-style: solid;\n border-color: gray;\n width: 100%;\n border-width: 0;\n}\n.PianoRollGrid-module_PianoRollGrid-Row__nRMCs.PianoRollGrid-module_IsDark__jRyyy {\n background-color: rgba(0, 0, 0, 0.2);\n}\n\n.PianoRollGrid-module_PianoRollGrid-Row__nRMCs.PianoRollGrid-module_Key__8ZwPN {\n border-width: 0px 1px 0px 0;\n}\n.PianoRollGrid-module_PianoRollGrid-Row__nRMCs.PianoRollGrid-module_IsBlackAndNextIsWhite__UF8O2 {\n background-color: rgba(0, 0, 0, 0.2);\n border-width: 0.1px 1px 0.1px 0;\n}\n\n.PianoRollGrid-module_PianoRollGrid-Time__jLz3E {\n position: absolute;\n box-sizing: border-box;\n top: 0px;\n height: 100%;\n border-left-style: solid;\n border-left-width: 0.5px;\n border-left-color: #bbb;\n background: #ccc;\n}\n\n.PianoRollGrid-module_PianoRollGrid-Time__jLz3E.PianoRollGrid-module_Highlighted__N1J6q {\n background: #ddd;\n}\n\n.PianoRollGrid-module_PianoRollGrid-Time__jLz3E.PianoRollGrid-module_HighlightedBorder__Vnrff {\n border-left-color: gray;\n}\n";
656
+ var styles$2 = {"PianoRollGrid":"PianoRollGrid-module_PianoRollGrid__tG119","PianoRollGrid-Row":"PianoRollGrid-module_PianoRollGrid-Row__nRMCs","IsDark":"PianoRollGrid-module_IsDark__jRyyy","Key":"PianoRollGrid-module_Key__8ZwPN","IsBlackAndNextIsWhite":"PianoRollGrid-module_IsBlackAndNextIsWhite__UF8O2","PianoRollGrid-Time":"PianoRollGrid-module_PianoRollGrid-Time__jLz3E","Highlighted":"PianoRollGrid-module_Highlighted__N1J6q","HighlightedBorder":"PianoRollGrid-module_HighlightedBorder__Vnrff"};
657
+ styleInject(css_248z$2);
640
658
 
641
- const _tmpl$$4 = /*#__PURE__*/template(`<div></div>`, 2);
642
- const PianoRollGrid = () => {
659
+ const usePianoRollGrid = () => {
643
660
  const context = usePianoRollContext();
644
- const verticalViewPort = createMemo(() => useViewPortDimension(context.mode === "keys" ? "vertical" : "verticalTracks"));
645
661
  const horizontalViewPort = createMemo(() => useViewPortDimension("horizontal"));
646
662
  const measureTicks = createMemo(() => context.ppq * 4);
647
663
  const selectedGridDivisorTicks = createMemo(() => measureTicks() / context.gridDivision);
@@ -662,43 +678,62 @@ const PianoRollGrid = () => {
662
678
  const startIndex = Math.floor(context.position / gridDivisorTicks());
663
679
  return Array.from({
664
680
  length: numberOfLines
665
- }).map((_, index) => ({
666
- index: index + startIndex,
667
- ticks: (index + startIndex) * gridDivisorTicks()
668
- }));
681
+ }).map((_, i) => {
682
+ const index = i + startIndex;
683
+ const ticks = index * gridDivisorTicks();
684
+ const measurePosition = ticks / context.ppq / 4 + 1;
685
+ const bars = Math.floor(measurePosition);
686
+ const beats = Math.floor((measurePosition - bars) * 4);
687
+ const label = `${bars}${beats ? `.${beats}` : ""}`;
688
+ return {
689
+ index,
690
+ ticks,
691
+ isHighlighted: Math.ceil((index + 1) * selectedGridDivisorTicks() / measureTicks()) % 2 === 0,
692
+ hasHighlightedBorder: index * gridDivisorTicks() % selectedGridDivisorTicks() === 0,
693
+ showLabel: index * selectedGridDivisorTicks() / measureTicks() % 2 === 0,
694
+ virtualDimensions: horizontalViewPort().calculatePixelDimensions(ticks, gridDivisorTicks()),
695
+ label
696
+ };
697
+ });
669
698
  });
699
+ return gridArray;
700
+ };
701
+
702
+ const _tmpl$$5 = /*#__PURE__*/template(`<div></div>`, 2);
703
+ const PianoRollGrid = () => {
704
+ const context = usePianoRollContext();
705
+ const verticalViewPort = createMemo(() => useViewPortDimension(context.mode === "keys" ? "vertical" : "verticalTracks"));
706
+ const horizontalViewPort = createMemo(() => useViewPortDimension("horizontal"));
707
+ const gridArray = usePianoRollGrid();
670
708
  return (() => {
671
- const _el$ = _tmpl$$4.cloneNode(true);
709
+ const _el$ = _tmpl$$5.cloneNode(true);
672
710
  insert(_el$, createComponent(Index, {
673
711
  get each() {
674
712
  return gridArray();
675
713
  },
676
714
  children: entry => {
677
- const virtualDimensions = createMemo(() => horizontalViewPort().calculatePixelDimensions(entry().ticks, gridDivisorTicks()));
678
715
  return createComponent(Show, {
679
716
  get when() {
680
- return virtualDimensions().size > 0;
717
+ return horizontalViewPort().isVisible(entry().virtualDimensions);
681
718
  },
682
719
  get children() {
683
- const _el$2 = _tmpl$$4.cloneNode(true);
720
+ const _el$2 = _tmpl$$5.cloneNode(true);
684
721
  effect(_p$ => {
685
- const _v$ = styles$1["PianoRollGrid-Time"],
686
- _v$2 = Math.ceil((entry().index + 1 * selectedGridDivisorTicks()) / measureTicks()) % 2 === 0 ? "#ddd" : "#ccc",
687
- _v$3 = `${virtualDimensions().offset}px`,
688
- _v$4 = `${virtualDimensions().size}px`,
689
- _v$5 = entry().index * gridDivisorTicks() % selectedGridDivisorTicks() === 0 ? "gray" : "#bbb";
690
- _v$ !== _p$._v$ && className(_el$2, _p$._v$ = _v$);
691
- _v$2 !== _p$._v$2 && _el$2.style.setProperty("background", _p$._v$2 = _v$2);
692
- _v$3 !== _p$._v$3 && _el$2.style.setProperty("left", _p$._v$3 = _v$3);
693
- _v$4 !== _p$._v$4 && _el$2.style.setProperty("width", _p$._v$4 = _v$4);
694
- _v$5 !== _p$._v$5 && _el$2.style.setProperty("border-left-color", _p$._v$5 = _v$5);
722
+ const _v$ = {
723
+ [styles$2["PianoRollGrid-Time"]]: true,
724
+ [styles$2["Highlighted"]]: entry().isHighlighted,
725
+ [styles$2["HighlightedBorder"]]: entry().hasHighlightedBorder
726
+ },
727
+ _v$2 = `${entry().virtualDimensions.offset}px`,
728
+ _v$3 = `${entry().virtualDimensions.size}px`;
729
+ _p$._v$ = classList(_el$2, _v$, _p$._v$);
730
+ _v$2 !== _p$._v$2 && _el$2.style.setProperty("left", _p$._v$2 = _v$2);
731
+ _v$3 !== _p$._v$3 && _el$2.style.setProperty("width", _p$._v$3 = _v$3);
695
732
  return _p$;
696
733
  }, {
697
734
  _v$: undefined,
698
735
  _v$2: undefined,
699
- _v$3: undefined,
700
- _v$4: undefined,
701
- _v$5: undefined
736
+ _v$3: undefined
702
737
  });
703
738
  return _el$2;
704
739
  }
@@ -716,29 +751,27 @@ const PianoRollGrid = () => {
716
751
  const virtualDimensions = createMemo(() => verticalViewPort().calculatePixelDimensions(127 - key().number, 1));
717
752
  return createComponent(Show, {
718
753
  get when() {
719
- return virtualDimensions().size > 0;
754
+ return verticalViewPort().isVisible(virtualDimensions());
720
755
  },
721
756
  get children() {
722
- const _el$3 = _tmpl$$4.cloneNode(true);
723
- _el$3.style.setProperty("width", "100%");
757
+ const _el$3 = _tmpl$$5.cloneNode(true);
724
758
  effect(_p$ => {
725
- const _v$6 = styles$1["PianoRollGrid-Row"],
726
- _v$7 = `${virtualDimensions().offset}px`,
727
- _v$8 = `${virtualDimensions().size}px`,
728
- _v$9 = key().isBlack ? "rgba(0,0,0,0.2)" : "none",
729
- _v$10 = `${!key().isBlack && !blackKeys.includes((key().number + 1) % 12) ? "0.1px" : 0} 1px ${!key().isBlack && !blackKeys.includes((key().number - 1) % 12) ? "0.1px" : 0} 0`;
730
- _v$6 !== _p$._v$6 && className(_el$3, _p$._v$6 = _v$6);
731
- _v$7 !== _p$._v$7 && _el$3.style.setProperty("top", _p$._v$7 = _v$7);
732
- _v$8 !== _p$._v$8 && _el$3.style.setProperty("height", _p$._v$8 = _v$8);
733
- _v$9 !== _p$._v$9 && _el$3.style.setProperty("background-color", _p$._v$9 = _v$9);
734
- _v$10 !== _p$._v$10 && _el$3.style.setProperty("border-width", _p$._v$10 = _v$10);
759
+ const _v$4 = {
760
+ [styles$2["PianoRollGrid-Row"]]: true,
761
+ [styles$2["Key"]]: true,
762
+ [styles$2["IsDark"]]: key().isBlack,
763
+ [styles$2["IsBlackAndNextIsWhite"]]: !key().isBlack && !blackKeys.includes((key().number + 1) % 12)
764
+ },
765
+ _v$5 = `${virtualDimensions().offset}px`,
766
+ _v$6 = `${virtualDimensions().size}px`;
767
+ _p$._v$4 = classList(_el$3, _v$4, _p$._v$4);
768
+ _v$5 !== _p$._v$5 && _el$3.style.setProperty("top", _p$._v$5 = _v$5);
769
+ _v$6 !== _p$._v$6 && _el$3.style.setProperty("height", _p$._v$6 = _v$6);
735
770
  return _p$;
736
771
  }, {
737
- _v$6: undefined,
738
- _v$7: undefined,
739
- _v$8: undefined,
740
- _v$9: undefined,
741
- _v$10: undefined
772
+ _v$4: undefined,
773
+ _v$5: undefined,
774
+ _v$6: undefined
742
775
  });
743
776
  return _el$3;
744
777
  }
@@ -760,27 +793,25 @@ const PianoRollGrid = () => {
760
793
  const virtualDimensions = createMemo(() => verticalViewPort().calculatePixelDimensions(index(), 1));
761
794
  return createComponent(Show, {
762
795
  get when() {
763
- return virtualDimensions().size > 0;
796
+ return verticalViewPort().isVisible(virtualDimensions());
764
797
  },
765
798
  get children() {
766
- const _el$4 = _tmpl$$4.cloneNode(true);
767
- _el$4.style.setProperty("width", "100%");
768
- _el$4.style.setProperty("border-width", "0");
799
+ const _el$4 = _tmpl$$5.cloneNode(true);
769
800
  effect(_p$ => {
770
- const _v$11 = styles$1["PianoRollGrid-Row"],
771
- _v$12 = `${virtualDimensions().offset}px`,
772
- _v$13 = `${virtualDimensions().size}px`,
773
- _v$14 = index() % 2 === 0 ? "rgba(0,0,0,0.2)" : "none";
774
- _v$11 !== _p$._v$11 && className(_el$4, _p$._v$11 = _v$11);
775
- _v$12 !== _p$._v$12 && _el$4.style.setProperty("top", _p$._v$12 = _v$12);
776
- _v$13 !== _p$._v$13 && _el$4.style.setProperty("height", _p$._v$13 = _v$13);
777
- _v$14 !== _p$._v$14 && _el$4.style.setProperty("background-color", _p$._v$14 = _v$14);
801
+ const _v$7 = {
802
+ [styles$2["PianoRollGrid-Row"]]: true,
803
+ [styles$2["IsDark"]]: index() % 2 === 0
804
+ },
805
+ _v$8 = `${virtualDimensions().offset}px`,
806
+ _v$9 = `${virtualDimensions().size}px`;
807
+ _p$._v$7 = classList(_el$4, _v$7, _p$._v$7);
808
+ _v$8 !== _p$._v$8 && _el$4.style.setProperty("top", _p$._v$8 = _v$8);
809
+ _v$9 !== _p$._v$9 && _el$4.style.setProperty("height", _p$._v$9 = _v$9);
778
810
  return _p$;
779
811
  }, {
780
- _v$11: undefined,
781
- _v$12: undefined,
782
- _v$13: undefined,
783
- _v$14: undefined
812
+ _v$7: undefined,
813
+ _v$8: undefined,
814
+ _v$9: undefined
784
815
  });
785
816
  return _el$4;
786
817
  }
@@ -789,47 +820,19 @@ const PianoRollGrid = () => {
789
820
  });
790
821
  }
791
822
  }), null);
792
- effect(() => className(_el$, styles$1.PianoRollGrid));
823
+ effect(() => className(_el$, styles$2.PianoRollGrid));
793
824
  return _el$;
794
825
  })();
795
826
  };
796
827
 
797
- const defaultRect = {
798
- left: 0,
799
- width: 0,
800
- top: 0,
801
- height: 0,
802
- bottom: 0,
803
- right: 0,
804
- x: 0,
805
- y: 0
806
- };
807
- function useBoundingClientRect(containerRef) {
808
- const [boundingClientRect, setBoundingClientRect] = createSignal(defaultRect);
809
- createEffect(() => {
810
- const container = containerRef();
811
- if (!container) return;
812
- const updateBoundingClientRect = () => {
813
- setBoundingClientRect(container.getBoundingClientRect() ?? defaultRect);
814
- };
815
- const resizeObserver = new ResizeObserver(updateBoundingClientRect);
816
- resizeObserver.observe(container);
817
- updateBoundingClientRect();
818
- return () => {
819
- resizeObserver.disconnect();
820
- };
821
- });
822
- return boundingClientRect;
823
- }
824
-
825
- const _tmpl$$3 = /*#__PURE__*/template(`<input step="0.01">`, 1);
828
+ const _tmpl$$4 = /*#__PURE__*/template(`<input step="0.01">`, 1);
826
829
  const ZoomSliderControl = props => {
827
830
  const propsWithDefaults = mergeProps({
828
831
  orientation: "horizontal"
829
832
  }, props);
830
833
  const dimension = createMemo(() => useViewPortDimension(props.dimensionName ?? propsWithDefaults.orientation));
831
834
  return (() => {
832
- const _el$ = _tmpl$$3.cloneNode(true);
835
+ const _el$ = _tmpl$$4.cloneNode(true);
833
836
  spread(_el$, mergeProps$1({
834
837
  get min() {
835
838
  return dimension().minZoom;
@@ -841,7 +844,10 @@ const ZoomSliderControl = props => {
841
844
  get value() {
842
845
  return dimension().zoom;
843
846
  },
844
- "onInput": event => dimension().onZoomChange?.(event.currentTarget.valueAsNumber),
847
+ "onInput": event => {
848
+ const value = event.currentTarget.valueAsNumber;
849
+ dimension().onZoomChange?.(value);
850
+ },
845
851
  "type": "range"
846
852
  }, () => ({
847
853
  orient: propsWithDefaults.orientation
@@ -871,17 +877,17 @@ const ZoomSliderControl = props => {
871
877
  })();
872
878
  };
873
879
 
874
- var css_248z = ".PianoRollTrackList-module_PianoRollTrackList__-sDf0 {\n position: relative;\n height: 100%;\n flex: 1;\n}\n\n.PianoRollTrackList-module_Track__mZP1K {\n border-width: 0px;\n position: absolute;\n box-sizing: border-box;\n width: 100%;\n border-color: #000;\n border-style: solid;\n border-right-width: 1px;\n border-bottom-width: 1px;\n cursor: \"pointer\";\n background: \"lightgrey\";\n}\n.PianoRollTrackList-module_Track__mZP1K.PianoRollTrackList-module_selected__0b-mf {\n background: \"gray\";\n}";
875
- var styles = {"PianoRollTrackList":"PianoRollTrackList-module_PianoRollTrackList__-sDf0","Track":"PianoRollTrackList-module_Track__mZP1K","selected":"PianoRollTrackList-module_selected__0b-mf"};
876
- styleInject(css_248z);
880
+ var css_248z$1 = ".PianoRollTrackList-module_PianoRollTrackList__-sDf0 {\n position: relative;\n height: 100%;\n flex: 1;\n}\n\n.PianoRollTrackList-module_Track__mZP1K {\n border-width: 0px;\n position: absolute;\n box-sizing: border-box;\n width: 100%;\n border-color: #000;\n border-style: solid;\n border-right-width: 1px;\n border-bottom-width: 1px;\n padding: 2px;\n cursor: pointer;\n background: lightgrey;\n}\n.PianoRollTrackList-module_Track__mZP1K.PianoRollTrackList-module_selected__0b-mf {\n background: gray;\n}";
881
+ var styles$1 = {"PianoRollTrackList":"PianoRollTrackList-module_PianoRollTrackList__-sDf0","Track":"PianoRollTrackList-module_Track__mZP1K","selected":"PianoRollTrackList-module_selected__0b-mf"};
882
+ styleInject(css_248z$1);
877
883
 
878
- const _tmpl$$2 = /*#__PURE__*/template(`<div></div>`, 2),
884
+ const _tmpl$$3 = /*#__PURE__*/template(`<div></div>`, 2),
879
885
  _tmpl$2$1 = /*#__PURE__*/template(`<div> </div>`, 2);
880
886
  const PianoRollTrackList = () => {
881
887
  const viewPort = createMemo(() => useViewPortDimension("verticalTracks"));
882
888
  const context = usePianoRollContext();
883
889
  return (() => {
884
- const _el$ = _tmpl$$2.cloneNode(true);
890
+ const _el$ = _tmpl$$3.cloneNode(true);
885
891
  insert(_el$, createComponent(Index, {
886
892
  get each() {
887
893
  return context.tracks;
@@ -900,8 +906,8 @@ const PianoRollTrackList = () => {
900
906
  insert(_el$2, () => track().name || "[unnamed track]", null);
901
907
  effect(_p$ => {
902
908
  const _v$ = {
903
- [styles["Track"]]: true,
904
- [styles["selected"]]: index === context.selectedTrackIndex
909
+ [styles$1["Track"]]: true,
910
+ [styles$1["selected"]]: index === context.selectedTrackIndex
905
911
  },
906
912
  _v$2 = track().name,
907
913
  _v$3 = `${virtualDimensions().offset}px`,
@@ -922,80 +928,214 @@ const PianoRollTrackList = () => {
922
928
  });
923
929
  }
924
930
  }));
925
- effect(() => className(_el$, styles.PianoRollTrackList));
931
+ effect(() => className(_el$, styles$1.PianoRollTrackList));
926
932
  return _el$;
927
933
  })();
928
934
  };
929
935
  delegateEvents(["click"]);
930
936
 
931
- const _tmpl$$1 = /*#__PURE__*/template(`<div><div></div></div>`, 4),
932
- _tmpl$2 = /*#__PURE__*/template(`<div></div>`, 2);
937
+ const PianoRollScrollZoomViewPort = props => {
938
+ const zoomFactor = 500;
939
+ const context = usePianoRollContext();
940
+ return createComponent(ScrollZoomViewPort, {
941
+ dimensions: {
942
+ horizontal: () => ({
943
+ pixelOffset: context.notesScrollerClientRect.left,
944
+ pixelSize: context.notesScrollerClientRect.width,
945
+ position: context.position,
946
+ range: context.duration,
947
+ zoom: context.zoom * (zoomFactor / context.notesScrollerClientRect.width),
948
+ onPositionChange: context.onPositionChange,
949
+ onZoomChange: zoom => context.onZoomChange?.(zoom / (zoomFactor / context.notesScrollerClientRect.width)),
950
+ minZoom: 1,
951
+ maxZoom: 500
952
+ }),
953
+ vertical: () => ({
954
+ pixelOffset: context.notesScrollerClientRect.top,
955
+ pixelSize: context.notesScrollerClientRect.height,
956
+ position: context.verticalPosition,
957
+ range: 128,
958
+ zoom: context.verticalZoom * (zoomFactor / context.notesScrollerClientRect.height),
959
+ onPositionChange: context.onVerticalPositionChange,
960
+ onZoomChange: verticalZoom => context.onVerticalZoomChange?.(verticalZoom / (zoomFactor / context.notesScrollerClientRect.height)),
961
+ minZoom: 1,
962
+ maxZoom: 10
963
+ }),
964
+ horizontalTracks: () => ({
965
+ pixelOffset: 0,
966
+ pixelSize: context.tracksScrollerClientRect.width
967
+ }),
968
+ verticalTracks: () => ({
969
+ pixelOffset: context.tracksScrollerClientRect.top,
970
+ pixelSize: context.tracksScrollerClientRect.height,
971
+ position: context.verticalTrackPosition,
972
+ range: context.tracks.length,
973
+ zoom: context.verticalTrackZoom * (zoomFactor / context.tracksScrollerClientRect.height),
974
+ onPositionChange: context.onVerticalTrackPositionChange,
975
+ onZoomChange: verticalTrackZoom => context.onVerticalTrackZoomChange?.(verticalTrackZoom / (zoomFactor / context.tracksScrollerClientRect.height)),
976
+ minZoom: 0.8,
977
+ maxZoom: 3
978
+ }),
979
+ horizontalKeys: () => ({
980
+ pixelSize: 60
981
+ })
982
+ },
983
+ get children() {
984
+ return props.children;
985
+ }
986
+ });
987
+ };
988
+
989
+ const defaultRect = {
990
+ left: 0,
991
+ width: 0,
992
+ top: 0,
993
+ height: 0,
994
+ bottom: 0,
995
+ right: 0,
996
+ x: 0,
997
+ y: 0
998
+ };
999
+ function useBoundingClientRect(containerRef) {
1000
+ const [boundingClientRect, setBoundingClientRect] = createSignal(defaultRect);
1001
+ createEffect(() => {
1002
+ const container = containerRef();
1003
+ if (!container) return;
1004
+ const updateBoundingClientRect = () => {
1005
+ setBoundingClientRect(container.getBoundingClientRect() ?? defaultRect);
1006
+ };
1007
+ const resizeObserver = new ResizeObserver(updateBoundingClientRect);
1008
+ resizeObserver.observe(container);
1009
+ updateBoundingClientRect();
1010
+ return () => {
1011
+ resizeObserver.disconnect();
1012
+ };
1013
+ });
1014
+ return boundingClientRect;
1015
+ }
1016
+
1017
+ const PianoRollNotesScroller = props => {
1018
+ const context = usePianoRollContext();
1019
+ const [ref, setRef] = createSignal();
1020
+ const clientRect = useBoundingClientRect(ref);
1021
+ createEffect(() => {
1022
+ context.onNotesScrollerClientRectChange(clientRect());
1023
+ });
1024
+ return createComponent(ScrollZoomContainer, {
1025
+ ref: setRef,
1026
+ get verticalDimensionName() {
1027
+ return context.mode === "keys" ? "vertical" : "verticalTracks";
1028
+ },
1029
+ get children() {
1030
+ return props.children;
1031
+ }
1032
+ });
1033
+ };
1034
+
1035
+ const PianoRollTrackListScroller = props => {
1036
+ const context = usePianoRollContext();
1037
+ const [ref, setRef] = createSignal();
1038
+ const clientRect = useBoundingClientRect(ref);
1039
+ createEffect(() => {
1040
+ context.onTracksScrollerClientRectChange(clientRect());
1041
+ });
1042
+ return createComponent(ScrollZoomContainer, {
1043
+ ref: setRef,
1044
+ horizontalDimensionName: "horizontalTracks",
1045
+ verticalDimensionName: "verticalTracks",
1046
+ get showScrollbar() {
1047
+ return context.mode === "keys";
1048
+ },
1049
+ get children() {
1050
+ return props.children;
1051
+ }
1052
+ });
1053
+ };
1054
+
1055
+ var css_248z = ".PianoRollScale-module_PianoRollScale__5wGRm {\n position: relative;\n width: 100%;\n height: 100%;\n}\n\n.PianoRollScale-module_PianoRollScale-Time__03hGQ {\n position: absolute;\n box-sizing: border-box;\n top: 0px;\n height: 100%;\n border-left-style: solid;\n border-left-width: 0.5px;\n border-left-color: x#666;\n border-bottom-color: #333;\n border-bottom-style: solid;\n border-bottom-width: 0.5px;\n background: #777;\n display: flex;\n align-items: center;\n}\n\n.PianoRollScale-module_PianoRollScale-Label__aoRi6 {\n position: absolute;\n z-index: 1;\n color: #ccc;\n margin-left: 3px;\n font-size: 0.8em;\n}\n\n.PianoRollScale-module_PianoRollScale-Time__03hGQ.PianoRollScale-module_Highlighted__ziWn5 {\n background: #666;\n}\n\n.PianoRollScale-module_PianoRollScale-Time__03hGQ.PianoRollScale-module_HighlightedBorder__-OoZE {\n border-left-color: #111;\n}\n";
1056
+ var styles = {"PianoRollScale":"PianoRollScale-module_PianoRollScale__5wGRm","PianoRollScale-Time":"PianoRollScale-module_PianoRollScale-Time__03hGQ","PianoRollScale-Label":"PianoRollScale-module_PianoRollScale-Label__aoRi6","Highlighted":"PianoRollScale-module_Highlighted__ziWn5","HighlightedBorder":"PianoRollScale-module_HighlightedBorder__-OoZE"};
1057
+ styleInject(css_248z);
1058
+
1059
+ const _tmpl$$2 = /*#__PURE__*/template(`<div></div>`, 2);
1060
+ const PianoRollScale = () => {
1061
+ const horizontalViewPort = createMemo(() => useViewPortDimension("horizontal"));
1062
+ const grid = usePianoRollGrid();
1063
+ return (() => {
1064
+ const _el$ = _tmpl$$2.cloneNode(true);
1065
+ insert(_el$, createComponent(Index, {
1066
+ get each() {
1067
+ return grid();
1068
+ },
1069
+ children: entry => {
1070
+ return createComponent(Show, {
1071
+ get when() {
1072
+ return horizontalViewPort().isVisible(entry().virtualDimensions);
1073
+ },
1074
+ get children() {
1075
+ const _el$2 = _tmpl$$2.cloneNode(true);
1076
+ insert(_el$2, createComponent(Show, {
1077
+ get when() {
1078
+ return entry().showLabel;
1079
+ },
1080
+ get children() {
1081
+ const _el$3 = _tmpl$$2.cloneNode(true);
1082
+ insert(_el$3, () => entry().label);
1083
+ effect(() => className(_el$3, styles["PianoRollScale-Label"]));
1084
+ return _el$3;
1085
+ }
1086
+ }));
1087
+ effect(_p$ => {
1088
+ const _v$ = {
1089
+ [styles["PianoRollScale-Time"]]: true,
1090
+ [styles["Highlighted"]]: entry().isHighlighted,
1091
+ [styles["HighlightedBorder"]]: entry().hasHighlightedBorder
1092
+ },
1093
+ _v$2 = `${entry().virtualDimensions.offset}px`,
1094
+ _v$3 = `${entry().virtualDimensions.size}px`;
1095
+ _p$._v$ = classList(_el$2, _v$, _p$._v$);
1096
+ _v$2 !== _p$._v$2 && _el$2.style.setProperty("left", _p$._v$2 = _v$2);
1097
+ _v$3 !== _p$._v$3 && _el$2.style.setProperty("width", _p$._v$3 = _v$3);
1098
+ return _p$;
1099
+ }, {
1100
+ _v$: undefined,
1101
+ _v$2: undefined,
1102
+ _v$3: undefined
1103
+ });
1104
+ return _el$2;
1105
+ }
1106
+ });
1107
+ }
1108
+ }));
1109
+ effect(() => className(_el$, styles.PianoRollScale));
1110
+ return _el$;
1111
+ })();
1112
+ };
1113
+
1114
+ 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);
933
1117
  const PianoRoll = allProps => {
934
1118
  const propsWithDefaults = mergeProps({
935
1119
  showAllTracks: false
936
1120
  }, allProps);
937
1121
  const [context, divProps] = splitContextProps(propsWithDefaults);
938
- const [notesScrollerRef, setNotesScrollerRef] = createSignal();
939
- const [tracksScrollerRef, setTracksScrollerRef] = createSignal();
940
- const notesScrollerClientRect = useBoundingClientRect(notesScrollerRef);
941
- const tracksScrollerClientRect = useBoundingClientRect(tracksScrollerRef);
942
- const zoomFactor = 500;
943
1122
  return createComponent(PianoRollContextProvider, {
944
1123
  value: context,
945
1124
  get children() {
946
- const _el$ = _tmpl$2.cloneNode(true);
1125
+ const _el$ = _tmpl$3.cloneNode(true);
947
1126
  spread(_el$, mergeProps$1(divProps, {
948
1127
  get ["class"]() {
949
- return styles$5.PianoRoll;
1128
+ return styles$6.PianoRoll;
950
1129
  }
951
1130
  }), false, true);
952
- insert(_el$, createComponent(ScrollZoomViewPort, {
953
- dimensions: {
954
- horizontal: () => ({
955
- pixelOffset: notesScrollerClientRect().left,
956
- pixelSize: notesScrollerClientRect().width,
957
- position: context.position,
958
- range: context.duration,
959
- zoom: context.zoom * (zoomFactor / notesScrollerClientRect().width),
960
- onPositionChange: context.onPositionChange,
961
- onZoomChange: zoom => context.onZoomChange?.(zoom / (zoomFactor / notesScrollerClientRect().width)),
962
- minZoom: 1,
963
- maxZoom: 500
964
- }),
965
- vertical: () => ({
966
- pixelOffset: notesScrollerClientRect().top,
967
- pixelSize: notesScrollerClientRect().height,
968
- position: context.verticalPosition,
969
- range: 128,
970
- zoom: context.verticalZoom * (zoomFactor / notesScrollerClientRect().height),
971
- onPositionChange: context.onVerticalPositionChange,
972
- onZoomChange: verticalZoom => context.onVerticalZoomChange?.(verticalZoom / (zoomFactor / notesScrollerClientRect().height)),
973
- minZoom: 1,
974
- maxZoom: 10
975
- }),
976
- horizontalTracks: () => ({
977
- pixelOffset: 0,
978
- pixelSize: tracksScrollerClientRect().width
979
- }),
980
- verticalTracks: () => ({
981
- pixelOffset: tracksScrollerClientRect().top,
982
- pixelSize: tracksScrollerClientRect().height,
983
- position: context.verticalTrackPosition,
984
- range: context.tracks.length,
985
- zoom: context.verticalTrackZoom * (zoomFactor / tracksScrollerClientRect().height),
986
- onPositionChange: context.onVerticalTrackPositionChange,
987
- onZoomChange: verticalTrackZoom => context.onVerticalTrackZoomChange?.(verticalTrackZoom / (zoomFactor / tracksScrollerClientRect().height)),
988
- minZoom: 0.8,
989
- maxZoom: 3
990
- }),
991
- horizontalKeys: () => ({
992
- pixelSize: 60
993
- })
994
- },
1131
+ insert(_el$, createComponent(PianoRollScrollZoomViewPort, {
995
1132
  get children() {
996
1133
  return [(() => {
997
- const _el$2 = _tmpl$$1.cloneNode(true),
998
- _el$3 = _el$2.firstChild;
1134
+ const _el$2 = _tmpl$2.cloneNode(true),
1135
+ _el$3 = _el$2.firstChild,
1136
+ _el$7 = _el$3.firstChild,
1137
+ _el$8 = _el$3.nextSibling,
1138
+ _el$9 = _el$8.firstChild;
999
1139
  insert(_el$2, createComponent(ZoomSliderControl, {
1000
1140
  orientation: "vertical",
1001
1141
  dimensionName: "verticalTracks"
@@ -1005,20 +1145,36 @@ const PianoRoll = allProps => {
1005
1145
  return context.showTrackList;
1006
1146
  },
1007
1147
  get children() {
1008
- return createComponent(ScrollZoomContainer, {
1009
- ref: setTracksScrollerRef,
1010
- horizontalDimensionName: "horizontalTracks",
1011
- verticalDimensionName: "verticalTracks",
1012
- get showScrollbar() {
1013
- return context.mode === "keys";
1014
- },
1148
+ const _el$4 = _tmpl$$1.cloneNode(true),
1149
+ _el$5 = _el$4.firstChild,
1150
+ _el$6 = _el$5.firstChild;
1151
+ _el$4.style.setProperty("height", "30px");
1152
+ _el$5.$$click = () => context.onModeChange(context.mode === "keys" ? "tracks" : "keys");
1153
+ _el$5.style.setProperty("font-size", "16px");
1154
+ _el$5.style.setProperty("line-height", "16px");
1155
+ _el$5.style.setProperty("cursor", "pointer");
1156
+ _el$5.style.setProperty("overflow", "hidden");
1157
+ insert(_el$6, () => context.mode === "keys" ? "≡" : "🎹");
1158
+ effect(() => setAttribute(_el$5, "title", context.mode === "keys" ? "Tracks Mode" : "Keys Mode"));
1159
+ return _el$4;
1160
+ }
1161
+ }), _el$7);
1162
+ _el$7.style.setProperty("flex", "1");
1163
+ _el$7.style.setProperty("display", "flex");
1164
+ _el$7.style.setProperty("overflow", "hidden");
1165
+ insert(_el$7, createComponent(Show, {
1166
+ get when() {
1167
+ return context.showTrackList;
1168
+ },
1169
+ get children() {
1170
+ return createComponent(PianoRollTrackListScroller, {
1015
1171
  get children() {
1016
1172
  return createComponent(PianoRollTrackList, {});
1017
1173
  }
1018
1174
  });
1019
1175
  }
1020
1176
  }), null);
1021
- insert(_el$3, createComponent(Show, {
1177
+ insert(_el$7, createComponent(Show, {
1022
1178
  get when() {
1023
1179
  return context.mode === "keys";
1024
1180
  },
@@ -1026,11 +1182,14 @@ const PianoRoll = allProps => {
1026
1182
  return createComponent(PianoRollKeys, {});
1027
1183
  }
1028
1184
  }), null);
1029
- insert(_el$2, createComponent(ScrollZoomContainer, {
1030
- ref: setNotesScrollerRef,
1031
- get verticalDimensionName() {
1032
- return context.mode === "keys" ? "vertical" : "verticalTracks";
1033
- },
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, {
1034
1193
  get children() {
1035
1194
  return [memo(() => allProps.children), createComponent(PianoRollGrid, {}), createComponent(PianoRollNotes, {})];
1036
1195
  }
@@ -1042,10 +1201,13 @@ const PianoRoll = allProps => {
1042
1201
  }
1043
1202
  }), null);
1044
1203
  effect(_p$ => {
1045
- const _v$ = styles$5.PianoRollContainer,
1046
- _v$2 = styles$5.PianoRollLeftColumn;
1204
+ const _v$ = styles$6.PianoRollContainer,
1205
+ _v$2 = {
1206
+ [styles$6.PianoRollLeftColumn]: true,
1207
+ [styles$6.showTrackList]: context.showTrackList
1208
+ };
1047
1209
  _v$ !== _p$._v$ && className(_el$2, _p$._v$ = _v$);
1048
- _v$2 !== _p$._v$2 && className(_el$3, _p$._v$2 = _v$2);
1210
+ _p$._v$2 = classList(_el$3, _v$2, _p$._v$2);
1049
1211
  return _p$;
1050
1212
  }, {
1051
1213
  _v$: undefined,
@@ -1056,7 +1218,7 @@ const PianoRoll = allProps => {
1056
1218
  orientation: "horizontal",
1057
1219
  get style() {
1058
1220
  return {
1059
- "margin-left": `${tracksScrollerClientRect().width + 24}px`,
1221
+ "margin-left": `${context.tracksScrollerClientRect.width + 24}px`,
1060
1222
  "margin-right": "24px"
1061
1223
  };
1062
1224
  }
@@ -1067,6 +1229,7 @@ const PianoRoll = allProps => {
1067
1229
  }
1068
1230
  });
1069
1231
  };
1232
+ delegateEvents(["click"]);
1070
1233
 
1071
1234
  const _tmpl$ = /*#__PURE__*/template(`<div class="PlayHead"></div>`, 2);
1072
1235
  const PlayHead = allProps => {