solid-pianoroll 0.0.12 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/esm/index.js CHANGED
@@ -40,11 +40,11 @@ const usePianoRollContext = () => {
40
40
  };
41
41
  const splitContextProps = allProps => splitProps(allProps, ["condensed", "duration", "gridDivision", "notes", "position", "ppq", "snapToGrid", "verticalPosition", "verticalZoom", "zoom", "onInsertNote", "onNoteChange", "onPositionChange", "onRemoveNote", "onVerticalPositionChange", "onVerticalZoomChange", "onZoomChange"]);
42
42
 
43
- const _tmpl$$7 = /*#__PURE__*/template(`<input max="500" min="1" step="0.01">`, 1);
43
+ const _tmpl$$8 = /*#__PURE__*/template(`<input max="500" min="1" step="0.01">`, 1);
44
44
  const HorizontalZoomControl = props => {
45
45
  const context = usePianoRollContext();
46
46
  return (() => {
47
- const _el$ = _tmpl$$7.cloneNode(true);
47
+ const _el$ = _tmpl$$8.cloneNode(true);
48
48
  spread(_el$, mergeProps(props, {
49
49
  get value() {
50
50
  return context.zoom;
@@ -66,6 +66,7 @@ const HorizontalZoomControl = props => {
66
66
  function createViewPortDimension(getState) {
67
67
  const getStateWithFunctions = () => ({
68
68
  ...getState(),
69
+ calculatePixelOffset,
69
70
  calculatePixelValue,
70
71
  calculatePosition,
71
72
  calculatePixelDimensions,
@@ -138,7 +139,7 @@ var css_248z$2 = ".PianoRollNotes-module_PianoRollNotes__6pF-y {\n position: ab
138
139
  var styles$2 = {"PianoRollNotes":"PianoRollNotes-module_PianoRollNotes__6pF-y","Note":"PianoRollNotes-module_Note__-jxLb","trimStart":"PianoRollNotes-module_trimStart__vuBlj","trimEnd":"PianoRollNotes-module_trimEnd__zPdjr"};
139
140
  styleInject(css_248z$2);
140
141
 
141
- const _tmpl$$6 = /*#__PURE__*/template(`<div></div>`, 2);
142
+ const _tmpl$$7 = /*#__PURE__*/template(`<div></div>`, 2);
142
143
  const PianoRollNotes = props => {
143
144
  const context = usePianoRollContext();
144
145
  const verticalViewPort = createMemo(() => useViewPortDimension("vertical"));
@@ -175,7 +176,7 @@ const PianoRollNotes = props => {
175
176
  return noteDragMode ? [styles$2.Note, styles$2[noteDragMode]] : [styles$2.Note];
176
177
  };
177
178
  return (() => {
178
- const _el$ = _tmpl$$6.cloneNode(true);
179
+ const _el$ = _tmpl$$7.cloneNode(true);
179
180
  _el$.$$click = event => {
180
181
  if (newNote()) {
181
182
  setNewNoteIndex(-1);
@@ -201,9 +202,11 @@ const PianoRollNotes = props => {
201
202
  const index = insertOrUpdateNote(event);
202
203
  setNewNoteIndex(index);
203
204
  };
204
- _el$.$$mousedown = () => {
205
+ _el$.$$mousedown = event => {
205
206
  console.log("down");
206
207
  setIsMouseDown(true);
208
+ const index = insertOrUpdateNote(event);
209
+ setNewNoteIndex(index);
207
210
  };
208
211
  const _ref$ = props.ref;
209
212
  typeof _ref$ === "function" ? use(_ref$, _el$) : props.ref = _el$;
@@ -219,7 +222,7 @@ const PianoRollNotes = props => {
219
222
  return memo(() => !!(verticalViewPort().isVisible(verticalVirtualDimensions()) || context.condensed))() && horizontalViewPort().isVisible(horizontalDimensions());
220
223
  },
221
224
  get children() {
222
- const _el$2 = _tmpl$$6.cloneNode(true);
225
+ const _el$2 = _tmpl$$7.cloneNode(true);
223
226
  _el$2.$$mousedown = event => {
224
227
  event.stopPropagation();
225
228
  setIsDragging(true);
@@ -295,7 +298,7 @@ const PianoRollNotes = props => {
295
298
  };
296
299
  delegateEvents(["mousedown", "mousemove", "mouseup", "dblclick", "click"]);
297
300
 
298
- const _tmpl$$5 = /*#__PURE__*/template(`<div class="PianoRoll-Scroller"><div><div><div></div></div></div></div>`, 8);
301
+ const _tmpl$$6 = /*#__PURE__*/template(`<div class="PianoRoll-Scroller"><div><div><div></div></div></div></div>`, 8);
299
302
  const ScrollContainer = props => {
300
303
  let scrollContentRef;
301
304
  const verticalViewPort = createMemo(() => useViewPortDimension("vertical"));
@@ -357,7 +360,7 @@ const ScrollContainer = props => {
357
360
  });
358
361
  });
359
362
  return (() => {
360
- const _el$ = _tmpl$$5.cloneNode(true),
363
+ const _el$ = _tmpl$$6.cloneNode(true),
361
364
  _el$2 = _el$.firstChild,
362
365
  _el$3 = _el$2.firstChild,
363
366
  _el$4 = _el$3.firstChild;
@@ -402,11 +405,11 @@ var css_248z$1 = ".PianoRollKeys-module_PianoRollKeys__5vnQ0 {\n position: rela
402
405
  var styles$1 = {"PianoRollKeys":"PianoRollKeys-module_PianoRollKeys__5vnQ0","Key":"PianoRollKeys-module_Key__jybNC","black":"PianoRollKeys-module_black__7rncB","white":"PianoRollKeys-module_white__fR2Lm","whiteAndNextIsWhite":"PianoRollKeys-module_whiteAndNextIsWhite__PN1O8","whiteAndPreviousIsWhite":"PianoRollKeys-module_whiteAndPreviousIsWhite__-fP3q"};
403
406
  styleInject(css_248z$1);
404
407
 
405
- const _tmpl$$4 = /*#__PURE__*/template(`<div></div>`, 2);
408
+ const _tmpl$$5 = /*#__PURE__*/template(`<div></div>`, 2);
406
409
  const PianoRollKeys = () => {
407
410
  const viewPort = createMemo(() => useViewPortDimension("vertical"));
408
411
  return (() => {
409
- const _el$ = _tmpl$$4.cloneNode(true);
412
+ const _el$ = _tmpl$$5.cloneNode(true);
410
413
  insert(_el$, createComponent(Index, {
411
414
  each: keys,
412
415
  children: key => {
@@ -416,7 +419,7 @@ const PianoRollKeys = () => {
416
419
  return virtualDimensions().size > 0;
417
420
  },
418
421
  get children() {
419
- const _el$2 = _tmpl$$4.cloneNode(true);
422
+ const _el$2 = _tmpl$$5.cloneNode(true);
420
423
  effect(_p$ => {
421
424
  const _v$ = {
422
425
  [styles$1["Key"]]: true,
@@ -465,7 +468,7 @@ var css_248z = ".PianoRollGrid-module_PianoRollGrid__tG119 {\n position: relati
465
468
  var styles = {"PianoRollGrid":"PianoRollGrid-module_PianoRollGrid__tG119","PianoRollGrid-Key":"PianoRollGrid-module_PianoRollGrid-Key__VRbiB","PianoRollGrid-Time":"PianoRollGrid-module_PianoRollGrid-Time__jLz3E"};
466
469
  styleInject(css_248z);
467
470
 
468
- const _tmpl$$3 = /*#__PURE__*/template(`<div></div>`, 2);
471
+ const _tmpl$$4 = /*#__PURE__*/template(`<div></div>`, 2);
469
472
  const PianoRollGrid = () => {
470
473
  const context = usePianoRollContext();
471
474
  const verticalViewPort = createMemo(() => useViewPortDimension("vertical"));
@@ -473,10 +476,12 @@ const PianoRollGrid = () => {
473
476
  const measureTicks = createMemo(() => context.ppq * 4);
474
477
  const selectedGridDivisorTicks = createMemo(() => measureTicks() / context.gridDivision);
475
478
  function calculateVisibleGridDivisorTicks(value) {
476
- if (horizontalViewPort().calculateVisibleRange() / value > 100) {
479
+ const visibleRange = horizontalViewPort().calculateVisibleRange();
480
+ if (visibleRange <= 0) return 0;
481
+ if (visibleRange / value > 100) {
477
482
  return calculateVisibleGridDivisorTicks(value * 2);
478
483
  }
479
- if (horizontalViewPort().calculateVisibleRange() / value < 30) {
484
+ if (visibleRange / value < 30) {
480
485
  return calculateVisibleGridDivisorTicks(value / 2);
481
486
  }
482
487
  return value;
@@ -493,7 +498,7 @@ const PianoRollGrid = () => {
493
498
  }));
494
499
  });
495
500
  return (() => {
496
- const _el$ = _tmpl$$3.cloneNode(true);
501
+ const _el$ = _tmpl$$4.cloneNode(true);
497
502
  insert(_el$, createComponent(Index, {
498
503
  get each() {
499
504
  return gridArray();
@@ -505,7 +510,7 @@ const PianoRollGrid = () => {
505
510
  return virtualDimensions().size > 0;
506
511
  },
507
512
  get children() {
508
- const _el$2 = _tmpl$$3.cloneNode(true);
513
+ const _el$2 = _tmpl$$4.cloneNode(true);
509
514
  effect(_p$ => {
510
515
  const _v$ = styles["PianoRollGrid-Time"],
511
516
  _v$2 = Math.ceil((entry().index + 1 * selectedGridDivisorTicks()) / measureTicks()) % 2 === 0 ? "#ddd" : "#ccc",
@@ -544,7 +549,7 @@ const PianoRollGrid = () => {
544
549
  return virtualDimensions().size > 0;
545
550
  },
546
551
  get children() {
547
- const _el$3 = _tmpl$$3.cloneNode(true);
552
+ const _el$3 = _tmpl$$4.cloneNode(true);
548
553
  _el$3.style.setProperty("width", "100%");
549
554
  effect(_p$ => {
550
555
  const _v$6 = styles["PianoRollGrid-Key"],
@@ -629,11 +634,11 @@ function useBoundingClientRect(containerRef) {
629
634
  return boundingClientRect;
630
635
  }
631
636
 
632
- const _tmpl$$2 = /*#__PURE__*/template(`<input min="1" max="11" step="0.01">`, 1);
637
+ const _tmpl$$3 = /*#__PURE__*/template(`<input min="1" max="11" step="0.01">`, 1);
633
638
  const VerticalZoomControl = props => {
634
639
  const context = usePianoRollContext();
635
640
  return (() => {
636
- const _el$ = _tmpl$$2.cloneNode(true);
641
+ const _el$ = _tmpl$$3.cloneNode(true);
637
642
  spread(_el$, mergeProps(props, {
638
643
  get value() {
639
644
  return context.verticalZoom;
@@ -657,15 +662,21 @@ const VerticalZoomControl = props => {
657
662
  })();
658
663
  };
659
664
 
660
- const _tmpl$$1 = /*#__PURE__*/template(`<ul></ul>`, 2),
661
- _tmpl$2 = /*#__PURE__*/template(`<div><ul></ul><div><div></div></div></div>`, 8),
662
- _tmpl$3 = /*#__PURE__*/template(`<li></li>`, 2);
665
+ const _tmpl$$2 = /*#__PURE__*/template(`<div><ul></ul></div>`, 4),
666
+ _tmpl$2 = /*#__PURE__*/template(`<ul></ul>`, 2),
667
+ _tmpl$3 = /*#__PURE__*/template(`<div><div></div></div>`, 4),
668
+ _tmpl$4 = /*#__PURE__*/template(`<div></div>`, 2),
669
+ _tmpl$5 = /*#__PURE__*/template(`<li></li>`, 2);
663
670
  const MultiTrackPianoRoll = allProps => {
664
- const condensed = createMemo(() => !allProps.selectedTrack);
665
- const [ownProps, restProps] = splitProps(allProps, ["tracks", "selectedTrack"]);
671
+ const selectedTrack = createMemo(() => allProps.tracks[allProps.selectedTrackIndex]);
672
+ const condensed = createMemo(() => !selectedTrack());
673
+ const [ownProps, restProps] = splitProps(allProps, ["tracks", "selectedTrackIndex"]);
666
674
  const [contextProps, divProps] = splitContextProps(mergeProps$1(restProps, {
667
675
  notes: [],
668
- condensed: false
676
+ condensed: false,
677
+ onNoteChange: () => undefined,
678
+ onInsertNote: () => -1,
679
+ onRemoveNote: () => undefined
669
680
  }));
670
681
  const [scrollerRef, setScrollerRef] = createSignal();
671
682
  const clientRect = useBoundingClientRect(scrollerRef);
@@ -674,179 +685,201 @@ const MultiTrackPianoRoll = allProps => {
674
685
  const maxZoom = createMemo(() => 500 * (zoomFactor / clientRect().width));
675
686
  const minVerticalZoom = createMemo(() => 1 / (zoomFactor / clientRect().height));
676
687
  const maxVerticalZoom = createMemo(() => 10 * (zoomFactor / clientRect().height));
677
- return createComponent(PianoRollContextProvider, {
678
- get value() {
679
- return {
680
- ...contextProps
681
- };
682
- },
683
- get children() {
684
- return createComponent(ScrollZoomViewPort, {
685
- dimensions: {
686
- horizontal: () => ({
687
- pixelOffset: clientRect().left,
688
- pixelSize: clientRect().width,
689
- position: contextProps.position,
690
- range: contextProps.duration,
691
- zoom: contextProps.zoom * (zoomFactor / clientRect().width),
692
- onPositionChange: contextProps.onPositionChange,
693
- onZoomChange: zoom => contextProps.onZoomChange?.(clamp(zoom / (zoomFactor / clientRect().width), minZoom(), maxZoom()))
694
- }),
695
- vertical: () => ({
696
- pixelOffset: clientRect().top,
697
- pixelSize: clientRect().height,
698
- position: contextProps.verticalPosition,
699
- range: 128,
700
- zoom: contextProps.verticalZoom * (zoomFactor / clientRect().height),
701
- onPositionChange: contextProps.onVerticalPositionChange,
702
- onZoomChange: verticalZoom => contextProps.onVerticalZoomChange?.(clamp(verticalZoom / (zoomFactor / clientRect().height), minVerticalZoom(), maxVerticalZoom()))
703
- })
704
- },
705
- get children() {
706
- const _el$ = _tmpl$2.cloneNode(true),
707
- _el$2 = _el$.firstChild,
708
- _el$3 = _el$2.nextSibling,
709
- _el$4 = _el$3.firstChild;
710
- _el$.style.setProperty("display", "flex");
711
- _el$.style.setProperty("flex", "1");
712
- _el$.style.setProperty("height", "100%");
713
- _el$.style.setProperty("flex-direction", "row");
714
- _el$2.style.setProperty("margin-block-start", "0");
715
- _el$2.style.setProperty("padding-inline-start", "0");
716
- _el$2.style.setProperty("width", "150px");
717
- insert(_el$2, createComponent(Index, {
718
- get each() {
719
- return allProps.tracks;
720
- },
721
- children: track => (() => {
722
- const _el$6 = _tmpl$3.cloneNode(true);
723
- _el$6.$$click = () => {
724
- if (track() === allProps.selectedTrack) {
725
- allProps.onSelectedTrackChange(undefined);
726
- } else {
727
- allProps.onSelectedTrackChange(track());
728
- }
729
- };
730
- _el$6.style.setProperty("width", "150px");
731
- _el$6.style.setProperty("height", "30px");
732
- _el$6.style.setProperty("list-style", "none");
733
- _el$6.style.setProperty("display", "flex");
734
- _el$6.style.setProperty("align-items", "center");
735
- _el$6.style.setProperty("border-top", "1px black solid");
736
- _el$6.style.setProperty("cursor", "pointer");
737
- insert(_el$6, () => track().name);
738
- effect(() => _el$6.style.setProperty("background", track() === allProps.selectedTrack ? "lightgray" : "none"));
739
- return _el$6;
740
- })()
741
- }));
742
- _el$3.style.setProperty("flex", "1");
743
- insert(_el$4, createComponent(Show, {
744
- get when() {
745
- return !condensed();
746
- },
747
- get children() {
748
- return createComponent(PianoRollKeys, {});
749
- }
750
- }), null);
751
- insert(_el$4, createComponent(ScrollContainer, {
752
- ref: setScrollerRef,
753
- get children() {
754
- const _el$5 = _tmpl$$1.cloneNode(true);
755
- _el$5.style.setProperty("margin", "0");
756
- _el$5.style.setProperty("margin-block-start", "0");
757
- _el$5.style.setProperty("padding-inline-start", "0");
758
- insert(_el$5, createComponent(Index, {
688
+ return (() => {
689
+ const _el$ = _tmpl$4.cloneNode(true);
690
+ spread(_el$, mergeProps(divProps, {
691
+ get style() {
692
+ return {
693
+ display: "flex",
694
+ flex: 1,
695
+ height: "100%",
696
+ "flex-direction": "row",
697
+ overflow: "hidden",
698
+ ...(typeof divProps.style === "object" && divProps.style)
699
+ };
700
+ }
701
+ }), false, true);
702
+ insert(_el$, createComponent(PianoRollContextProvider, {
703
+ get value() {
704
+ return {
705
+ ...contextProps
706
+ };
707
+ },
708
+ get children() {
709
+ return createComponent(ScrollZoomViewPort, {
710
+ dimensions: {
711
+ horizontal: () => ({
712
+ pixelOffset: clientRect().left,
713
+ pixelSize: clientRect().width,
714
+ position: contextProps.position,
715
+ range: contextProps.duration,
716
+ zoom: contextProps.zoom * (zoomFactor / clientRect().width),
717
+ onPositionChange: contextProps.onPositionChange,
718
+ onZoomChange: zoom => contextProps.onZoomChange?.(clamp(zoom / (zoomFactor / clientRect().width), minZoom(), maxZoom()))
719
+ }),
720
+ vertical: () => ({
721
+ pixelOffset: clientRect().top,
722
+ pixelSize: clientRect().height,
723
+ position: contextProps.verticalPosition,
724
+ range: 128,
725
+ zoom: contextProps.verticalZoom * (zoomFactor / clientRect().height),
726
+ onPositionChange: contextProps.onVerticalPositionChange,
727
+ onZoomChange: verticalZoom => contextProps.onVerticalZoomChange?.(clamp(verticalZoom / (zoomFactor / clientRect().height), minVerticalZoom(), maxVerticalZoom()))
728
+ })
729
+ },
730
+ get children() {
731
+ return [(() => {
732
+ const _el$2 = _tmpl$$2.cloneNode(true),
733
+ _el$3 = _el$2.firstChild;
734
+ _el$2.style.setProperty("width", "250px");
735
+ _el$2.style.setProperty("display", "flex");
736
+ _el$2.style.setProperty("flex-direction", "row");
737
+ _el$3.style.setProperty("margin-block-start", "0");
738
+ _el$3.style.setProperty("padding-inline-start", "0");
739
+ _el$3.style.setProperty("flex", "1");
740
+ _el$3.style.setProperty("position", "relative");
741
+ insert(_el$3, createComponent(Index, {
759
742
  get each() {
760
743
  return allProps.tracks;
761
744
  },
762
- children: track => {
763
- const notes = useNotes();
764
- createEffect(() => {
765
- notes.onNotesChange(track().notes);
766
- });
767
- const [context, setContext] = createStore({
768
- ...contextProps
769
- });
770
- createEffect(() => {
771
- setContext({
772
- ...contextProps,
773
- condensed: condensed(),
774
- notes: notes.notes(),
775
- onNoteChange: notes.onNoteChange,
776
- onInsertNote: notes.onInsertNote,
777
- onRemoveNote: notes.onRemoveNote
778
- });
779
- });
780
- const verticalViewPort = useViewPortDimension("vertical");
781
- return createComponent(Show, {
782
- get when() {
783
- return condensed() || allProps.selectedTrack === track();
784
- },
785
- get children() {
786
- return createComponent(PianoRollContextProvider, {
787
- value: context,
788
- get children() {
789
- const _el$7 = _tmpl$3.cloneNode(true);
790
- _el$7.style.setProperty("display", "flex");
791
- _el$7.style.setProperty("position", "relative");
792
- _el$7.style.setProperty("list-style", "none");
793
- _el$7.style.setProperty("flex-direction", "row");
794
- _el$7.style.setProperty("border-top", "1px black solid");
795
- insert(_el$7, createComponent(PianoRollNotes, {}), null);
796
- insert(_el$7, createComponent(PianoRollGrid, {}), null);
797
- effect(() => _el$7.style.setProperty("height", condensed() ? "30px" : `${verticalViewPort.pixelSize}px`));
798
- return _el$7;
799
- }
800
- });
745
+ children: (track, noteIndex) => (() => {
746
+ const _el$7 = _tmpl$5.cloneNode(true);
747
+ _el$7.$$click = () => {
748
+ if (noteIndex === allProps.selectedTrackIndex) {
749
+ allProps.onSelectedTrackIndexChange(-1);
750
+ } else {
751
+ allProps.onSelectedTrackIndexChange(noteIndex);
801
752
  }
753
+ };
754
+ _el$7.style.setProperty("width", "100%");
755
+ _el$7.style.setProperty("height", "30px");
756
+ _el$7.style.setProperty("list-style", "none");
757
+ _el$7.style.setProperty("display", "flex");
758
+ _el$7.style.setProperty("align-items", "center");
759
+ _el$7.style.setProperty("border-top", "1px black solid");
760
+ _el$7.style.setProperty("cursor", "pointer");
761
+ insert(_el$7, () => track().name);
762
+ effect(() => _el$7.style.setProperty("background", noteIndex === allProps.selectedTrackIndex ? "lightgray" : "none"));
763
+ return _el$7;
764
+ })()
765
+ }));
766
+ insert(_el$2, createComponent(Show, {
767
+ get when() {
768
+ return !condensed();
769
+ },
770
+ get children() {
771
+ return createComponent(PianoRollKeys, {});
772
+ }
773
+ }), null);
774
+ return _el$2;
775
+ })(), (() => {
776
+ const _el$4 = _tmpl$3.cloneNode(true),
777
+ _el$5 = _el$4.firstChild;
778
+ _el$4.style.setProperty("flex", "1");
779
+ insert(_el$5, createComponent(ScrollContainer, {
780
+ ref: setScrollerRef,
781
+ get children() {
782
+ return [memo(() => allProps.children), (() => {
783
+ const _el$6 = _tmpl$2.cloneNode(true);
784
+ _el$6.style.setProperty("margin", "0");
785
+ _el$6.style.setProperty("margin-block-start", "0");
786
+ _el$6.style.setProperty("padding-inline-start", "0");
787
+ insert(_el$6, createComponent(Index, {
788
+ get each() {
789
+ return allProps.tracks;
790
+ },
791
+ children: (track, trackIndex) => {
792
+ const notes = useNotes();
793
+ createEffect(() => {
794
+ notes.onNotesChange(track().notes);
795
+ });
796
+ const [context, setContext] = createStore({
797
+ ...contextProps
798
+ });
799
+ createEffect(() => {
800
+ setContext({
801
+ ...contextProps,
802
+ condensed: condensed(),
803
+ notes: track()?.notes,
804
+ onNoteChange: (noteIndex, note) => allProps?.onNoteChange?.(trackIndex, noteIndex, note),
805
+ onInsertNote: note => allProps.onInsertNote?.(trackIndex, note) ?? -1,
806
+ onRemoveNote: noteIndex => allProps.onRemoveNote?.(trackIndex, noteIndex)
807
+ });
808
+ });
809
+ const verticalViewPort = useViewPortDimension("vertical");
810
+ return createComponent(Show, {
811
+ get when() {
812
+ return condensed() || allProps.selectedTrackIndex === trackIndex;
813
+ },
814
+ get children() {
815
+ return createComponent(PianoRollContextProvider, {
816
+ value: context,
817
+ get children() {
818
+ const _el$8 = _tmpl$5.cloneNode(true);
819
+ _el$8.style.setProperty("display", "flex");
820
+ _el$8.style.setProperty("position", "relative");
821
+ _el$8.style.setProperty("list-style", "none");
822
+ _el$8.style.setProperty("flex-direction", "row");
823
+ _el$8.style.setProperty("border-top", "1px black solid");
824
+ insert(_el$8, createComponent(PianoRollNotes, {}), null);
825
+ insert(_el$8, createComponent(PianoRollGrid, {}), null);
826
+ effect(() => _el$8.style.setProperty("height", condensed() ? "30px" : `${verticalViewPort.pixelSize}px`));
827
+ return _el$8;
828
+ }
829
+ });
830
+ }
831
+ });
832
+ }
833
+ }));
834
+ return _el$6;
835
+ })()];
836
+ }
837
+ }), null);
838
+ insert(_el$5, createComponent(Show, {
839
+ get when() {
840
+ return !condensed();
841
+ },
842
+ get children() {
843
+ return createComponent(VerticalZoomControl, {
844
+ get value() {
845
+ return contextProps.verticalZoom;
846
+ },
847
+ onInput: event => contextProps.onVerticalZoomChange?.(event.currentTarget.valueAsNumber)
802
848
  });
803
849
  }
804
- }));
805
- return _el$5;
806
- }
807
- }), null);
808
- insert(_el$4, createComponent(Show, {
809
- get when() {
810
- return !condensed();
811
- },
812
- get children() {
813
- return createComponent(VerticalZoomControl, {
850
+ }), null);
851
+ insert(_el$4, createComponent(HorizontalZoomControl, {
852
+ style: {
853
+ width: "100%",
854
+ "margin-left": 0
855
+ },
814
856
  get value() {
815
- return contextProps.verticalZoom;
857
+ return contextProps.zoom;
816
858
  },
817
- onInput: event => contextProps.onVerticalZoomChange?.(event.currentTarget.valueAsNumber)
859
+ onInput: event => contextProps.onZoomChange?.(event.currentTarget.valueAsNumber)
860
+ }), null);
861
+ effect(_p$ => {
862
+ const _v$ = styles$3.PianoRoll,
863
+ _v$2 = styles$3.PianoRollContainer;
864
+ _v$ !== _p$._v$ && className(_el$4, _p$._v$ = _v$);
865
+ _v$2 !== _p$._v$2 && className(_el$5, _p$._v$2 = _v$2);
866
+ return _p$;
867
+ }, {
868
+ _v$: undefined,
869
+ _v$2: undefined
818
870
  });
819
- }
820
- }), null);
821
- insert(_el$3, createComponent(HorizontalZoomControl, {
822
- style: {
823
- width: "100%",
824
- "margin-left": 0
825
- },
826
- get value() {
827
- return contextProps.zoom;
828
- },
829
- onInput: event => contextProps.onZoomChange?.(event.currentTarget.valueAsNumber)
830
- }), null);
831
- effect(_p$ => {
832
- const _v$ = styles$3.PianoRoll,
833
- _v$2 = styles$3.PianoRollContainer;
834
- _v$ !== _p$._v$ && className(_el$3, _p$._v$ = _v$);
835
- _v$2 !== _p$._v$2 && className(_el$4, _p$._v$2 = _v$2);
836
- return _p$;
837
- }, {
838
- _v$: undefined,
839
- _v$2: undefined
840
- });
841
- return _el$;
842
- }
843
- });
844
- }
845
- });
871
+ return _el$4;
872
+ })()];
873
+ }
874
+ });
875
+ }
876
+ }));
877
+ return _el$;
878
+ })();
846
879
  };
847
880
  delegateEvents(["click"]);
848
881
 
849
- const _tmpl$ = /*#__PURE__*/template(`<div><div></div></div>`, 4);
882
+ const _tmpl$$1 = /*#__PURE__*/template(`<div><div></div></div>`, 4);
850
883
  const PianoRoll = allProps => {
851
884
  const [contextProps, divProps] = splitContextProps(allProps);
852
885
  const [scrollerRef, setScrollerRef] = createSignal();
@@ -859,7 +892,7 @@ const PianoRoll = allProps => {
859
892
  return createComponent(PianoRollContextProvider, {
860
893
  value: contextProps,
861
894
  get children() {
862
- const _el$ = _tmpl$.cloneNode(true),
895
+ const _el$ = _tmpl$$1.cloneNode(true),
863
896
  _el$2 = _el$.firstChild;
864
897
  spread(_el$, mergeProps(divProps, {
865
898
  get ["class"]() {
@@ -891,7 +924,7 @@ const PianoRoll = allProps => {
891
924
  return [createComponent(PianoRollKeys, {}), createComponent(ScrollContainer, {
892
925
  ref: setScrollerRef,
893
926
  get children() {
894
- return [createComponent(PianoRollGrid, {}), createComponent(PianoRollNotes, {})];
927
+ return [memo(() => allProps.children), createComponent(PianoRollGrid, {}), createComponent(PianoRollNotes, {})];
895
928
  }
896
929
  }), createComponent(VerticalZoomControl, {
897
930
  get min() {
@@ -917,6 +950,60 @@ const PianoRoll = allProps => {
917
950
  });
918
951
  };
919
952
 
953
+ const _tmpl$ = /*#__PURE__*/template(`<div class="PlayHead"></div>`, 2);
954
+ const PlayHead = allProps => {
955
+ const propsWithDefauls = mergeProps$1({
956
+ playHeadPosition: 0,
957
+ sync: false
958
+ }, allProps);
959
+ const [props, divProps] = splitProps(propsWithDefauls, ["playHeadPosition", "sync", "onPlayHeadPositionChange", "onPositionChange"]);
960
+ const viewPort = useViewPortDimension("horizontal");
961
+ createEffect(() => {
962
+ if (!props.sync) return;
963
+ const maxPosition = viewPort.range;
964
+ const newPosition = clamp(props.playHeadPosition - viewPort.range / viewPort.zoom / 2, 0, maxPosition);
965
+ props.onPositionChange?.(newPosition);
966
+ });
967
+ const leftPosition = createMemo(() => viewPort.calculatePixelOffset(props.playHeadPosition));
968
+ return (() => {
969
+ const _el$ = _tmpl$.cloneNode(true);
970
+ spread(_el$, mergeProps(divProps, {
971
+ get style() {
972
+ return {
973
+ position: "absolute",
974
+ height: "100%",
975
+ width: "2px",
976
+ left: `${leftPosition()}px`,
977
+ "background-color": "green",
978
+ cursor: "pointer",
979
+ ...(typeof divProps.style === "object" && divProps.style)
980
+ };
981
+ },
982
+ "onMouseDown": event => {
983
+ event.preventDefault();
984
+ event.stopPropagation();
985
+ const handleMouseMove = ({
986
+ movementX
987
+ }) => {
988
+ const {
989
+ parentElement
990
+ } = event.currentTarget;
991
+ if (!parentElement) return;
992
+ const newPosition = viewPort.calculatePosition(leftPosition() + movementX);
993
+ props.onPlayHeadPositionChange?.(newPosition);
994
+ };
995
+ const handleMouseUp = () => {
996
+ window.removeEventListener("mousemove", handleMouseMove);
997
+ window.removeEventListener("mouseup", handleMouseUp);
998
+ };
999
+ window.addEventListener("mousemove", handleMouseMove);
1000
+ window.addEventListener("mouseup", handleMouseUp);
1001
+ }
1002
+ }), false, false);
1003
+ return _el$;
1004
+ })();
1005
+ };
1006
+
920
1007
  const usePianoRoll = () => {
921
1008
  const [ppq, onPpqChange] = createSignal(120);
922
1009
  const [condensed, onCondensedChange] = createSignal(false);
@@ -924,7 +1011,7 @@ const usePianoRoll = () => {
924
1011
  const [zoom, onZoomChange] = createSignal(10);
925
1012
  const [verticalZoom, onVerticalZoomChange] = createSignal(5);
926
1013
  const [verticalPosition, onVerticalPositionChange] = createSignal(64);
927
- const [gridDivision, onGridDivisionChange] = createSignal(16);
1014
+ const [gridDivision, onGridDivisionChange] = createSignal(4);
928
1015
  const [snapToGrid, onSnapToGridChange] = createSignal(true);
929
1016
  const [duration, onDurationChange] = createSignal(0);
930
1017
  return {
@@ -949,5 +1036,5 @@ const usePianoRoll = () => {
949
1036
  };
950
1037
  };
951
1038
 
952
- export { MultiTrackPianoRoll, PianoRoll, useNotes, usePianoRoll };
1039
+ export { MultiTrackPianoRoll, PianoRoll, PlayHead, useNotes, usePianoRoll };
953
1040
  //# sourceMappingURL=index.js.map