solid-pianoroll 0.0.13 → 0.0.15
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 +451 -412
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +453 -414
- package/dist/esm/index.js.map +1 -1
- package/dist/source/PianoRoll.jsx +19 -3
- package/dist/source/PianoRollContext.jsx +5 -2
- package/dist/source/PianoRollGrid.jsx +25 -5
- package/dist/source/PianoRollNotes.jsx +117 -81
- package/dist/source/PianoRollTrackList.jsx +28 -0
- package/dist/source/PlayHead.jsx +47 -0
- package/dist/source/index.jsx +2 -2
- package/dist/source/usePianoRoll.js +4 -4
- package/dist/source/viewport/createViewPortDimension.js +1 -0
- package/dist/types/PianoRoll.d.ts +12 -8
- package/dist/types/PianoRollContext.d.ts +2 -1
- package/dist/types/PianoRollTrackList.d.ts +2 -0
- package/dist/types/PlayHead.d.ts +8 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/types.d.ts +4 -0
- package/dist/types/usePianoRoll.d.ts +2 -2
- package/dist/types/viewport/ScrollZoomViewPort.d.ts +1 -0
- package/dist/types/viewport/createViewPortDimension.d.ts +1 -0
- package/package.json +3 -2
- package/dist/source/MultiTrackPianoRoll.jsx +0 -136
- package/dist/types/MultiTrackPianoRoll.d.ts +0 -10
package/dist/esm/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createContext, splitProps, useContext, createEffect, createMemo, createSignal,
|
|
1
|
+
import { createComponent, insert, effect, classList, setAttribute, className, template, delegateEvents, use, memo, spread, mergeProps } from 'solid-js/web';
|
|
2
|
+
import { createContext, splitProps, useContext, createEffect, createMemo, Index, Show, createSignal, batch, For, mergeProps as mergeProps$1 } from 'solid-js';
|
|
3
3
|
import { createStore } from 'solid-js/store';
|
|
4
4
|
|
|
5
5
|
function styleInject(css, ref) {
|
|
@@ -27,9 +27,9 @@ function styleInject(css, ref) {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
var css_248z$
|
|
31
|
-
var styles$
|
|
32
|
-
styleInject(css_248z$
|
|
30
|
+
var css_248z$4 = ".PianoRoll-module_PianoRoll__rkRYx {\n box-sizing: border-box;\n display: flex;\n overflow: hidden;\n flex-direction: column;\n}\n\n.PianoRoll-module_PianoRollContainer__Oyxr7 {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: row;\n}\n";
|
|
31
|
+
var styles$4 = {"PianoRoll":"PianoRoll-module_PianoRoll__rkRYx","PianoRollContainer":"PianoRoll-module_PianoRollContainer__Oyxr7"};
|
|
32
|
+
styleInject(css_248z$4);
|
|
33
33
|
|
|
34
34
|
const PianoRollContext = createContext();
|
|
35
35
|
const PianoRollContextProvider = PianoRollContext.Provider;
|
|
@@ -38,34 +38,16 @@ const usePianoRollContext = () => {
|
|
|
38
38
|
if (!context) throw new Error("No PianoRollContext found");
|
|
39
39
|
return context;
|
|
40
40
|
};
|
|
41
|
-
const splitContextProps = allProps => splitProps(allProps, ["
|
|
41
|
+
const splitContextProps = allProps => splitProps(allProps, ["mode", "duration", "gridDivision", "tracks", "position", "ppq", "snapToGrid", "verticalPosition", "verticalZoom", "zoom", "onInsertNote", "onNoteChange", "onPositionChange", "onRemoveNote", "onVerticalPositionChange", "onVerticalZoomChange", "onZoomChange", "showAllTracks", "selectedTrackIndex", "onSelectedTrackIndexChange"]);
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return (() => {
|
|
47
|
-
const _el$ = _tmpl$$7.cloneNode(true);
|
|
48
|
-
spread(_el$, mergeProps(props, {
|
|
49
|
-
get value() {
|
|
50
|
-
return context.zoom;
|
|
51
|
-
},
|
|
52
|
-
"onInput": event => context.onZoomChange?.(event.currentTarget.valueAsNumber),
|
|
53
|
-
"type": "range",
|
|
54
|
-
get style() {
|
|
55
|
-
return {
|
|
56
|
-
"margin-left": "50px",
|
|
57
|
-
"margin-right": "16px",
|
|
58
|
-
...(typeof props.style === "object" && props.style)
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
}), false, false);
|
|
62
|
-
return _el$;
|
|
63
|
-
})();
|
|
64
|
-
};
|
|
43
|
+
var css_248z$3 = ".PianoRollKeys-module_PianoRollKeys__5vnQ0 {\n position: relative;\n height: 100%;\n width: 50px;\n}\n\n.PianoRollKeys-module_Key__jybNC {\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}\n\n.PianoRollKeys-module_black__7rncB {\n background: black;\n}\n\n.PianoRollKeys-module_white__fR2Lm {\n background: white;\n}\n\n.PianoRollKeys-module_whiteAndNextIsWhite__PN1O8 {\n border-top-width: 0.1px;\n}\n\n.PianoRollKeys-module_whiteAndPreviousIsWhite__-fP3q {\n border-bottom-width: 0.1px;\n}\n";
|
|
44
|
+
var styles$3 = {"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"};
|
|
45
|
+
styleInject(css_248z$3);
|
|
65
46
|
|
|
66
47
|
function createViewPortDimension(getState) {
|
|
67
48
|
const getStateWithFunctions = () => ({
|
|
68
49
|
...getState(),
|
|
50
|
+
calculatePixelOffset,
|
|
69
51
|
calculatePixelValue,
|
|
70
52
|
calculatePosition,
|
|
71
53
|
calculatePixelDimensions,
|
|
@@ -134,11 +116,70 @@ const useViewPortDimension = name => {
|
|
|
134
116
|
return viewPort;
|
|
135
117
|
};
|
|
136
118
|
|
|
119
|
+
const _tmpl$$8 = /*#__PURE__*/template(`<div></div>`, 2);
|
|
120
|
+
const PianoRollKeys = () => {
|
|
121
|
+
const viewPort = createMemo(() => useViewPortDimension("vertical"));
|
|
122
|
+
return (() => {
|
|
123
|
+
const _el$ = _tmpl$$8.cloneNode(true);
|
|
124
|
+
insert(_el$, createComponent(Index, {
|
|
125
|
+
each: keys,
|
|
126
|
+
children: key => {
|
|
127
|
+
const virtualDimensions = createMemo(() => viewPort().calculatePixelDimensions(127 - key().number, 1));
|
|
128
|
+
return createComponent(Show, {
|
|
129
|
+
get when() {
|
|
130
|
+
return virtualDimensions().size > 0;
|
|
131
|
+
},
|
|
132
|
+
get children() {
|
|
133
|
+
const _el$2 = _tmpl$$8.cloneNode(true);
|
|
134
|
+
effect(_p$ => {
|
|
135
|
+
const _v$ = {
|
|
136
|
+
[styles$3["Key"]]: true,
|
|
137
|
+
[styles$3["black"]]: key().isBlack,
|
|
138
|
+
[styles$3["white"]]: !key().isBlack,
|
|
139
|
+
[styles$3["whiteAndNextIsWhite"]]: !key().isBlack && !blackKeys.includes((key().number + 1) % 12),
|
|
140
|
+
[styles$3["whiteAndPreviousIsWhite"]]: !key().isBlack && !blackKeys.includes((key().number - 1) % 12)
|
|
141
|
+
},
|
|
142
|
+
_v$2 = key().name,
|
|
143
|
+
_v$3 = key().number % 12,
|
|
144
|
+
_v$4 = `${virtualDimensions().offset}px`,
|
|
145
|
+
_v$5 = `${virtualDimensions().size}px`;
|
|
146
|
+
_p$._v$ = classList(_el$2, _v$, _p$._v$);
|
|
147
|
+
_v$2 !== _p$._v$2 && setAttribute(_el$2, "title", _p$._v$2 = _v$2);
|
|
148
|
+
_v$3 !== _p$._v$3 && setAttribute(_el$2, "data-index", _p$._v$3 = _v$3);
|
|
149
|
+
_v$4 !== _p$._v$4 && _el$2.style.setProperty("top", _p$._v$4 = _v$4);
|
|
150
|
+
_v$5 !== _p$._v$5 && _el$2.style.setProperty("height", _p$._v$5 = _v$5);
|
|
151
|
+
return _p$;
|
|
152
|
+
}, {
|
|
153
|
+
_v$: undefined,
|
|
154
|
+
_v$2: undefined,
|
|
155
|
+
_v$3: undefined,
|
|
156
|
+
_v$4: undefined,
|
|
157
|
+
_v$5: undefined
|
|
158
|
+
});
|
|
159
|
+
return _el$2;
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}));
|
|
164
|
+
effect(() => className(_el$, styles$3.PianoRollKeys));
|
|
165
|
+
return _el$;
|
|
166
|
+
})();
|
|
167
|
+
};
|
|
168
|
+
const blackKeys = [1, 3, 6, 8, 10];
|
|
169
|
+
const keyNames = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
|
|
170
|
+
const keys = Array.from({
|
|
171
|
+
length: 128
|
|
172
|
+
}).map((_, index) => ({
|
|
173
|
+
number: index,
|
|
174
|
+
name: `${keyNames[index % 12]} ${Math.floor(index / 12) - 2}`,
|
|
175
|
+
isBlack: blackKeys.includes(index % 12)
|
|
176
|
+
}));
|
|
177
|
+
|
|
137
178
|
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}";
|
|
138
179
|
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
180
|
styleInject(css_248z$2);
|
|
140
181
|
|
|
141
|
-
const _tmpl$$
|
|
182
|
+
const _tmpl$$7 = /*#__PURE__*/template(`<div></div>`, 2);
|
|
142
183
|
const PianoRollNotes = props => {
|
|
143
184
|
const context = usePianoRollContext();
|
|
144
185
|
const verticalViewPort = createMemo(() => useViewPortDimension("vertical"));
|
|
@@ -147,10 +188,11 @@ const PianoRollNotes = props => {
|
|
|
147
188
|
const snapValueToGridIfEnabled = (value, altKey) => context.snapToGrid && !altKey ? Math.round(value / gridDivisionTicks()) * gridDivisionTicks() : value;
|
|
148
189
|
const insertOrUpdateNote = event => {
|
|
149
190
|
const position = horizontalViewPort().calculatePosition(event.clientX);
|
|
150
|
-
const
|
|
191
|
+
const existingNote = currentNote();
|
|
192
|
+
const midi = context.mode === "keys" ? 127 - Math.floor(verticalViewPort().calculatePosition(event.clientY)) : existingNote?.midi ?? 60;
|
|
193
|
+
const targetTrackIndex = context.mode === "tracks" ? Math.floor(verticalViewPort().calculatePosition(event.clientY)) : context.selectedTrackIndex ?? 0;
|
|
151
194
|
const eventPositionTicks = Math.floor(position / gridDivisionTicks()) * gridDivisionTicks();
|
|
152
195
|
const velocity = 127;
|
|
153
|
-
const existingNote = newNote();
|
|
154
196
|
const ticks = existingNote?.ticks ?? eventPositionTicks;
|
|
155
197
|
const durationTicks = existingNote?.ticks ? eventPositionTicks - existingNote?.ticks : gridDivisionTicks();
|
|
156
198
|
const note = {
|
|
@@ -160,25 +202,26 @@ const PianoRollNotes = props => {
|
|
|
160
202
|
velocity
|
|
161
203
|
};
|
|
162
204
|
if (existingNote) {
|
|
163
|
-
context.onNoteChange?.(
|
|
164
|
-
return
|
|
205
|
+
context.onNoteChange?.(currentNoteTrackIndex(), currentNoteIndex(), note);
|
|
206
|
+
return currentNoteIndex();
|
|
165
207
|
} else {
|
|
166
|
-
return context.onInsertNote?.(note) ?? -1;
|
|
208
|
+
return context.onInsertNote?.(targetTrackIndex, note) ?? -1;
|
|
167
209
|
}
|
|
168
210
|
};
|
|
169
211
|
const [isDragging, setIsDragging] = createSignal(false);
|
|
170
212
|
const [noteDragMode, setNoteDragMode] = createSignal();
|
|
171
|
-
const [
|
|
213
|
+
const [currentNoteIndex, setCurrentNoteIndex] = createSignal(-1);
|
|
214
|
+
const [currentNoteTrackIndex, setCurrentNoteTrackIndex] = createSignal(-1);
|
|
172
215
|
const [isMouseDown, setIsMouseDown] = createSignal(false);
|
|
173
|
-
const
|
|
216
|
+
const currentNote = createMemo(() => context.tracks[currentNoteTrackIndex()]?.notes[currentNoteIndex()]);
|
|
174
217
|
const getClasses = noteDragMode => {
|
|
175
218
|
return noteDragMode ? [styles$2.Note, styles$2[noteDragMode]] : [styles$2.Note];
|
|
176
219
|
};
|
|
177
220
|
return (() => {
|
|
178
|
-
const _el$ = _tmpl$$
|
|
221
|
+
const _el$ = _tmpl$$7.cloneNode(true);
|
|
179
222
|
_el$.$$click = event => {
|
|
180
|
-
if (
|
|
181
|
-
|
|
223
|
+
if (currentNote()) {
|
|
224
|
+
setCurrentNoteIndex(-1);
|
|
182
225
|
return;
|
|
183
226
|
}
|
|
184
227
|
if (!event.altKey) return;
|
|
@@ -199,94 +242,133 @@ const PianoRollNotes = props => {
|
|
|
199
242
|
return;
|
|
200
243
|
}
|
|
201
244
|
const index = insertOrUpdateNote(event);
|
|
202
|
-
|
|
245
|
+
setCurrentNoteIndex(index);
|
|
203
246
|
};
|
|
204
247
|
_el$.$$mousedown = event => {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
248
|
+
batch(() => {
|
|
249
|
+
setIsMouseDown(true);
|
|
250
|
+
const index = insertOrUpdateNote(event);
|
|
251
|
+
setCurrentNoteTrackIndex(context.selectedTrackIndex ?? 0);
|
|
252
|
+
setCurrentNoteIndex(index);
|
|
253
|
+
});
|
|
209
254
|
};
|
|
210
255
|
const _ref$ = props.ref;
|
|
211
256
|
typeof _ref$ === "function" ? use(_ref$, _el$) : props.ref = _el$;
|
|
212
|
-
insert(_el$, createComponent(
|
|
257
|
+
insert(_el$, createComponent(For, {
|
|
213
258
|
get each() {
|
|
214
|
-
return context.
|
|
259
|
+
return context.tracks;
|
|
215
260
|
},
|
|
216
|
-
children: (
|
|
217
|
-
const verticalVirtualDimensions = createMemo(() => verticalViewPort().calculatePixelDimensions(127 - note().midi, 1));
|
|
218
|
-
const horizontalDimensions = createMemo(() => horizontalViewPort().calculatePixelDimensions(note().ticks, note().durationTicks));
|
|
261
|
+
children: (track, trackIndex) => {
|
|
219
262
|
return createComponent(Show, {
|
|
220
263
|
get when() {
|
|
221
|
-
return
|
|
264
|
+
return trackIndex() === context.selectedTrackIndex || context.showAllTracks || context.mode === "tracks";
|
|
222
265
|
},
|
|
223
266
|
get children() {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
267
|
+
return createComponent(For, {
|
|
268
|
+
get each() {
|
|
269
|
+
return track.notes;
|
|
270
|
+
},
|
|
271
|
+
children: (note, noteIndex) => {
|
|
272
|
+
const verticalVirtualDimensions = createMemo(() => verticalViewPort().calculatePixelDimensions(context.mode === "keys" ? 127 - note.midi : trackIndex(), 1));
|
|
273
|
+
const horizontalDimensions = createMemo(() => horizontalViewPort().calculatePixelDimensions(note.ticks, note.durationTicks));
|
|
274
|
+
return createComponent(Show, {
|
|
275
|
+
get when() {
|
|
276
|
+
return memo(() => !!verticalViewPort().isVisible(verticalVirtualDimensions()))() && horizontalViewPort().isVisible(horizontalDimensions());
|
|
277
|
+
},
|
|
278
|
+
get children() {
|
|
279
|
+
const _el$2 = _tmpl$$7.cloneNode(true);
|
|
280
|
+
_el$2.$$mousedown = event => {
|
|
281
|
+
event.stopPropagation();
|
|
282
|
+
setIsDragging(true);
|
|
283
|
+
setCurrentNoteIndex(noteIndex());
|
|
284
|
+
setCurrentNoteTrackIndex(trackIndex());
|
|
285
|
+
const initialPosition = horizontalViewPort().calculatePosition(event.clientX);
|
|
286
|
+
const diffPosition = initialPosition - note.ticks;
|
|
287
|
+
const handleMouseMove = mouseMoveEvent => {
|
|
288
|
+
const note = currentNote();
|
|
289
|
+
if (!note) return;
|
|
290
|
+
const ticks = snapValueToGridIfEnabled(Math.max(horizontalViewPort().calculatePosition(mouseMoveEvent.clientX) - diffPosition, 0), mouseMoveEvent.altKey);
|
|
291
|
+
const updatedNote = {
|
|
292
|
+
...note,
|
|
293
|
+
...(noteDragMode() === "move" && context.mode === "keys" && {
|
|
294
|
+
midi: Math.round(127 - verticalViewPort().calculatePosition(mouseMoveEvent.clientY))
|
|
295
|
+
}),
|
|
296
|
+
...((noteDragMode() === "move" || noteDragMode() === "trimStart") && {
|
|
297
|
+
ticks
|
|
298
|
+
}),
|
|
299
|
+
...(noteDragMode() === "trimStart" && {
|
|
300
|
+
durationTicks: note.durationTicks + note.ticks - ticks
|
|
301
|
+
}),
|
|
302
|
+
...(noteDragMode() === "trimEnd" && {
|
|
303
|
+
durationTicks: snapValueToGridIfEnabled(horizontalViewPort().calculatePosition(mouseMoveEvent.clientX) - note.ticks, mouseMoveEvent.altKey)
|
|
304
|
+
})
|
|
305
|
+
};
|
|
306
|
+
const previousTrackIndex = currentNoteTrackIndex();
|
|
307
|
+
const previousNoteIndex = currentNoteIndex();
|
|
308
|
+
const targetTrackIndex = context.mode === "tracks" ? Math.floor(verticalViewPort().calculatePosition(mouseMoveEvent.clientY)) : previousTrackIndex;
|
|
309
|
+
if (targetTrackIndex === previousTrackIndex) {
|
|
310
|
+
context.onNoteChange?.(previousTrackIndex, previousNoteIndex, updatedNote);
|
|
311
|
+
} else {
|
|
312
|
+
batch(() => {
|
|
313
|
+
if (context.onInsertNote) {
|
|
314
|
+
context.onRemoveNote?.(previousTrackIndex, previousNoteIndex);
|
|
315
|
+
const newNoteIndex = context.onInsertNote(targetTrackIndex, updatedNote);
|
|
316
|
+
setCurrentNoteTrackIndex(targetTrackIndex);
|
|
317
|
+
setCurrentNoteIndex(newNoteIndex);
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
const handleMouseUp = () => {
|
|
323
|
+
setIsDragging(false);
|
|
324
|
+
setCurrentNoteIndex(-1);
|
|
325
|
+
setCurrentNoteTrackIndex(-1);
|
|
326
|
+
window.removeEventListener("mousemove", handleMouseMove);
|
|
327
|
+
window.removeEventListener("mouseup", handleMouseUp);
|
|
328
|
+
};
|
|
329
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
330
|
+
window.addEventListener("mouseup", handleMouseUp);
|
|
331
|
+
};
|
|
332
|
+
_el$2.$$dblclick = event => {
|
|
333
|
+
event.stopPropagation();
|
|
334
|
+
context.onRemoveNote?.(trackIndex(), noteIndex());
|
|
335
|
+
};
|
|
336
|
+
_el$2.$$mousemove = event => {
|
|
337
|
+
if (isDragging()) return;
|
|
338
|
+
event.stopPropagation();
|
|
339
|
+
const relativeX = horizontalViewPort().calculatePixelValue(horizontalViewPort().calculatePosition(event.clientX));
|
|
340
|
+
const noteStartX = horizontalViewPort().calculatePixelValue(note.ticks);
|
|
341
|
+
const noteEndX = horizontalViewPort().calculatePixelValue(note.ticks + note.durationTicks);
|
|
342
|
+
setNoteDragMode(relativeX - noteStartX < 3 ? "trimStart" : noteEndX - relativeX < 3 ? "trimEnd" : "move");
|
|
343
|
+
};
|
|
344
|
+
setAttribute(_el$2, "draggable", false);
|
|
345
|
+
effect(_p$ => {
|
|
346
|
+
const _v$ = getClasses(noteDragMode()).join(" "),
|
|
347
|
+
_v$2 = `rgba(255,0,0, ${(128 + note.velocity) / 256})`,
|
|
348
|
+
_v$3 = `${verticalVirtualDimensions().offset}px`,
|
|
349
|
+
_v$4 = `${verticalVirtualDimensions().size}px`,
|
|
350
|
+
_v$5 = `${horizontalDimensions().offset}px`,
|
|
351
|
+
_v$6 = `${horizontalDimensions().size}px`;
|
|
352
|
+
_v$ !== _p$._v$ && className(_el$2, _p$._v$ = _v$);
|
|
353
|
+
_v$2 !== _p$._v$2 && _el$2.style.setProperty("background-color", _p$._v$2 = _v$2);
|
|
354
|
+
_v$3 !== _p$._v$3 && _el$2.style.setProperty("top", _p$._v$3 = _v$3);
|
|
355
|
+
_v$4 !== _p$._v$4 && _el$2.style.setProperty("height", _p$._v$4 = _v$4);
|
|
356
|
+
_v$5 !== _p$._v$5 && _el$2.style.setProperty("left", _p$._v$5 = _v$5);
|
|
357
|
+
_v$6 !== _p$._v$6 && _el$2.style.setProperty("width", _p$._v$6 = _v$6);
|
|
358
|
+
return _p$;
|
|
359
|
+
}, {
|
|
360
|
+
_v$: undefined,
|
|
361
|
+
_v$2: undefined,
|
|
362
|
+
_v$3: undefined,
|
|
363
|
+
_v$4: undefined,
|
|
364
|
+
_v$5: undefined,
|
|
365
|
+
_v$6: undefined
|
|
366
|
+
});
|
|
367
|
+
return _el$2;
|
|
368
|
+
}
|
|
246
369
|
});
|
|
247
|
-
}
|
|
248
|
-
const handleMouseUp = () => {
|
|
249
|
-
setIsDragging(false);
|
|
250
|
-
window.removeEventListener("mousemove", handleMouseMove);
|
|
251
|
-
window.removeEventListener("mouseup", handleMouseUp);
|
|
252
|
-
};
|
|
253
|
-
window.addEventListener("mousemove", handleMouseMove);
|
|
254
|
-
window.addEventListener("mouseup", handleMouseUp);
|
|
255
|
-
};
|
|
256
|
-
_el$2.$$dblclick = event => {
|
|
257
|
-
event.stopPropagation();
|
|
258
|
-
context.onRemoveNote?.(index);
|
|
259
|
-
};
|
|
260
|
-
_el$2.$$mousemove = event => {
|
|
261
|
-
if (isDragging()) return;
|
|
262
|
-
event.stopPropagation();
|
|
263
|
-
const relativeX = horizontalViewPort().calculatePixelValue(horizontalViewPort().calculatePosition(event.clientX));
|
|
264
|
-
const noteStartX = horizontalViewPort().calculatePixelValue(note().ticks);
|
|
265
|
-
const noteEndX = horizontalViewPort().calculatePixelValue(note().ticks + note().durationTicks);
|
|
266
|
-
setNoteDragMode(relativeX - noteStartX < 3 ? "trimStart" : noteEndX - relativeX < 3 ? "trimEnd" : "move");
|
|
267
|
-
};
|
|
268
|
-
effect(_p$ => {
|
|
269
|
-
const _v$ = getClasses(noteDragMode()).join(" "),
|
|
270
|
-
_v$2 = {
|
|
271
|
-
"background-color": `rgba(255,0,0, ${(128 + note().velocity) / 256})`,
|
|
272
|
-
...(context.condensed ? {
|
|
273
|
-
top: 0,
|
|
274
|
-
height: "100%"
|
|
275
|
-
} : {
|
|
276
|
-
top: `${verticalVirtualDimensions().offset}px`,
|
|
277
|
-
height: `${verticalVirtualDimensions().size}px`
|
|
278
|
-
}),
|
|
279
|
-
left: `${horizontalDimensions().offset}px`,
|
|
280
|
-
width: `${horizontalDimensions().size}px`
|
|
281
|
-
};
|
|
282
|
-
_v$ !== _p$._v$ && className(_el$2, _p$._v$ = _v$);
|
|
283
|
-
_p$._v$2 = style(_el$2, _v$2, _p$._v$2);
|
|
284
|
-
return _p$;
|
|
285
|
-
}, {
|
|
286
|
-
_v$: undefined,
|
|
287
|
-
_v$2: undefined
|
|
370
|
+
}
|
|
288
371
|
});
|
|
289
|
-
return _el$2;
|
|
290
372
|
}
|
|
291
373
|
});
|
|
292
374
|
}
|
|
@@ -297,7 +379,7 @@ const PianoRollNotes = props => {
|
|
|
297
379
|
};
|
|
298
380
|
delegateEvents(["mousedown", "mousemove", "mouseup", "dblclick", "click"]);
|
|
299
381
|
|
|
300
|
-
const _tmpl$$
|
|
382
|
+
const _tmpl$$6 = /*#__PURE__*/template(`<div class="PianoRoll-Scroller"><div><div><div></div></div></div></div>`, 8);
|
|
301
383
|
const ScrollContainer = props => {
|
|
302
384
|
let scrollContentRef;
|
|
303
385
|
const verticalViewPort = createMemo(() => useViewPortDimension("vertical"));
|
|
@@ -359,7 +441,7 @@ const ScrollContainer = props => {
|
|
|
359
441
|
});
|
|
360
442
|
});
|
|
361
443
|
return (() => {
|
|
362
|
-
const _el$ = _tmpl$$
|
|
444
|
+
const _el$ = _tmpl$$6.cloneNode(true),
|
|
363
445
|
_el$2 = _el$.firstChild,
|
|
364
446
|
_el$3 = _el$2.firstChild,
|
|
365
447
|
_el$4 = _el$3.firstChild;
|
|
@@ -400,74 +482,11 @@ const ScrollContainer = props => {
|
|
|
400
482
|
})();
|
|
401
483
|
};
|
|
402
484
|
|
|
403
|
-
var css_248z$1 = ".
|
|
404
|
-
var styles$1 = {"
|
|
485
|
+
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";
|
|
486
|
+
var styles$1 = {"PianoRollGrid":"PianoRollGrid-module_PianoRollGrid__tG119","PianoRollGrid-Row":"PianoRollGrid-module_PianoRollGrid-Row__nRMCs","PianoRollGrid-Time":"PianoRollGrid-module_PianoRollGrid-Time__jLz3E"};
|
|
405
487
|
styleInject(css_248z$1);
|
|
406
488
|
|
|
407
|
-
const _tmpl$$
|
|
408
|
-
const PianoRollKeys = () => {
|
|
409
|
-
const viewPort = createMemo(() => useViewPortDimension("vertical"));
|
|
410
|
-
return (() => {
|
|
411
|
-
const _el$ = _tmpl$$4.cloneNode(true);
|
|
412
|
-
insert(_el$, createComponent(Index, {
|
|
413
|
-
each: keys,
|
|
414
|
-
children: key => {
|
|
415
|
-
const virtualDimensions = createMemo(() => viewPort().calculatePixelDimensions(127 - key().number, 1));
|
|
416
|
-
return createComponent(Show, {
|
|
417
|
-
get when() {
|
|
418
|
-
return virtualDimensions().size > 0;
|
|
419
|
-
},
|
|
420
|
-
get children() {
|
|
421
|
-
const _el$2 = _tmpl$$4.cloneNode(true);
|
|
422
|
-
effect(_p$ => {
|
|
423
|
-
const _v$ = {
|
|
424
|
-
[styles$1["Key"]]: true,
|
|
425
|
-
[styles$1["black"]]: key().isBlack,
|
|
426
|
-
[styles$1["white"]]: !key().isBlack,
|
|
427
|
-
[styles$1["whiteAndNextIsWhite"]]: !key().isBlack && !blackKeys.includes((key().number + 1) % 12),
|
|
428
|
-
[styles$1["whiteAndPreviousIsWhite"]]: !key().isBlack && !blackKeys.includes((key().number - 1) % 12)
|
|
429
|
-
},
|
|
430
|
-
_v$2 = key().name,
|
|
431
|
-
_v$3 = key().number % 12,
|
|
432
|
-
_v$4 = `${virtualDimensions().offset}px`,
|
|
433
|
-
_v$5 = `${virtualDimensions().size}px`;
|
|
434
|
-
_p$._v$ = classList(_el$2, _v$, _p$._v$);
|
|
435
|
-
_v$2 !== _p$._v$2 && setAttribute(_el$2, "title", _p$._v$2 = _v$2);
|
|
436
|
-
_v$3 !== _p$._v$3 && setAttribute(_el$2, "data-index", _p$._v$3 = _v$3);
|
|
437
|
-
_v$4 !== _p$._v$4 && _el$2.style.setProperty("top", _p$._v$4 = _v$4);
|
|
438
|
-
_v$5 !== _p$._v$5 && _el$2.style.setProperty("height", _p$._v$5 = _v$5);
|
|
439
|
-
return _p$;
|
|
440
|
-
}, {
|
|
441
|
-
_v$: undefined,
|
|
442
|
-
_v$2: undefined,
|
|
443
|
-
_v$3: undefined,
|
|
444
|
-
_v$4: undefined,
|
|
445
|
-
_v$5: undefined
|
|
446
|
-
});
|
|
447
|
-
return _el$2;
|
|
448
|
-
}
|
|
449
|
-
});
|
|
450
|
-
}
|
|
451
|
-
}));
|
|
452
|
-
effect(() => className(_el$, styles$1.PianoRollKeys));
|
|
453
|
-
return _el$;
|
|
454
|
-
})();
|
|
455
|
-
};
|
|
456
|
-
const blackKeys = [1, 3, 6, 8, 10];
|
|
457
|
-
const keyNames = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
|
|
458
|
-
const keys = Array.from({
|
|
459
|
-
length: 128
|
|
460
|
-
}).map((_, index) => ({
|
|
461
|
-
number: index,
|
|
462
|
-
name: `${keyNames[index % 12]} ${Math.floor(index / 12) - 2}`,
|
|
463
|
-
isBlack: blackKeys.includes(index % 12)
|
|
464
|
-
}));
|
|
465
|
-
|
|
466
|
-
var css_248z = ".PianoRollGrid-module_PianoRollGrid__tG119 {\n position: relative;\n width: 100%;\n height: 100%;\n}\n\n.PianoRollGrid-module_PianoRollGrid-Key__VRbiB {\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";
|
|
467
|
-
var styles = {"PianoRollGrid":"PianoRollGrid-module_PianoRollGrid__tG119","PianoRollGrid-Key":"PianoRollGrid-module_PianoRollGrid-Key__VRbiB","PianoRollGrid-Time":"PianoRollGrid-module_PianoRollGrid-Time__jLz3E"};
|
|
468
|
-
styleInject(css_248z);
|
|
469
|
-
|
|
470
|
-
const _tmpl$$3 = /*#__PURE__*/template(`<div></div>`, 2);
|
|
489
|
+
const _tmpl$$5 = /*#__PURE__*/template(`<div></div>`, 2);
|
|
471
490
|
const PianoRollGrid = () => {
|
|
472
491
|
const context = usePianoRollContext();
|
|
473
492
|
const verticalViewPort = createMemo(() => useViewPortDimension("vertical"));
|
|
@@ -475,10 +494,12 @@ const PianoRollGrid = () => {
|
|
|
475
494
|
const measureTicks = createMemo(() => context.ppq * 4);
|
|
476
495
|
const selectedGridDivisorTicks = createMemo(() => measureTicks() / context.gridDivision);
|
|
477
496
|
function calculateVisibleGridDivisorTicks(value) {
|
|
478
|
-
|
|
497
|
+
const visibleRange = horizontalViewPort().calculateVisibleRange();
|
|
498
|
+
if (visibleRange <= 0) return 0;
|
|
499
|
+
if (visibleRange / value > 100) {
|
|
479
500
|
return calculateVisibleGridDivisorTicks(value * 2);
|
|
480
501
|
}
|
|
481
|
-
if (
|
|
502
|
+
if (visibleRange / value < 30) {
|
|
482
503
|
return calculateVisibleGridDivisorTicks(value / 2);
|
|
483
504
|
}
|
|
484
505
|
return value;
|
|
@@ -495,7 +516,7 @@ const PianoRollGrid = () => {
|
|
|
495
516
|
}));
|
|
496
517
|
});
|
|
497
518
|
return (() => {
|
|
498
|
-
const _el$ = _tmpl$$
|
|
519
|
+
const _el$ = _tmpl$$5.cloneNode(true);
|
|
499
520
|
insert(_el$, createComponent(Index, {
|
|
500
521
|
get each() {
|
|
501
522
|
return gridArray();
|
|
@@ -507,9 +528,9 @@ const PianoRollGrid = () => {
|
|
|
507
528
|
return virtualDimensions().size > 0;
|
|
508
529
|
},
|
|
509
530
|
get children() {
|
|
510
|
-
const _el$2 = _tmpl$$
|
|
531
|
+
const _el$2 = _tmpl$$5.cloneNode(true);
|
|
511
532
|
effect(_p$ => {
|
|
512
|
-
const _v$ = styles["PianoRollGrid-Time"],
|
|
533
|
+
const _v$ = styles$1["PianoRollGrid-Time"],
|
|
513
534
|
_v$2 = Math.ceil((entry().index + 1 * selectedGridDivisorTicks()) / measureTicks()) % 2 === 0 ? "#ddd" : "#ccc",
|
|
514
535
|
_v$3 = `${virtualDimensions().offset}px`,
|
|
515
536
|
_v$4 = `${virtualDimensions().size}px`,
|
|
@@ -534,7 +555,7 @@ const PianoRollGrid = () => {
|
|
|
534
555
|
}), null);
|
|
535
556
|
insert(_el$, createComponent(Show, {
|
|
536
557
|
get when() {
|
|
537
|
-
return
|
|
558
|
+
return context.mode === "keys";
|
|
538
559
|
},
|
|
539
560
|
get children() {
|
|
540
561
|
return createComponent(Index, {
|
|
@@ -546,10 +567,10 @@ const PianoRollGrid = () => {
|
|
|
546
567
|
return virtualDimensions().size > 0;
|
|
547
568
|
},
|
|
548
569
|
get children() {
|
|
549
|
-
const _el$3 = _tmpl$$
|
|
570
|
+
const _el$3 = _tmpl$$5.cloneNode(true);
|
|
550
571
|
_el$3.style.setProperty("width", "100%");
|
|
551
572
|
effect(_p$ => {
|
|
552
|
-
const _v$6 = styles["PianoRollGrid-
|
|
573
|
+
const _v$6 = styles$1["PianoRollGrid-Row"],
|
|
553
574
|
_v$7 = `${virtualDimensions().offset}px`,
|
|
554
575
|
_v$8 = `${virtualDimensions().size}px`,
|
|
555
576
|
_v$9 = key().isBlack ? "rgba(0,0,0,0.2)" : "none",
|
|
@@ -574,35 +595,53 @@ const PianoRollGrid = () => {
|
|
|
574
595
|
});
|
|
575
596
|
}
|
|
576
597
|
}), null);
|
|
577
|
-
|
|
598
|
+
insert(_el$, createComponent(Show, {
|
|
599
|
+
get when() {
|
|
600
|
+
return context.mode === "tracks";
|
|
601
|
+
},
|
|
602
|
+
get children() {
|
|
603
|
+
return createComponent(For, {
|
|
604
|
+
get each() {
|
|
605
|
+
return context.tracks;
|
|
606
|
+
},
|
|
607
|
+
children: (track, index) => {
|
|
608
|
+
const virtualDimensions = createMemo(() => verticalViewPort().calculatePixelDimensions(index(), 1));
|
|
609
|
+
return createComponent(Show, {
|
|
610
|
+
get when() {
|
|
611
|
+
return virtualDimensions().size > 0;
|
|
612
|
+
},
|
|
613
|
+
get children() {
|
|
614
|
+
const _el$4 = _tmpl$$5.cloneNode(true);
|
|
615
|
+
_el$4.style.setProperty("width", "100%");
|
|
616
|
+
_el$4.style.setProperty("border-width", "0");
|
|
617
|
+
effect(_p$ => {
|
|
618
|
+
const _v$11 = styles$1["PianoRollGrid-Row"],
|
|
619
|
+
_v$12 = `${virtualDimensions().offset}px`,
|
|
620
|
+
_v$13 = `${virtualDimensions().size}px`,
|
|
621
|
+
_v$14 = index() % 2 === 0 ? "rgba(0,0,0,0.2)" : "none";
|
|
622
|
+
_v$11 !== _p$._v$11 && className(_el$4, _p$._v$11 = _v$11);
|
|
623
|
+
_v$12 !== _p$._v$12 && _el$4.style.setProperty("top", _p$._v$12 = _v$12);
|
|
624
|
+
_v$13 !== _p$._v$13 && _el$4.style.setProperty("height", _p$._v$13 = _v$13);
|
|
625
|
+
_v$14 !== _p$._v$14 && _el$4.style.setProperty("background-color", _p$._v$14 = _v$14);
|
|
626
|
+
return _p$;
|
|
627
|
+
}, {
|
|
628
|
+
_v$11: undefined,
|
|
629
|
+
_v$12: undefined,
|
|
630
|
+
_v$13: undefined,
|
|
631
|
+
_v$14: undefined
|
|
632
|
+
});
|
|
633
|
+
return _el$4;
|
|
634
|
+
}
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
}), null);
|
|
640
|
+
effect(() => className(_el$, styles$1.PianoRollGrid));
|
|
578
641
|
return _el$;
|
|
579
642
|
})();
|
|
580
643
|
};
|
|
581
644
|
|
|
582
|
-
const useNotes = () => {
|
|
583
|
-
const [notes, onNotesChange] = createSignal([]);
|
|
584
|
-
const onNoteChange = (index, note) => {
|
|
585
|
-
onNotesChange([...notes().slice(0, index), note, ...notes().splice(index + 1)]);
|
|
586
|
-
};
|
|
587
|
-
const onInsertNote = note => {
|
|
588
|
-
const index = Math.max(notes().findIndex(({
|
|
589
|
-
ticks
|
|
590
|
-
}) => ticks > note.ticks), 0);
|
|
591
|
-
onNotesChange([...notes().slice(0, index), note, ...notes().splice(index)]);
|
|
592
|
-
return index;
|
|
593
|
-
};
|
|
594
|
-
const onRemoveNote = index => {
|
|
595
|
-
onNotesChange([...notes().slice(0, index), ...notes().splice(index + 1)]);
|
|
596
|
-
};
|
|
597
|
-
return {
|
|
598
|
-
notes,
|
|
599
|
-
onNotesChange,
|
|
600
|
-
onNoteChange,
|
|
601
|
-
onInsertNote,
|
|
602
|
-
onRemoveNote
|
|
603
|
-
};
|
|
604
|
-
};
|
|
605
|
-
|
|
606
645
|
const defaultRect = {
|
|
607
646
|
left: 0,
|
|
608
647
|
width: 0,
|
|
@@ -631,11 +670,11 @@ function useBoundingClientRect(containerRef) {
|
|
|
631
670
|
return boundingClientRect;
|
|
632
671
|
}
|
|
633
672
|
|
|
634
|
-
const _tmpl$$
|
|
673
|
+
const _tmpl$$4 = /*#__PURE__*/template(`<input min="1" max="11" step="0.01">`, 1);
|
|
635
674
|
const VerticalZoomControl = props => {
|
|
636
675
|
const context = usePianoRollContext();
|
|
637
676
|
return (() => {
|
|
638
|
-
const _el$ = _tmpl$$
|
|
677
|
+
const _el$ = _tmpl$$4.cloneNode(true);
|
|
639
678
|
spread(_el$, mergeProps(props, {
|
|
640
679
|
get value() {
|
|
641
680
|
return context.verticalZoom;
|
|
@@ -659,196 +698,91 @@ const VerticalZoomControl = props => {
|
|
|
659
698
|
})();
|
|
660
699
|
};
|
|
661
700
|
|
|
662
|
-
const _tmpl$$
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
_el$2 =
|
|
710
|
-
_el$
|
|
711
|
-
_el$
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
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, {
|
|
761
|
-
get each() {
|
|
762
|
-
return allProps.tracks;
|
|
763
|
-
},
|
|
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
|
-
});
|
|
803
|
-
}
|
|
804
|
-
});
|
|
805
|
-
}
|
|
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, {
|
|
816
|
-
get value() {
|
|
817
|
-
return contextProps.verticalZoom;
|
|
701
|
+
const _tmpl$$3 = /*#__PURE__*/template(`<input max="500" min="1" step="0.01">`, 1);
|
|
702
|
+
const HorizontalZoomControl = props => {
|
|
703
|
+
const context = usePianoRollContext();
|
|
704
|
+
return (() => {
|
|
705
|
+
const _el$ = _tmpl$$3.cloneNode(true);
|
|
706
|
+
spread(_el$, mergeProps(props, {
|
|
707
|
+
get value() {
|
|
708
|
+
return context.zoom;
|
|
709
|
+
},
|
|
710
|
+
"onInput": event => context.onZoomChange?.(event.currentTarget.valueAsNumber),
|
|
711
|
+
"type": "range",
|
|
712
|
+
get style() {
|
|
713
|
+
return {
|
|
714
|
+
"margin-left": "50px",
|
|
715
|
+
"margin-right": "16px",
|
|
716
|
+
...(typeof props.style === "object" && props.style)
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
}), false, false);
|
|
720
|
+
return _el$;
|
|
721
|
+
})();
|
|
722
|
+
};
|
|
723
|
+
|
|
724
|
+
var css_248z = ".PianoRollTrackList-module_PianoRollTrackList__pyuxQ {\n position: relative;\n height: 100%;\n flex: 1;\n}\n\n.PianoRollTrackList-module_Track__VZFIg {\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}\n";
|
|
725
|
+
var styles = {"PianoRollTrackList":"PianoRollTrackList-module_PianoRollTrackList__pyuxQ","Track":"PianoRollTrackList-module_Track__VZFIg"};
|
|
726
|
+
styleInject(css_248z);
|
|
727
|
+
|
|
728
|
+
const _tmpl$$2 = /*#__PURE__*/template(`<div></div>`, 2),
|
|
729
|
+
_tmpl$2$1 = /*#__PURE__*/template(`<div> </div>`, 2);
|
|
730
|
+
const PianoRollTrackList = () => {
|
|
731
|
+
const viewPort = createMemo(() => useViewPortDimension("vertical"));
|
|
732
|
+
const context = usePianoRollContext();
|
|
733
|
+
return (() => {
|
|
734
|
+
const _el$ = _tmpl$$2.cloneNode(true);
|
|
735
|
+
insert(_el$, createComponent(Index, {
|
|
736
|
+
get each() {
|
|
737
|
+
return context.tracks;
|
|
738
|
+
},
|
|
739
|
+
children: (track, index) => {
|
|
740
|
+
const virtualDimensions = createMemo(() => viewPort().calculatePixelDimensions(context.mode === "tracks" ? index : index * 8, context.mode === "tracks" ? 1 : 8));
|
|
741
|
+
return createComponent(Show, {
|
|
742
|
+
get when() {
|
|
743
|
+
return virtualDimensions().size > 0;
|
|
744
|
+
},
|
|
745
|
+
get children() {
|
|
746
|
+
const _el$2 = _tmpl$2$1.cloneNode(true),
|
|
747
|
+
_el$3 = _el$2.firstChild;
|
|
748
|
+
_el$2.$$click = () => context.onSelectedTrackIndexChange?.(index);
|
|
749
|
+
_el$2.style.setProperty("cursor", "pointer");
|
|
750
|
+
insert(_el$2, index, _el$3);
|
|
751
|
+
insert(_el$2, () => track().name || "[unnamed track]", null);
|
|
752
|
+
effect(_p$ => {
|
|
753
|
+
const _v$ = {
|
|
754
|
+
[styles["Track"]]: true
|
|
818
755
|
},
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
"
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
}
|
|
845
|
-
});
|
|
846
|
-
}
|
|
847
|
-
});
|
|
756
|
+
_v$2 = track().name,
|
|
757
|
+
_v$3 = `${virtualDimensions().offset}px`,
|
|
758
|
+
_v$4 = `${virtualDimensions().size}px`,
|
|
759
|
+
_v$5 = index === context.selectedTrackIndex ? "gray" : "lightgrey";
|
|
760
|
+
_p$._v$ = classList(_el$2, _v$, _p$._v$);
|
|
761
|
+
_v$2 !== _p$._v$2 && setAttribute(_el$2, "title", _p$._v$2 = _v$2);
|
|
762
|
+
_v$3 !== _p$._v$3 && _el$2.style.setProperty("top", _p$._v$3 = _v$3);
|
|
763
|
+
_v$4 !== _p$._v$4 && _el$2.style.setProperty("height", _p$._v$4 = _v$4);
|
|
764
|
+
_v$5 !== _p$._v$5 && _el$2.style.setProperty("background", _p$._v$5 = _v$5);
|
|
765
|
+
return _p$;
|
|
766
|
+
}, {
|
|
767
|
+
_v$: undefined,
|
|
768
|
+
_v$2: undefined,
|
|
769
|
+
_v$3: undefined,
|
|
770
|
+
_v$4: undefined,
|
|
771
|
+
_v$5: undefined
|
|
772
|
+
});
|
|
773
|
+
return _el$2;
|
|
774
|
+
}
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
}));
|
|
778
|
+
effect(() => className(_el$, styles.PianoRollTrackList));
|
|
779
|
+
return _el$;
|
|
780
|
+
})();
|
|
848
781
|
};
|
|
849
782
|
delegateEvents(["click"]);
|
|
850
783
|
|
|
851
|
-
const _tmpl
|
|
784
|
+
const _tmpl$$1 = /*#__PURE__*/template(`<div></div>`, 2),
|
|
785
|
+
_tmpl$2 = /*#__PURE__*/template(`<div><div></div></div>`, 4);
|
|
852
786
|
const PianoRoll = allProps => {
|
|
853
787
|
const [contextProps, divProps] = splitContextProps(allProps);
|
|
854
788
|
const [scrollerRef, setScrollerRef] = createSignal();
|
|
@@ -858,14 +792,20 @@ const PianoRoll = allProps => {
|
|
|
858
792
|
const maxZoom = createMemo(() => 500 * (zoomFactor / clientRect().width));
|
|
859
793
|
const minVerticalZoom = createMemo(() => 1 / (zoomFactor / clientRect().height));
|
|
860
794
|
const maxVerticalZoom = createMemo(() => 10 * (zoomFactor / clientRect().height));
|
|
795
|
+
createEffect(isInitial => {
|
|
796
|
+
if (isInitial) return false;
|
|
797
|
+
if (contextProps.mode === "tracks") {
|
|
798
|
+
contextProps.onVerticalPositionChange?.(0);
|
|
799
|
+
}
|
|
800
|
+
}, true);
|
|
861
801
|
return createComponent(PianoRollContextProvider, {
|
|
862
802
|
value: contextProps,
|
|
863
803
|
get children() {
|
|
864
|
-
const _el$ = _tmpl
|
|
804
|
+
const _el$ = _tmpl$2.cloneNode(true),
|
|
865
805
|
_el$2 = _el$.firstChild;
|
|
866
806
|
spread(_el$, mergeProps(divProps, {
|
|
867
807
|
get ["class"]() {
|
|
868
|
-
return styles$
|
|
808
|
+
return styles$4.PianoRoll;
|
|
869
809
|
}
|
|
870
810
|
}), false, true);
|
|
871
811
|
insert(_el$2, createComponent(ScrollZoomViewPort, {
|
|
@@ -883,17 +823,38 @@ const PianoRoll = allProps => {
|
|
|
883
823
|
pixelOffset: clientRect().top,
|
|
884
824
|
pixelSize: clientRect().height,
|
|
885
825
|
position: contextProps.verticalPosition,
|
|
886
|
-
range: 128,
|
|
826
|
+
range: contextProps.mode === "keys" ? 128 : Math.max(contextProps.tracks.length, 16),
|
|
887
827
|
zoom: contextProps.verticalZoom * (zoomFactor / clientRect().height),
|
|
888
828
|
onPositionChange: contextProps.onVerticalPositionChange,
|
|
889
829
|
onZoomChange: verticalZoom => contextProps.onVerticalZoomChange?.(clamp(verticalZoom / (zoomFactor / clientRect().height), minVerticalZoom(), maxVerticalZoom()))
|
|
890
830
|
})
|
|
891
831
|
},
|
|
892
832
|
get children() {
|
|
893
|
-
return [
|
|
833
|
+
return [(() => {
|
|
834
|
+
const _el$3 = _tmpl$$1.cloneNode(true);
|
|
835
|
+
_el$3.style.setProperty("display", "flex");
|
|
836
|
+
_el$3.style.setProperty("width", "20%");
|
|
837
|
+
insert(_el$3, createComponent(Show, {
|
|
838
|
+
get when() {
|
|
839
|
+
return allProps.showTrackList;
|
|
840
|
+
},
|
|
841
|
+
get children() {
|
|
842
|
+
return createComponent(PianoRollTrackList, {});
|
|
843
|
+
}
|
|
844
|
+
}), null);
|
|
845
|
+
insert(_el$3, createComponent(Show, {
|
|
846
|
+
get when() {
|
|
847
|
+
return contextProps.mode === "keys";
|
|
848
|
+
},
|
|
849
|
+
get children() {
|
|
850
|
+
return createComponent(PianoRollKeys, {});
|
|
851
|
+
}
|
|
852
|
+
}), null);
|
|
853
|
+
return _el$3;
|
|
854
|
+
})(), createComponent(ScrollContainer, {
|
|
894
855
|
ref: setScrollerRef,
|
|
895
856
|
get children() {
|
|
896
|
-
return [createComponent(PianoRollGrid, {}), createComponent(PianoRollNotes, {})];
|
|
857
|
+
return [memo(() => allProps.children), createComponent(PianoRollGrid, {}), createComponent(PianoRollNotes, {})];
|
|
897
858
|
}
|
|
898
859
|
}), createComponent(VerticalZoomControl, {
|
|
899
860
|
get min() {
|
|
@@ -913,19 +874,97 @@ const PianoRoll = allProps => {
|
|
|
913
874
|
return maxZoom();
|
|
914
875
|
}
|
|
915
876
|
}), null);
|
|
916
|
-
effect(() => className(_el$2, styles$
|
|
877
|
+
effect(() => className(_el$2, styles$4.PianoRollContainer));
|
|
917
878
|
return _el$;
|
|
918
879
|
}
|
|
919
880
|
});
|
|
920
881
|
};
|
|
921
882
|
|
|
883
|
+
const _tmpl$ = /*#__PURE__*/template(`<div class="PlayHead"></div>`, 2);
|
|
884
|
+
const PlayHead = allProps => {
|
|
885
|
+
const propsWithDefauls = mergeProps$1({
|
|
886
|
+
playHeadPosition: 0,
|
|
887
|
+
sync: false
|
|
888
|
+
}, allProps);
|
|
889
|
+
const [props, divProps] = splitProps(propsWithDefauls, ["playHeadPosition", "sync", "onPlayHeadPositionChange", "onPositionChange"]);
|
|
890
|
+
const viewPort = useViewPortDimension("horizontal");
|
|
891
|
+
createEffect(() => {
|
|
892
|
+
if (!props.sync) return;
|
|
893
|
+
const maxPosition = viewPort.range;
|
|
894
|
+
const newPosition = clamp(props.playHeadPosition - viewPort.range / viewPort.zoom / 2, 0, maxPosition);
|
|
895
|
+
props.onPositionChange?.(newPosition);
|
|
896
|
+
});
|
|
897
|
+
const leftPosition = createMemo(() => viewPort.calculatePixelOffset(props.playHeadPosition));
|
|
898
|
+
return (() => {
|
|
899
|
+
const _el$ = _tmpl$.cloneNode(true);
|
|
900
|
+
spread(_el$, mergeProps(divProps, {
|
|
901
|
+
get style() {
|
|
902
|
+
return {
|
|
903
|
+
position: "absolute",
|
|
904
|
+
height: "100%",
|
|
905
|
+
width: "2px",
|
|
906
|
+
left: `${leftPosition()}px`,
|
|
907
|
+
"background-color": "green",
|
|
908
|
+
cursor: "pointer",
|
|
909
|
+
...(typeof divProps.style === "object" && divProps.style)
|
|
910
|
+
};
|
|
911
|
+
},
|
|
912
|
+
"onMouseDown": event => {
|
|
913
|
+
event.preventDefault();
|
|
914
|
+
event.stopPropagation();
|
|
915
|
+
const handleMouseMove = ({
|
|
916
|
+
movementX
|
|
917
|
+
}) => {
|
|
918
|
+
const {
|
|
919
|
+
parentElement
|
|
920
|
+
} = event.currentTarget;
|
|
921
|
+
if (!parentElement) return;
|
|
922
|
+
const newPosition = viewPort.calculatePosition(leftPosition() + movementX);
|
|
923
|
+
props.onPlayHeadPositionChange?.(newPosition);
|
|
924
|
+
};
|
|
925
|
+
const handleMouseUp = () => {
|
|
926
|
+
window.removeEventListener("mousemove", handleMouseMove);
|
|
927
|
+
window.removeEventListener("mouseup", handleMouseUp);
|
|
928
|
+
};
|
|
929
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
930
|
+
window.addEventListener("mouseup", handleMouseUp);
|
|
931
|
+
}
|
|
932
|
+
}), false, false);
|
|
933
|
+
return _el$;
|
|
934
|
+
})();
|
|
935
|
+
};
|
|
936
|
+
|
|
937
|
+
const useNotes = () => {
|
|
938
|
+
const [notes, onNotesChange] = createSignal([]);
|
|
939
|
+
const onNoteChange = (index, note) => {
|
|
940
|
+
onNotesChange([...notes().slice(0, index), note, ...notes().splice(index + 1)]);
|
|
941
|
+
};
|
|
942
|
+
const onInsertNote = note => {
|
|
943
|
+
const index = Math.max(notes().findIndex(({
|
|
944
|
+
ticks
|
|
945
|
+
}) => ticks > note.ticks), 0);
|
|
946
|
+
onNotesChange([...notes().slice(0, index), note, ...notes().splice(index)]);
|
|
947
|
+
return index;
|
|
948
|
+
};
|
|
949
|
+
const onRemoveNote = index => {
|
|
950
|
+
onNotesChange([...notes().slice(0, index), ...notes().splice(index + 1)]);
|
|
951
|
+
};
|
|
952
|
+
return {
|
|
953
|
+
notes,
|
|
954
|
+
onNotesChange,
|
|
955
|
+
onNoteChange,
|
|
956
|
+
onInsertNote,
|
|
957
|
+
onRemoveNote
|
|
958
|
+
};
|
|
959
|
+
};
|
|
960
|
+
|
|
922
961
|
const usePianoRoll = () => {
|
|
923
962
|
const [ppq, onPpqChange] = createSignal(120);
|
|
924
|
-
const [
|
|
963
|
+
const [mode, onModeChange] = createSignal("tracks");
|
|
925
964
|
const [position, onPositionChange] = createSignal(0);
|
|
926
965
|
const [zoom, onZoomChange] = createSignal(10);
|
|
927
966
|
const [verticalZoom, onVerticalZoomChange] = createSignal(5);
|
|
928
|
-
const [verticalPosition, onVerticalPositionChange] = createSignal(
|
|
967
|
+
const [verticalPosition, onVerticalPositionChange] = createSignal(44);
|
|
929
968
|
const [gridDivision, onGridDivisionChange] = createSignal(4);
|
|
930
969
|
const [snapToGrid, onSnapToGridChange] = createSignal(true);
|
|
931
970
|
const [duration, onDurationChange] = createSignal(0);
|
|
@@ -944,12 +983,12 @@ const usePianoRoll = () => {
|
|
|
944
983
|
onGridDivisionChange,
|
|
945
984
|
snapToGrid,
|
|
946
985
|
onSnapToGridChange,
|
|
947
|
-
|
|
948
|
-
|
|
986
|
+
mode,
|
|
987
|
+
onModeChange,
|
|
949
988
|
duration,
|
|
950
989
|
onDurationChange
|
|
951
990
|
};
|
|
952
991
|
};
|
|
953
992
|
|
|
954
|
-
export {
|
|
993
|
+
export { PianoRoll, PlayHead, useNotes, usePianoRoll };
|
|
955
994
|
//# sourceMappingURL=index.js.map
|