solid-pianoroll 0.0.11 → 0.0.13

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.
@@ -12,7 +12,9 @@ const PianoRollNotes = (props) => {
12
12
  : value;
13
13
  const insertOrUpdateNote = (event) => {
14
14
  const position = horizontalViewPort().calculatePosition(event.clientX);
15
- const midi = 127 - Math.floor(verticalViewPort().calculatePosition(event.clientY));
15
+ const midi = context.condensed
16
+ ? 60
17
+ : 127 - Math.floor(verticalViewPort().calculatePosition(event.clientY));
16
18
  const eventPositionTicks = Math.floor(position / gridDivisionTicks()) * gridDivisionTicks();
17
19
  const velocity = 127;
18
20
  const existingNote = newNote();
@@ -37,9 +39,11 @@ const PianoRollNotes = (props) => {
37
39
  const getClasses = (noteDragMode) => {
38
40
  return noteDragMode ? [styles.Note, styles[noteDragMode]] : [styles.Note];
39
41
  };
40
- return (<div class={styles.PianoRollNotes} ref={props.ref} onMouseDown={() => {
42
+ return (<div class={styles.PianoRollNotes} ref={props.ref} onMouseDown={(event) => {
41
43
  console.log("down");
42
44
  setIsMouseDown(true);
45
+ const index = insertOrUpdateNote(event);
46
+ setNewNoteIndex(index);
43
47
  }} onMouseMove={(event) => {
44
48
  if (isDragging())
45
49
  return;
@@ -48,7 +52,6 @@ const PianoRollNotes = (props) => {
48
52
  return;
49
53
  }
50
54
  const index = insertOrUpdateNote(event);
51
- console.log({ index });
52
55
  setNewNoteIndex(index);
53
56
  }} onMouseUp={(event) => {
54
57
  setIsMouseDown(false);
@@ -68,9 +71,10 @@ const PianoRollNotes = (props) => {
68
71
  }}>
69
72
  <Index each={context.notes}>
70
73
  {(note, index) => {
71
- const verticalVirtualDimensionss = createMemo(() => verticalViewPort().calculatePixelDimensions(127 - note().midi, 1));
74
+ const verticalVirtualDimensions = createMemo(() => verticalViewPort().calculatePixelDimensions(127 - note().midi, 1));
72
75
  const horizontalDimensions = createMemo(() => horizontalViewPort().calculatePixelDimensions(note().ticks, note().durationTicks));
73
- return (<Show when={!!verticalVirtualDimensionss().size && !!horizontalDimensions().size}>
76
+ return (<Show when={(verticalViewPort().isVisible(verticalVirtualDimensions()) || context.condensed) &&
77
+ horizontalViewPort().isVisible(horizontalDimensions())}>
74
78
  <div class={getClasses(noteDragMode()).join(" ")} onMouseMove={(event) => {
75
79
  if (isDragging())
76
80
  return;
@@ -96,7 +100,8 @@ const PianoRollNotes = (props) => {
96
100
  diffPosition, 0), mouseMoveEvent.altKey);
97
101
  context.onNoteChange?.(index, {
98
102
  ...note(),
99
- ...(noteDragMode() === "move" && {
103
+ ...(noteDragMode() === "move" &&
104
+ !context.condensed && {
100
105
  midi: Math.round(127 - verticalViewPort().calculatePosition(mouseMoveEvent.clientY)),
101
106
  }),
102
107
  ...((noteDragMode() === "move" || noteDragMode() === "trimStart") && {
@@ -120,8 +125,12 @@ const PianoRollNotes = (props) => {
120
125
  window.addEventListener("mouseup", handleMouseUp);
121
126
  }} style={{
122
127
  "background-color": `rgba(255,0,0, ${(128 + note().velocity) / 256})`,
123
- top: `${verticalVirtualDimensionss().offset}px`,
124
- height: `${verticalVirtualDimensionss().size}px`,
128
+ ...(context.condensed
129
+ ? { top: 0, height: "100%" }
130
+ : {
131
+ top: `${verticalVirtualDimensions().offset}px`,
132
+ height: `${verticalVirtualDimensions().size}px`,
133
+ }),
125
134
  left: `${horizontalDimensions().offset}px`,
126
135
  width: `${horizontalDimensions().size}px`,
127
136
  }}></div>
@@ -1,3 +1,5 @@
1
+ import MultiTrackPianoRoll from "./MultiTrackPianoRoll";
1
2
  import PianoRoll from "./PianoRoll";
3
+ import useNotes from "./useNotes";
2
4
  import usePianoRoll from "./usePianoRoll";
3
- export { PianoRoll, usePianoRoll };
5
+ export { PianoRoll, MultiTrackPianoRoll, usePianoRoll, useNotes };
@@ -0,0 +1,23 @@
1
+ import { createSignal } from "solid-js";
2
+ const useNotes = () => {
3
+ const [notes, onNotesChange] = createSignal([]);
4
+ const onNoteChange = (index, note) => {
5
+ onNotesChange([...notes().slice(0, index), note, ...notes().splice(index + 1)]);
6
+ };
7
+ const onInsertNote = (note) => {
8
+ const index = Math.max(notes().findIndex(({ ticks }) => ticks > note.ticks), 0);
9
+ onNotesChange([...notes().slice(0, index), note, ...notes().splice(index)]);
10
+ return index;
11
+ };
12
+ const onRemoveNote = (index) => {
13
+ onNotesChange([...notes().slice(0, index), ...notes().splice(index + 1)]);
14
+ };
15
+ return {
16
+ notes,
17
+ onNotesChange,
18
+ onNoteChange,
19
+ onInsertNote,
20
+ onRemoveNote,
21
+ };
22
+ };
23
+ export default useNotes;
@@ -1,31 +1,14 @@
1
- import { createEffect, createSignal } from "solid-js";
1
+ import { createSignal } from "solid-js";
2
2
  const usePianoRoll = () => {
3
3
  const [ppq, onPpqChange] = createSignal(120);
4
+ const [condensed, onCondensedChange] = createSignal(false);
4
5
  const [position, onPositionChange] = createSignal(0);
5
6
  const [zoom, onZoomChange] = createSignal(10);
6
7
  const [verticalZoom, onVerticalZoomChange] = createSignal(5);
7
8
  const [verticalPosition, onVerticalPositionChange] = createSignal(64);
8
- const [gridDivision, onGridDivisionChange] = createSignal(16);
9
+ const [gridDivision, onGridDivisionChange] = createSignal(4);
9
10
  const [snapToGrid, onSnapToGridChange] = createSignal(true);
10
- const [notes, onNotesChange] = createSignal([]);
11
11
  const [duration, onDurationChange] = createSignal(0);
12
- const onNoteChange = (index, note) => {
13
- onNotesChange([...notes().slice(0, index), note, ...notes().splice(index + 1)]);
14
- };
15
- const onInsertNote = (note) => {
16
- const index = Math.max(notes().findIndex(({ ticks }) => ticks > note.ticks), 0);
17
- onNotesChange([...notes().slice(0, index), note, ...notes().splice(index)]);
18
- return index;
19
- };
20
- const onRemoveNote = (index) => {
21
- onNotesChange([...notes().slice(0, index), ...notes().splice(index + 1)]);
22
- };
23
- createEffect(() => {
24
- const minDuration = Math.max((notes()[notes().length - 1]?.ticks ?? 0) + (notes()[notes().length - 1]?.durationTicks ?? 0), ppq() * 4 * 4);
25
- if (duration() < minDuration) {
26
- onDurationChange(minDuration);
27
- }
28
- });
29
12
  return {
30
13
  ppq,
31
14
  onPpqChange,
@@ -41,11 +24,8 @@ const usePianoRoll = () => {
41
24
  onGridDivisionChange,
42
25
  snapToGrid,
43
26
  onSnapToGridChange,
44
- notes,
45
- onNotesChange,
46
- onNoteChange,
47
- onInsertNote,
48
- onRemoveNote,
27
+ condensed,
28
+ onCondensedChange,
49
29
  duration,
50
30
  onDurationChange,
51
31
  };
@@ -4,6 +4,7 @@ const HorizontalZoomControl = (props) => {
4
4
  return (<input max="500" min="1" step={0.01} {...props} value={context.zoom} onInput={(event) => context.onZoomChange?.(event.currentTarget.valueAsNumber)} type="range" style={{
5
5
  "margin-left": "50px",
6
6
  "margin-right": "16px",
7
+ ...(typeof props.style === "object" && props.style),
7
8
  }}/>);
8
9
  };
9
10
  export default HorizontalZoomControl;
@@ -8,6 +8,7 @@ export default function createViewPortDimension(getState) {
8
8
  calculatePixelDimensions,
9
9
  calculateVisibleRange,
10
10
  calculateMaxPosition,
11
+ isVisible,
11
12
  });
12
13
  const [state, setState] = createStore(getStateWithFunctions());
13
14
  createEffect(() => setState(getStateWithFunctions()));
@@ -34,6 +35,9 @@ export default function createViewPortDimension(getState) {
34
35
  const size = calculatePixelValue(length);
35
36
  return { offset, size };
36
37
  }
38
+ function isVisible({ offset, size }) {
39
+ return offset + size > 0 && offset < state.pixelSize;
40
+ }
37
41
  return state;
38
42
  }
39
43
  export const clamp = (value, min, max) => Math.max(min, Math.min(max, value));
@@ -0,0 +1,10 @@
1
+ import { JSX } from "solid-js";
2
+ import { TrackJSON } from "@tonejs/midi";
3
+ import { PianoRollProps } from "./PianoRoll";
4
+ export type MultiTrackPianoRollProps = Omit<PianoRollProps, "notes" | "onNoteChange" | "onInsertNote" | "onRemoveNote" | "condensed"> & {
5
+ tracks: TrackJSON[];
6
+ selectedTrack?: TrackJSON;
7
+ onSelectedTrackChange: (track?: TrackJSON) => void;
8
+ } & JSX.IntrinsicElements["div"];
9
+ declare const MultiTrackPianoRoll: (allProps: MultiTrackPianoRollProps) => JSX.Element;
10
+ export default MultiTrackPianoRoll;
@@ -1,3 +1,4 @@
1
1
  import { PianoRollProps } from "./PianoRoll";
2
2
  export declare const PianoRollContextProvider: import("solid-js/types/reactive/signal").ContextProviderComponent<PianoRollProps>;
3
3
  export declare const usePianoRollContext: () => PianoRollProps;
4
+ export declare const splitContextProps: (allProps: PianoRollProps) => [Pick<PianoRollProps, "position" | "condensed" | "zoom" | "onZoomChange" | "onPositionChange" | "notes" | "duration" | "gridDivision" | "ppq" | "snapToGrid" | "verticalPosition" | "verticalZoom" | "onInsertNote" | "onNoteChange" | "onRemoveNote" | "onVerticalPositionChange" | "onVerticalZoomChange">, Omit<PianoRollProps, "position" | "condensed" | "zoom" | "onZoomChange" | "onPositionChange" | "notes" | "duration" | "gridDivision" | "ppq" | "snapToGrid" | "verticalPosition" | "verticalZoom" | "onInsertNote" | "onNoteChange" | "onRemoveNote" | "onVerticalPositionChange" | "onVerticalZoomChange">];
@@ -1,3 +1,5 @@
1
+ import MultiTrackPianoRoll from "./MultiTrackPianoRoll";
1
2
  import PianoRoll from "./PianoRoll";
3
+ import useNotes from "./useNotes";
2
4
  import usePianoRoll from "./usePianoRoll";
3
- export { PianoRoll, usePianoRoll };
5
+ export { PianoRoll, MultiTrackPianoRoll, usePianoRoll, useNotes };
@@ -0,0 +1,9 @@
1
+ import { Note } from "./types";
2
+ declare const useNotes: () => {
3
+ notes: import("solid-js").Accessor<Note[]>;
4
+ onNotesChange: import("solid-js").Setter<Note[]>;
5
+ onNoteChange: (index: number, note: Note) => void;
6
+ onInsertNote: (note: Note) => number;
7
+ onRemoveNote: (index: number) => void;
8
+ };
9
+ export default useNotes;
@@ -1,5 +1,4 @@
1
1
  import { GridDivision } from "./PianoRoll";
2
- import { Note } from "./types";
3
2
  declare const usePianoRoll: () => {
4
3
  ppq: import("solid-js").Accessor<number>;
5
4
  onPpqChange: import("solid-js").Setter<number>;
@@ -15,11 +14,8 @@ declare const usePianoRoll: () => {
15
14
  onGridDivisionChange: import("solid-js").Setter<GridDivision>;
16
15
  snapToGrid: import("solid-js").Accessor<boolean>;
17
16
  onSnapToGridChange: import("solid-js").Setter<boolean>;
18
- notes: import("solid-js").Accessor<Note[]>;
19
- onNotesChange: import("solid-js").Setter<Note[]>;
20
- onNoteChange: (index: number, note: Note) => void;
21
- onInsertNote: (note: Note) => number;
22
- onRemoveNote: (index: number) => void;
17
+ condensed: import("solid-js").Accessor<boolean>;
18
+ onCondensedChange: import("solid-js").Setter<boolean>;
23
19
  duration: import("solid-js").Accessor<number>;
24
20
  onDurationChange: import("solid-js").Setter<number>;
25
21
  };
@@ -12,6 +12,10 @@ export declare const useViewPortDimension: (name: ViewPortDimensionName) => {
12
12
  };
13
13
  calculateVisibleRange: () => number;
14
14
  calculateMaxPosition: () => number;
15
+ isVisible: ({ offset, size }: {
16
+ offset: number;
17
+ size: number;
18
+ }) => boolean;
15
19
  position: number;
16
20
  range: number;
17
21
  pixelOffset: number;
@@ -19,6 +19,10 @@ export default function createViewPortDimension(getState: () => ViewPortDimensio
19
19
  };
20
20
  calculateVisibleRange: () => number;
21
21
  calculateMaxPosition: () => number;
22
+ isVisible: ({ offset, size }: {
23
+ offset: number;
24
+ size: number;
25
+ }) => boolean;
22
26
  position: number;
23
27
  range: number;
24
28
  pixelOffset: number;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.0.11",
2
+ "version": "0.0.13",
3
3
  "name": "solid-pianoroll",
4
4
  "description": "Pianoroll UI Control for Solid JS apps",
5
5
  "license": "MIT",