solid-pianoroll 0.0.13 → 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);
@@ -221,7 +222,7 @@ const PianoRollNotes = props => {
221
222
  return memo(() => !!(verticalViewPort().isVisible(verticalVirtualDimensions()) || context.condensed))() && horizontalViewPort().isVisible(horizontalDimensions());
222
223
  },
223
224
  get children() {
224
- const _el$2 = _tmpl$$6.cloneNode(true);
225
+ const _el$2 = _tmpl$$7.cloneNode(true);
225
226
  _el$2.$$mousedown = event => {
226
227
  event.stopPropagation();
227
228
  setIsDragging(true);
@@ -297,7 +298,7 @@ const PianoRollNotes = props => {
297
298
  };
298
299
  delegateEvents(["mousedown", "mousemove", "mouseup", "dblclick", "click"]);
299
300
 
300
- 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);
301
302
  const ScrollContainer = props => {
302
303
  let scrollContentRef;
303
304
  const verticalViewPort = createMemo(() => useViewPortDimension("vertical"));
@@ -359,7 +360,7 @@ const ScrollContainer = props => {
359
360
  });
360
361
  });
361
362
  return (() => {
362
- const _el$ = _tmpl$$5.cloneNode(true),
363
+ const _el$ = _tmpl$$6.cloneNode(true),
363
364
  _el$2 = _el$.firstChild,
364
365
  _el$3 = _el$2.firstChild,
365
366
  _el$4 = _el$3.firstChild;
@@ -404,11 +405,11 @@ var css_248z$1 = ".PianoRollKeys-module_PianoRollKeys__5vnQ0 {\n position: rela
404
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"};
405
406
  styleInject(css_248z$1);
406
407
 
407
- const _tmpl$$4 = /*#__PURE__*/template(`<div></div>`, 2);
408
+ const _tmpl$$5 = /*#__PURE__*/template(`<div></div>`, 2);
408
409
  const PianoRollKeys = () => {
409
410
  const viewPort = createMemo(() => useViewPortDimension("vertical"));
410
411
  return (() => {
411
- const _el$ = _tmpl$$4.cloneNode(true);
412
+ const _el$ = _tmpl$$5.cloneNode(true);
412
413
  insert(_el$, createComponent(Index, {
413
414
  each: keys,
414
415
  children: key => {
@@ -418,7 +419,7 @@ const PianoRollKeys = () => {
418
419
  return virtualDimensions().size > 0;
419
420
  },
420
421
  get children() {
421
- const _el$2 = _tmpl$$4.cloneNode(true);
422
+ const _el$2 = _tmpl$$5.cloneNode(true);
422
423
  effect(_p$ => {
423
424
  const _v$ = {
424
425
  [styles$1["Key"]]: true,
@@ -467,7 +468,7 @@ var css_248z = ".PianoRollGrid-module_PianoRollGrid__tG119 {\n position: relati
467
468
  var styles = {"PianoRollGrid":"PianoRollGrid-module_PianoRollGrid__tG119","PianoRollGrid-Key":"PianoRollGrid-module_PianoRollGrid-Key__VRbiB","PianoRollGrid-Time":"PianoRollGrid-module_PianoRollGrid-Time__jLz3E"};
468
469
  styleInject(css_248z);
469
470
 
470
- const _tmpl$$3 = /*#__PURE__*/template(`<div></div>`, 2);
471
+ const _tmpl$$4 = /*#__PURE__*/template(`<div></div>`, 2);
471
472
  const PianoRollGrid = () => {
472
473
  const context = usePianoRollContext();
473
474
  const verticalViewPort = createMemo(() => useViewPortDimension("vertical"));
@@ -475,10 +476,12 @@ const PianoRollGrid = () => {
475
476
  const measureTicks = createMemo(() => context.ppq * 4);
476
477
  const selectedGridDivisorTicks = createMemo(() => measureTicks() / context.gridDivision);
477
478
  function calculateVisibleGridDivisorTicks(value) {
478
- if (horizontalViewPort().calculateVisibleRange() / value > 100) {
479
+ const visibleRange = horizontalViewPort().calculateVisibleRange();
480
+ if (visibleRange <= 0) return 0;
481
+ if (visibleRange / value > 100) {
479
482
  return calculateVisibleGridDivisorTicks(value * 2);
480
483
  }
481
- if (horizontalViewPort().calculateVisibleRange() / value < 30) {
484
+ if (visibleRange / value < 30) {
482
485
  return calculateVisibleGridDivisorTicks(value / 2);
483
486
  }
484
487
  return value;
@@ -495,7 +498,7 @@ const PianoRollGrid = () => {
495
498
  }));
496
499
  });
497
500
  return (() => {
498
- const _el$ = _tmpl$$3.cloneNode(true);
501
+ const _el$ = _tmpl$$4.cloneNode(true);
499
502
  insert(_el$, createComponent(Index, {
500
503
  get each() {
501
504
  return gridArray();
@@ -507,7 +510,7 @@ const PianoRollGrid = () => {
507
510
  return virtualDimensions().size > 0;
508
511
  },
509
512
  get children() {
510
- const _el$2 = _tmpl$$3.cloneNode(true);
513
+ const _el$2 = _tmpl$$4.cloneNode(true);
511
514
  effect(_p$ => {
512
515
  const _v$ = styles["PianoRollGrid-Time"],
513
516
  _v$2 = Math.ceil((entry().index + 1 * selectedGridDivisorTicks()) / measureTicks()) % 2 === 0 ? "#ddd" : "#ccc",
@@ -546,7 +549,7 @@ const PianoRollGrid = () => {
546
549
  return virtualDimensions().size > 0;
547
550
  },
548
551
  get children() {
549
- const _el$3 = _tmpl$$3.cloneNode(true);
552
+ const _el$3 = _tmpl$$4.cloneNode(true);
550
553
  _el$3.style.setProperty("width", "100%");
551
554
  effect(_p$ => {
552
555
  const _v$6 = styles["PianoRollGrid-Key"],
@@ -631,11 +634,11 @@ function useBoundingClientRect(containerRef) {
631
634
  return boundingClientRect;
632
635
  }
633
636
 
634
- 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);
635
638
  const VerticalZoomControl = props => {
636
639
  const context = usePianoRollContext();
637
640
  return (() => {
638
- const _el$ = _tmpl$$2.cloneNode(true);
641
+ const _el$ = _tmpl$$3.cloneNode(true);
639
642
  spread(_el$, mergeProps(props, {
640
643
  get value() {
641
644
  return context.verticalZoom;
@@ -659,15 +662,21 @@ const VerticalZoomControl = props => {
659
662
  })();
660
663
  };
661
664
 
662
- const _tmpl$$1 = /*#__PURE__*/template(`<ul></ul>`, 2),
663
- _tmpl$2 = /*#__PURE__*/template(`<div><ul></ul><div><div></div></div></div>`, 8),
664
- _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);
665
670
  const MultiTrackPianoRoll = allProps => {
666
- const condensed = createMemo(() => !allProps.selectedTrack);
667
- 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"]);
668
674
  const [contextProps, divProps] = splitContextProps(mergeProps$1(restProps, {
669
675
  notes: [],
670
- condensed: false
676
+ condensed: false,
677
+ onNoteChange: () => undefined,
678
+ onInsertNote: () => -1,
679
+ onRemoveNote: () => undefined
671
680
  }));
672
681
  const [scrollerRef, setScrollerRef] = createSignal();
673
682
  const clientRect = useBoundingClientRect(scrollerRef);
@@ -676,179 +685,201 @@ const MultiTrackPianoRoll = allProps => {
676
685
  const maxZoom = createMemo(() => 500 * (zoomFactor / clientRect().width));
677
686
  const minVerticalZoom = createMemo(() => 1 / (zoomFactor / clientRect().height));
678
687
  const maxVerticalZoom = createMemo(() => 10 * (zoomFactor / clientRect().height));
679
- return createComponent(PianoRollContextProvider, {
680
- get value() {
681
- return {
682
- ...contextProps
683
- };
684
- },
685
- get children() {
686
- return createComponent(ScrollZoomViewPort, {
687
- dimensions: {
688
- horizontal: () => ({
689
- pixelOffset: clientRect().left,
690
- pixelSize: clientRect().width,
691
- position: contextProps.position,
692
- range: contextProps.duration,
693
- zoom: contextProps.zoom * (zoomFactor / clientRect().width),
694
- onPositionChange: contextProps.onPositionChange,
695
- onZoomChange: zoom => contextProps.onZoomChange?.(clamp(zoom / (zoomFactor / clientRect().width), minZoom(), maxZoom()))
696
- }),
697
- vertical: () => ({
698
- pixelOffset: clientRect().top,
699
- pixelSize: clientRect().height,
700
- position: contextProps.verticalPosition,
701
- range: 128,
702
- zoom: contextProps.verticalZoom * (zoomFactor / clientRect().height),
703
- onPositionChange: contextProps.onVerticalPositionChange,
704
- onZoomChange: verticalZoom => contextProps.onVerticalZoomChange?.(clamp(verticalZoom / (zoomFactor / clientRect().height), minVerticalZoom(), maxVerticalZoom()))
705
- })
706
- },
707
- get children() {
708
- const _el$ = _tmpl$2.cloneNode(true),
709
- _el$2 = _el$.firstChild,
710
- _el$3 = _el$2.nextSibling,
711
- _el$4 = _el$3.firstChild;
712
- _el$.style.setProperty("display", "flex");
713
- _el$.style.setProperty("flex", "1");
714
- _el$.style.setProperty("height", "100%");
715
- _el$.style.setProperty("flex-direction", "row");
716
- _el$2.style.setProperty("margin-block-start", "0");
717
- _el$2.style.setProperty("padding-inline-start", "0");
718
- _el$2.style.setProperty("width", "150px");
719
- insert(_el$2, createComponent(Index, {
720
- get each() {
721
- return allProps.tracks;
722
- },
723
- children: track => (() => {
724
- const _el$6 = _tmpl$3.cloneNode(true);
725
- _el$6.$$click = () => {
726
- if (track() === allProps.selectedTrack) {
727
- allProps.onSelectedTrackChange(undefined);
728
- } else {
729
- allProps.onSelectedTrackChange(track());
730
- }
731
- };
732
- _el$6.style.setProperty("width", "150px");
733
- _el$6.style.setProperty("height", "30px");
734
- _el$6.style.setProperty("list-style", "none");
735
- _el$6.style.setProperty("display", "flex");
736
- _el$6.style.setProperty("align-items", "center");
737
- _el$6.style.setProperty("border-top", "1px black solid");
738
- _el$6.style.setProperty("cursor", "pointer");
739
- insert(_el$6, () => track().name);
740
- effect(() => _el$6.style.setProperty("background", track() === allProps.selectedTrack ? "lightgray" : "none"));
741
- return _el$6;
742
- })()
743
- }));
744
- _el$3.style.setProperty("flex", "1");
745
- insert(_el$4, createComponent(Show, {
746
- get when() {
747
- return !condensed();
748
- },
749
- get children() {
750
- return createComponent(PianoRollKeys, {});
751
- }
752
- }), null);
753
- insert(_el$4, createComponent(ScrollContainer, {
754
- ref: setScrollerRef,
755
- get children() {
756
- const _el$5 = _tmpl$$1.cloneNode(true);
757
- _el$5.style.setProperty("margin", "0");
758
- _el$5.style.setProperty("margin-block-start", "0");
759
- _el$5.style.setProperty("padding-inline-start", "0");
760
- 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, {
761
742
  get each() {
762
743
  return allProps.tracks;
763
744
  },
764
- children: track => {
765
- const notes = useNotes();
766
- createEffect(() => {
767
- notes.onNotesChange(track().notes);
768
- });
769
- const [context, setContext] = createStore({
770
- ...contextProps
771
- });
772
- createEffect(() => {
773
- setContext({
774
- ...contextProps,
775
- condensed: condensed(),
776
- notes: notes.notes(),
777
- onNoteChange: notes.onNoteChange,
778
- onInsertNote: notes.onInsertNote,
779
- onRemoveNote: notes.onRemoveNote
780
- });
781
- });
782
- const verticalViewPort = useViewPortDimension("vertical");
783
- return createComponent(Show, {
784
- get when() {
785
- return condensed() || allProps.selectedTrack === track();
786
- },
787
- get children() {
788
- return createComponent(PianoRollContextProvider, {
789
- value: context,
790
- get children() {
791
- const _el$7 = _tmpl$3.cloneNode(true);
792
- _el$7.style.setProperty("display", "flex");
793
- _el$7.style.setProperty("position", "relative");
794
- _el$7.style.setProperty("list-style", "none");
795
- _el$7.style.setProperty("flex-direction", "row");
796
- _el$7.style.setProperty("border-top", "1px black solid");
797
- insert(_el$7, createComponent(PianoRollNotes, {}), null);
798
- insert(_el$7, createComponent(PianoRollGrid, {}), null);
799
- effect(() => _el$7.style.setProperty("height", condensed() ? "30px" : `${verticalViewPort.pixelSize}px`));
800
- return _el$7;
801
- }
802
- });
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);
803
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)
804
848
  });
805
849
  }
806
- }));
807
- return _el$5;
808
- }
809
- }), null);
810
- insert(_el$4, createComponent(Show, {
811
- get when() {
812
- return !condensed();
813
- },
814
- get children() {
815
- return createComponent(VerticalZoomControl, {
850
+ }), null);
851
+ insert(_el$4, createComponent(HorizontalZoomControl, {
852
+ style: {
853
+ width: "100%",
854
+ "margin-left": 0
855
+ },
816
856
  get value() {
817
- return contextProps.verticalZoom;
857
+ return contextProps.zoom;
818
858
  },
819
- 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
820
870
  });
821
- }
822
- }), null);
823
- insert(_el$3, createComponent(HorizontalZoomControl, {
824
- style: {
825
- width: "100%",
826
- "margin-left": 0
827
- },
828
- get value() {
829
- return contextProps.zoom;
830
- },
831
- onInput: event => contextProps.onZoomChange?.(event.currentTarget.valueAsNumber)
832
- }), null);
833
- effect(_p$ => {
834
- const _v$ = styles$3.PianoRoll,
835
- _v$2 = styles$3.PianoRollContainer;
836
- _v$ !== _p$._v$ && className(_el$3, _p$._v$ = _v$);
837
- _v$2 !== _p$._v$2 && className(_el$4, _p$._v$2 = _v$2);
838
- return _p$;
839
- }, {
840
- _v$: undefined,
841
- _v$2: undefined
842
- });
843
- return _el$;
844
- }
845
- });
846
- }
847
- });
871
+ return _el$4;
872
+ })()];
873
+ }
874
+ });
875
+ }
876
+ }));
877
+ return _el$;
878
+ })();
848
879
  };
849
880
  delegateEvents(["click"]);
850
881
 
851
- const _tmpl$ = /*#__PURE__*/template(`<div><div></div></div>`, 4);
882
+ const _tmpl$$1 = /*#__PURE__*/template(`<div><div></div></div>`, 4);
852
883
  const PianoRoll = allProps => {
853
884
  const [contextProps, divProps] = splitContextProps(allProps);
854
885
  const [scrollerRef, setScrollerRef] = createSignal();
@@ -861,7 +892,7 @@ const PianoRoll = allProps => {
861
892
  return createComponent(PianoRollContextProvider, {
862
893
  value: contextProps,
863
894
  get children() {
864
- const _el$ = _tmpl$.cloneNode(true),
895
+ const _el$ = _tmpl$$1.cloneNode(true),
865
896
  _el$2 = _el$.firstChild;
866
897
  spread(_el$, mergeProps(divProps, {
867
898
  get ["class"]() {
@@ -893,7 +924,7 @@ const PianoRoll = allProps => {
893
924
  return [createComponent(PianoRollKeys, {}), createComponent(ScrollContainer, {
894
925
  ref: setScrollerRef,
895
926
  get children() {
896
- return [createComponent(PianoRollGrid, {}), createComponent(PianoRollNotes, {})];
927
+ return [memo(() => allProps.children), createComponent(PianoRollGrid, {}), createComponent(PianoRollNotes, {})];
897
928
  }
898
929
  }), createComponent(VerticalZoomControl, {
899
930
  get min() {
@@ -919,6 +950,60 @@ const PianoRoll = allProps => {
919
950
  });
920
951
  };
921
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
+
922
1007
  const usePianoRoll = () => {
923
1008
  const [ppq, onPpqChange] = createSignal(120);
924
1009
  const [condensed, onCondensedChange] = createSignal(false);
@@ -951,5 +1036,5 @@ const usePianoRoll = () => {
951
1036
  };
952
1037
  };
953
1038
 
954
- export { MultiTrackPianoRoll, PianoRoll, useNotes, usePianoRoll };
1039
+ export { MultiTrackPianoRoll, PianoRoll, PlayHead, useNotes, usePianoRoll };
955
1040
  //# sourceMappingURL=index.js.map