solid-pianoroll 0.0.2 → 0.0.3
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/cjs/index.js +471 -266
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +473 -268
- package/dist/esm/index.js.map +1 -1
- package/dist/source/HorizontalZoomControl.jsx +9 -0
- package/dist/source/PianoRoll.jsx +26 -261
- package/dist/source/PianoRollContext.jsx +48 -0
- package/dist/source/PianoRollGrid.jsx +60 -0
- package/dist/source/PianoRollKeys.jsx +29 -0
- package/dist/source/PianoRollNotes.jsx +86 -0
- package/dist/source/ScrollContainer.jsx +84 -0
- package/dist/source/VerticalZoomControl.jsx +12 -0
- package/dist/source/useBoundingClientRect.js +29 -0
- package/dist/types/HorizontalZoomControl.d.ts +2 -0
- package/dist/types/PianoRoll.d.ts +6 -3
- package/dist/types/PianoRollContext.d.ts +23 -0
- package/dist/types/PianoRollGrid.d.ts +2 -0
- package/dist/types/PianoRollKeys.d.ts +9 -0
- package/dist/types/PianoRollNotes.d.ts +5 -0
- package/dist/types/ScrollContainer.d.ts +5 -0
- package/dist/types/VerticalZoomControl.d.ts +2 -0
- package/dist/types/useBoundingClientRect.d.ts +3 -0
- package/dist/types/useViewPortScaler.d.ts +1 -0
- package/package.json +4 -1
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { createMemo, Index, Show } from "solid-js";
|
|
2
|
+
import { usePianoRollContext } from "./PianoRollContext";
|
|
3
|
+
import { keys } from "./PianoRollKeys";
|
|
4
|
+
const PianoRollGrid = () => {
|
|
5
|
+
const context = usePianoRollContext();
|
|
6
|
+
const gridArray = createMemo(() => {
|
|
7
|
+
const numberOfLines = context.duration / ((context.ppq * 4) / context.gridDivision);
|
|
8
|
+
return Array.from({ length: numberOfLines }).map((_, index) => ({
|
|
9
|
+
index,
|
|
10
|
+
tick: index * ((context.ppq * 4) / context.gridDivision),
|
|
11
|
+
}));
|
|
12
|
+
});
|
|
13
|
+
const visibleDimensions = createMemo(() => context.horizontalViewPort.getVirtualDimensions(context.position, context.duration / context.zoom));
|
|
14
|
+
return (<div class="PianoRoll-Grid-Container" style={{
|
|
15
|
+
position: "absolute",
|
|
16
|
+
width: `${context.clientRect.width}px`,
|
|
17
|
+
height: `${context.clientRect.height}px`,
|
|
18
|
+
}}>
|
|
19
|
+
<div class="PianoRoll-Grid" style={{
|
|
20
|
+
position: "relative",
|
|
21
|
+
width: `${context.clientRect.width}px`,
|
|
22
|
+
height: "100%",
|
|
23
|
+
}}>
|
|
24
|
+
<Index each={gridArray()}>
|
|
25
|
+
{(gridline) => {
|
|
26
|
+
const left = createMemo(() => context.horizontalViewPort.getScaledValue(gridline().tick));
|
|
27
|
+
return (<Show when={left() >= visibleDimensions().offset &&
|
|
28
|
+
left() <= visibleDimensions().offset + visibleDimensions().size}>
|
|
29
|
+
<div class="PianoRoll-Grid-Time" style={{
|
|
30
|
+
"z-index": 1,
|
|
31
|
+
position: "absolute",
|
|
32
|
+
"box-sizing": "border-box",
|
|
33
|
+
top: `0px`,
|
|
34
|
+
height: `100%`,
|
|
35
|
+
left: `${left()}px`,
|
|
36
|
+
width: `1px`,
|
|
37
|
+
"background-color": "gray",
|
|
38
|
+
}}></div>
|
|
39
|
+
</Show>);
|
|
40
|
+
}}
|
|
41
|
+
</Index>
|
|
42
|
+
<Index each={keys}>
|
|
43
|
+
{(key) => {
|
|
44
|
+
const virtualDimensions = createMemo(() => context.verticalViewPort.getVirtualDimensions(127 - key().number, 1));
|
|
45
|
+
return (<Show when={virtualDimensions().size > 0}>
|
|
46
|
+
<div class="PianoRoll-Grid-Key" style={{
|
|
47
|
+
position: "absolute",
|
|
48
|
+
top: `${virtualDimensions().offset}px`,
|
|
49
|
+
height: `${virtualDimensions().size}px`,
|
|
50
|
+
width: "100%",
|
|
51
|
+
"border-bottom": `0.5px black solid`,
|
|
52
|
+
"border-top": `0.5px black solid`,
|
|
53
|
+
}}></div>
|
|
54
|
+
</Show>);
|
|
55
|
+
}}
|
|
56
|
+
</Index>
|
|
57
|
+
</div>
|
|
58
|
+
</div>);
|
|
59
|
+
};
|
|
60
|
+
export default PianoRollGrid;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import styles from "./PianoRollKeys.module.css";
|
|
2
|
+
import { createMemo, Index, Show } from "solid-js";
|
|
3
|
+
import { usePianoRollContext } from "./PianoRollContext";
|
|
4
|
+
const PianoRollKeys = () => {
|
|
5
|
+
const context = usePianoRollContext();
|
|
6
|
+
return (<div class={styles.PianoRollKeys}>
|
|
7
|
+
<Index each={keys}>
|
|
8
|
+
{(key) => {
|
|
9
|
+
const virtualDimensions = createMemo(() => context.verticalViewPort.getVirtualDimensions(127 - key().number, 1));
|
|
10
|
+
return (<Show when={virtualDimensions().size > 0}>
|
|
11
|
+
<div class={styles["PianoRollKeys-Key"]} title={key().name} data-index={key().number % 12} style={{
|
|
12
|
+
top: `${virtualDimensions().offset}px`,
|
|
13
|
+
height: `${virtualDimensions().size}px`,
|
|
14
|
+
"background-color": key().isBlack ? "#000" : "#fff",
|
|
15
|
+
"border-width": `${!key().isBlack && !blackKeys.includes((key().number + 1) % 12) ? "0.1px" : 0} 1px ${!key().isBlack && !blackKeys.includes((key().number - 1) % 12) ? "0.1px" : 0} 0`,
|
|
16
|
+
}}></div>
|
|
17
|
+
</Show>);
|
|
18
|
+
}}
|
|
19
|
+
</Index>
|
|
20
|
+
</div>);
|
|
21
|
+
};
|
|
22
|
+
export const blackKeys = [1, 3, 6, 8, 10];
|
|
23
|
+
export const keyNames = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
|
|
24
|
+
export const keys = Array.from({ length: 128 }).map((_, index) => ({
|
|
25
|
+
number: index,
|
|
26
|
+
name: `${keyNames[index % 12]} ${Math.floor(index / 12) - 2}`,
|
|
27
|
+
isBlack: blackKeys.includes(index % 12),
|
|
28
|
+
}));
|
|
29
|
+
export default PianoRollKeys;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { createMemo, Index, Show } from "solid-js";
|
|
2
|
+
import { usePianoRollContext } from "./PianoRollContext";
|
|
3
|
+
const PianoRollNotes = (props) => {
|
|
4
|
+
const context = usePianoRollContext();
|
|
5
|
+
const gridDivisionTicks = createMemo(() => (context.ppq * 4) / context.gridDivision);
|
|
6
|
+
const snapValueToGridIfEnabled = (value, altKey) => context.snapToGrid && !altKey
|
|
7
|
+
? Math.round(value / gridDivisionTicks()) * gridDivisionTicks()
|
|
8
|
+
: value;
|
|
9
|
+
return (<div class="PianoRoll-Notes-Container" style={{
|
|
10
|
+
position: "absolute",
|
|
11
|
+
width: `${context.clientRect.width}px`,
|
|
12
|
+
height: `${context.clientRect.height}px`,
|
|
13
|
+
}}>
|
|
14
|
+
<div class="PianoRoll-Notes" ref={props.ref} style={{
|
|
15
|
+
position: "relative",
|
|
16
|
+
width: `${context.clientRect.width}px`,
|
|
17
|
+
height: "100%",
|
|
18
|
+
}}>
|
|
19
|
+
<Index each={context.notes}>
|
|
20
|
+
{(note, index) => {
|
|
21
|
+
const horizontalVirtualDimensions = createMemo(() => context.verticalViewPort.getVirtualDimensions(127 - note().midi, 1));
|
|
22
|
+
const verticalVirtualDimensions = createMemo(() => context.horizontalViewPort.getVirtualDimensions(note().ticks, note().durationTicks));
|
|
23
|
+
return (<Show when={!!horizontalVirtualDimensions().size && !!verticalVirtualDimensions().size}>
|
|
24
|
+
<div class="PianoRoll-Note" onMouseMove={(event) => {
|
|
25
|
+
if (context.isDragging)
|
|
26
|
+
return;
|
|
27
|
+
const relativeX = context.horizontalViewPort.getScaledValue(context.horizontalViewPort.getPosition(event.clientX));
|
|
28
|
+
const noteStartX = context.horizontalViewPort.getScaledValue(note().ticks);
|
|
29
|
+
const noteEndX = context.horizontalViewPort.getScaledValue(note().ticks + note().durationTicks);
|
|
30
|
+
context.onNoteDragModeChange(relativeX - noteStartX < 3
|
|
31
|
+
? "trimStart"
|
|
32
|
+
: noteEndX - relativeX < 3
|
|
33
|
+
? "trimEnd"
|
|
34
|
+
: "move");
|
|
35
|
+
}} onMouseDown={(event) => {
|
|
36
|
+
context.onIsDraggingChange(true);
|
|
37
|
+
const initialPosition = context.horizontalViewPort.getPosition(event.clientX);
|
|
38
|
+
const diffPosition = initialPosition - note().ticks;
|
|
39
|
+
const handleMouseMove = (mouseMoveEvent) => {
|
|
40
|
+
const ticks = snapValueToGridIfEnabled(Math.max(context.horizontalViewPort.getPosition(mouseMoveEvent.clientX) -
|
|
41
|
+
diffPosition, 0), mouseMoveEvent.altKey);
|
|
42
|
+
context.onNoteChange?.(index, {
|
|
43
|
+
...note(),
|
|
44
|
+
...(context.noteDragMode === "move" && {
|
|
45
|
+
midi: Math.round(127 - context.verticalViewPort.getPosition(mouseMoveEvent.clientY)),
|
|
46
|
+
}),
|
|
47
|
+
...((context.noteDragMode === "move" ||
|
|
48
|
+
context.noteDragMode === "trimStart") && {
|
|
49
|
+
ticks,
|
|
50
|
+
}),
|
|
51
|
+
...(context.noteDragMode === "trimStart" && {
|
|
52
|
+
durationTicks: note().durationTicks + note().ticks - ticks,
|
|
53
|
+
}),
|
|
54
|
+
...(context.noteDragMode === "trimEnd" && {
|
|
55
|
+
durationTicks: snapValueToGridIfEnabled(context.horizontalViewPort.getPosition(mouseMoveEvent.clientX) -
|
|
56
|
+
note().ticks, mouseMoveEvent.altKey),
|
|
57
|
+
}),
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
const handleMouseUp = () => {
|
|
61
|
+
context.onIsDraggingChange(false);
|
|
62
|
+
window.removeEventListener("mousemove", handleMouseMove);
|
|
63
|
+
window.removeEventListener("mouseup", handleMouseUp);
|
|
64
|
+
};
|
|
65
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
66
|
+
window.addEventListener("mouseup", handleMouseUp);
|
|
67
|
+
}} style={{
|
|
68
|
+
"z-index": 1,
|
|
69
|
+
position: "absolute",
|
|
70
|
+
"box-sizing": "border-box",
|
|
71
|
+
top: `${horizontalVirtualDimensions().offset}px`,
|
|
72
|
+
height: `${horizontalVirtualDimensions().size}px`,
|
|
73
|
+
left: `${verticalVirtualDimensions().offset}px`,
|
|
74
|
+
width: `${verticalVirtualDimensions().size}px`,
|
|
75
|
+
"border-width": "0.5px",
|
|
76
|
+
"border-style": "solid",
|
|
77
|
+
"background-color": `rgba(255,0,0, ${(128 + note().velocity) / 256})`,
|
|
78
|
+
"border-color": "#a00",
|
|
79
|
+
}}></div>
|
|
80
|
+
</Show>);
|
|
81
|
+
}}
|
|
82
|
+
</Index>
|
|
83
|
+
</div>
|
|
84
|
+
</div>);
|
|
85
|
+
};
|
|
86
|
+
export default PianoRollNotes;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { createEffect } from "solid-js";
|
|
2
|
+
import { clamp } from "./helpers";
|
|
3
|
+
import { usePianoRollContext } from "./PianoRollContext";
|
|
4
|
+
const ScrollContainer = (props) => {
|
|
5
|
+
let scrollContentRef;
|
|
6
|
+
const context = usePianoRollContext();
|
|
7
|
+
const forwardEventToNote = (event) => {
|
|
8
|
+
const x = "clientX" in event ? event.clientX : event.touches[0]?.clientX;
|
|
9
|
+
const y = "clientY" in event ? event.clientY : event.touches[0]?.clientY;
|
|
10
|
+
const elementUnderMouse = [...(context.notesContainer?.querySelectorAll?.("div") ?? [])].find((element) => {
|
|
11
|
+
const rect = element.getBoundingClientRect();
|
|
12
|
+
return (x >= rect.left &&
|
|
13
|
+
rect.left + rect.width > x &&
|
|
14
|
+
y >= rect.top &&
|
|
15
|
+
rect.top + rect.height > y);
|
|
16
|
+
});
|
|
17
|
+
if (elementUnderMouse) {
|
|
18
|
+
return elementUnderMouse.dispatchEvent(new MouseEvent(event.type, event));
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
const handleScroll = (event) => {
|
|
22
|
+
event.preventDefault();
|
|
23
|
+
if (didUpdateScroll) {
|
|
24
|
+
didUpdateScroll = false;
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const maxVerticalPosition = 128 - 128 / context.verticalZoom;
|
|
28
|
+
const maxPosition = context.duration - context.duration / context.zoom;
|
|
29
|
+
const { width, height } = context.clientRect;
|
|
30
|
+
const { scrollTop, scrollLeft, scrollWidth, scrollHeight } = event.currentTarget;
|
|
31
|
+
const scrollTopAmount = scrollTop / (scrollHeight - height);
|
|
32
|
+
const scrollLeftAmount = scrollLeft / (scrollWidth - width);
|
|
33
|
+
context.onVerticalPositionChange?.(maxVerticalPosition * scrollTopAmount);
|
|
34
|
+
context.onPositionChange?.(maxPosition * scrollLeftAmount);
|
|
35
|
+
};
|
|
36
|
+
let didUpdateScroll = false;
|
|
37
|
+
createEffect(() => {
|
|
38
|
+
const maxVerticalPosition = 128 - 128 / context.verticalZoom;
|
|
39
|
+
const maxPosition = context.duration - context.duration / context.zoom;
|
|
40
|
+
const scrollTopAmount = maxVerticalPosition > 0 ? context.verticalPosition / maxVerticalPosition : 0;
|
|
41
|
+
const scrollLeftAmount = maxPosition > 0 ? context.position / maxPosition : 0;
|
|
42
|
+
const { height, width } = context.clientRect;
|
|
43
|
+
if (!scrollContentRef?.parentElement)
|
|
44
|
+
return;
|
|
45
|
+
const scrollDivHeight = clamp(context.verticalZoom * height, height, 10000);
|
|
46
|
+
const scrollTop = scrollTopAmount * (scrollDivHeight - height);
|
|
47
|
+
const scrollDivWidth = clamp(context.zoom * width, width, 10000);
|
|
48
|
+
const scrollLeft = scrollLeftAmount * (scrollDivWidth - width);
|
|
49
|
+
didUpdateScroll = true;
|
|
50
|
+
scrollContentRef.style.height = `${scrollDivHeight}px`;
|
|
51
|
+
scrollContentRef.style.width = `${scrollDivWidth}px`;
|
|
52
|
+
scrollContentRef.parentElement.scrollTo({
|
|
53
|
+
left: scrollLeft,
|
|
54
|
+
top: scrollTop,
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
return (<div ref={props.ref} class="PianoRoll-Vertical-Scroller" style={{
|
|
58
|
+
flex: 1,
|
|
59
|
+
...(context.noteDragMode && {
|
|
60
|
+
cursor: context.noteDragMode === "trimStart"
|
|
61
|
+
? "w-resize"
|
|
62
|
+
: context.noteDragMode === "trimEnd"
|
|
63
|
+
? "e-resize"
|
|
64
|
+
: "pointer",
|
|
65
|
+
}),
|
|
66
|
+
//"box-sizing": "border-box",
|
|
67
|
+
"z-index": 1,
|
|
68
|
+
overflow: "scroll",
|
|
69
|
+
"pointer-events": "auto",
|
|
70
|
+
}} onScroll={handleScroll} onMouseDown={forwardEventToNote} onMouseMove={(event) => {
|
|
71
|
+
if (forwardEventToNote(event))
|
|
72
|
+
return;
|
|
73
|
+
if (context.isDragging)
|
|
74
|
+
return;
|
|
75
|
+
context.onNoteDragModeChange(undefined);
|
|
76
|
+
}} onClick={forwardEventToNote} onDblClick={(event) => {
|
|
77
|
+
if (!forwardEventToNote(event)) {
|
|
78
|
+
//TODO create new note with current gutter length
|
|
79
|
+
}
|
|
80
|
+
}} onMouseUp={forwardEventToNote} onTouchStart={forwardEventToNote} onTouchMove={forwardEventToNote} onTouchEnd={forwardEventToNote} onTouchCancel={forwardEventToNote} onDragStart={forwardEventToNote} onDrag={forwardEventToNote} onDragEnd={forwardEventToNote}>
|
|
81
|
+
<div ref={scrollContentRef}></div>
|
|
82
|
+
</div>);
|
|
83
|
+
};
|
|
84
|
+
export default ScrollContainer;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { usePianoRollContext } from "./PianoRollContext";
|
|
2
|
+
const VerticalZoomControl = () => {
|
|
3
|
+
const context = usePianoRollContext();
|
|
4
|
+
return (<input value={context.verticalZoom} onInput={(event) => context.onVerticalZoomChange?.(event.currentTarget.valueAsNumber)} type="range" min="1" max="11" step={0.01} {...{ orient: "vertical" }} style={{
|
|
5
|
+
width: "16px",
|
|
6
|
+
...{
|
|
7
|
+
"writing-mode": "bt-lr" /* IE */,
|
|
8
|
+
"-webkit-appearance": "slider-vertical" /* WebKit */,
|
|
9
|
+
},
|
|
10
|
+
}}/>);
|
|
11
|
+
};
|
|
12
|
+
export default VerticalZoomControl;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createEffect, createSignal } from "solid-js";
|
|
2
|
+
const defaultRect = {
|
|
3
|
+
left: 0,
|
|
4
|
+
width: 0,
|
|
5
|
+
top: 0,
|
|
6
|
+
height: 0,
|
|
7
|
+
bottom: 0,
|
|
8
|
+
right: 0,
|
|
9
|
+
x: 0,
|
|
10
|
+
y: 0,
|
|
11
|
+
};
|
|
12
|
+
export default function useBoundingClientRect(containerRef) {
|
|
13
|
+
const [boundingClientRect, setBoundingClientRect] = createSignal(defaultRect);
|
|
14
|
+
createEffect(() => {
|
|
15
|
+
const container = containerRef();
|
|
16
|
+
if (!container)
|
|
17
|
+
return;
|
|
18
|
+
const updateBoundingClientRect = () => {
|
|
19
|
+
setBoundingClientRect(container.getBoundingClientRect() ?? defaultRect);
|
|
20
|
+
};
|
|
21
|
+
const resizeObserver = new ResizeObserver(updateBoundingClientRect);
|
|
22
|
+
resizeObserver.observe(container);
|
|
23
|
+
updateBoundingClientRect();
|
|
24
|
+
return () => {
|
|
25
|
+
resizeObserver.disconnect();
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
return boundingClientRect;
|
|
29
|
+
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { Midi } from "@tonejs/midi";
|
|
2
2
|
import { JSX } from "solid-js";
|
|
3
3
|
type Note = Pick<ReturnType<Midi["tracks"][number]["notes"][number]["toJSON"]>, "durationTicks" | "midi" | "ticks" | "velocity">;
|
|
4
|
-
type
|
|
4
|
+
export type GridDivision = 1 | 2 | 4 | 8 | 16 | 32 | 64;
|
|
5
|
+
export type PianoRollProps = {
|
|
5
6
|
ppq: number;
|
|
6
7
|
notes: Note[];
|
|
8
|
+
gridDivision: GridDivision;
|
|
9
|
+
snapToGrid: boolean;
|
|
7
10
|
verticalPosition: number;
|
|
8
11
|
verticalZoom: number;
|
|
9
12
|
position: number;
|
|
@@ -14,6 +17,6 @@ type PianoRollProps = {
|
|
|
14
17
|
onZoomChange?: (zoom: number) => void;
|
|
15
18
|
onPositionChange?: (zoom: number) => void;
|
|
16
19
|
onNoteChange?: (index: number, note: Note) => void;
|
|
17
|
-
}
|
|
18
|
-
declare const PianoRoll: (allProps: PianoRollProps) => JSX.Element;
|
|
20
|
+
};
|
|
21
|
+
declare const PianoRoll: (allProps: PianoRollProps & JSX.IntrinsicElements["div"]) => JSX.Element;
|
|
19
22
|
export default PianoRoll;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { JSX } from "solid-js";
|
|
2
|
+
import { PianoRollProps } from "./PianoRoll";
|
|
3
|
+
import { ClientRect } from "./useBoundingClientRect";
|
|
4
|
+
import { ViewPortScaler } from "./useViewPortScaler";
|
|
5
|
+
export type NoteDragMode = "trimStart" | "move" | "trimEnd" | undefined;
|
|
6
|
+
type PianoRollContext = {
|
|
7
|
+
horizontalViewPort: ViewPortScaler;
|
|
8
|
+
verticalViewPort: ViewPortScaler;
|
|
9
|
+
clientRect: ClientRect;
|
|
10
|
+
notesContainer?: HTMLDivElement;
|
|
11
|
+
isDragging: boolean;
|
|
12
|
+
onIsDraggingChange: (isDragging: boolean) => void;
|
|
13
|
+
noteDragMode: NoteDragMode;
|
|
14
|
+
onNoteDragModeChange: (isDragging: NoteDragMode) => void;
|
|
15
|
+
} & PianoRollProps;
|
|
16
|
+
declare const PianoRollContext: import("solid-js").Context<PianoRollContext>;
|
|
17
|
+
export declare const PianoRollContextProvider: (props: {
|
|
18
|
+
scrollContainer?: HTMLDivElement;
|
|
19
|
+
notesContainer?: HTMLDivElement;
|
|
20
|
+
children: JSX.Element;
|
|
21
|
+
} & PianoRollProps) => JSX.Element;
|
|
22
|
+
export declare const usePianoRollContext: () => PianoRollContext;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
declare const PianoRollKeys: () => import("solid-js").JSX.Element;
|
|
2
|
+
export declare const blackKeys: number[];
|
|
3
|
+
export declare const keyNames: string[];
|
|
4
|
+
export declare const keys: {
|
|
5
|
+
number: number;
|
|
6
|
+
name: string;
|
|
7
|
+
isBlack: boolean;
|
|
8
|
+
}[];
|
|
9
|
+
export default PianoRollKeys;
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.0.
|
|
2
|
+
"version": "0.0.3",
|
|
3
3
|
"name": "solid-pianoroll",
|
|
4
4
|
"description": "Pianoroll UI Control for Solid JS apps",
|
|
5
5
|
"license": "MIT",
|
|
@@ -50,12 +50,15 @@
|
|
|
50
50
|
"solid-js": ">=1.0.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
+
"postcss": "^8.4.20",
|
|
53
54
|
"prettier": "2.8.1",
|
|
54
55
|
"rollup": "^3.7.2",
|
|
56
|
+
"rollup-plugin-postcss": "^4.0.2",
|
|
55
57
|
"rollup-preset-solid": "^2.0.1",
|
|
56
58
|
"solid-js": "^1.6.4",
|
|
57
59
|
"taze": "^0.8.4",
|
|
58
60
|
"typescript": "^4.9.4",
|
|
61
|
+
"typescript-plugin-css-modules": "^4.1.1",
|
|
59
62
|
"vite": "^4.0.0",
|
|
60
63
|
"vite-plugin-solid": "^2.5.0"
|
|
61
64
|
},
|