solid-pianoroll 0.0.11 → 0.0.12
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 +340 -140
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +341 -143
- package/dist/esm/index.js.map +1 -1
- package/dist/source/MultiTrackPianoRoll.jsx +136 -0
- package/dist/source/PianoRoll.jsx +3 -20
- package/dist/source/PianoRollContext.jsx +20 -1
- package/dist/source/PianoRollNotes.jsx +14 -7
- package/dist/source/index.jsx +3 -1
- package/dist/source/useNotes.js +23 -0
- package/dist/source/usePianoRoll.js +4 -24
- package/dist/source/viewport/HorizontalZoomControl.jsx +1 -0
- package/dist/source/viewport/createViewPortDimension.js +4 -0
- package/dist/types/MultiTrackPianoRoll.d.ts +10 -0
- package/dist/types/PianoRollContext.d.ts +1 -0
- package/dist/types/index.d.ts +3 -1
- package/dist/types/useNotes.d.ts +9 -0
- package/dist/types/usePianoRoll.d.ts +2 -6
- package/dist/types/viewport/ScrollZoomViewPort.d.ts +4 -0
- package/dist/types/viewport/createViewPortDimension.d.ts +4 -0
- package/package.json +1 -1
package/dist/cjs/index.js
CHANGED
|
@@ -29,7 +29,7 @@ function styleInject(css, ref) {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
var css_248z$3 = ".PianoRoll-module_PianoRoll__rkRYx {\n box-sizing: border-box;\n display: flex;\n overflow: hidden;\n flex-direction: column;\n
|
|
32
|
+
var css_248z$3 = ".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";
|
|
33
33
|
var styles$3 = {"PianoRoll":"PianoRoll-module_PianoRoll__rkRYx","PianoRollContainer":"PianoRoll-module_PianoRollContainer__Oyxr7"};
|
|
34
34
|
styleInject(css_248z$3);
|
|
35
35
|
|
|
@@ -40,10 +40,30 @@ const usePianoRollContext = () => {
|
|
|
40
40
|
if (!context) throw new Error("No PianoRollContext found");
|
|
41
41
|
return context;
|
|
42
42
|
};
|
|
43
|
+
const splitContextProps = allProps => solidJs.splitProps(allProps, ["condensed", "duration", "gridDivision", "notes", "position", "ppq", "snapToGrid", "verticalPosition", "verticalZoom", "zoom", "onInsertNote", "onNoteChange", "onPositionChange", "onRemoveNote", "onVerticalPositionChange", "onVerticalZoomChange", "onZoomChange"]);
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
const _tmpl$$7 = /*#__PURE__*/web.template(`<input max="500" min="1" step="0.01">`, 1);
|
|
46
|
+
const HorizontalZoomControl = props => {
|
|
47
|
+
const context = usePianoRollContext();
|
|
48
|
+
return (() => {
|
|
49
|
+
const _el$ = _tmpl$$7.cloneNode(true);
|
|
50
|
+
web.spread(_el$, web.mergeProps(props, {
|
|
51
|
+
get value() {
|
|
52
|
+
return context.zoom;
|
|
53
|
+
},
|
|
54
|
+
"onInput": event => context.onZoomChange?.(event.currentTarget.valueAsNumber),
|
|
55
|
+
"type": "range",
|
|
56
|
+
get style() {
|
|
57
|
+
return {
|
|
58
|
+
"margin-left": "50px",
|
|
59
|
+
"margin-right": "16px",
|
|
60
|
+
...(typeof props.style === "object" && props.style)
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}), false, false);
|
|
64
|
+
return _el$;
|
|
65
|
+
})();
|
|
66
|
+
};
|
|
47
67
|
|
|
48
68
|
function createViewPortDimension(getState) {
|
|
49
69
|
const getStateWithFunctions = () => ({
|
|
@@ -52,7 +72,8 @@ function createViewPortDimension(getState) {
|
|
|
52
72
|
calculatePosition,
|
|
53
73
|
calculatePixelDimensions,
|
|
54
74
|
calculateVisibleRange,
|
|
55
|
-
calculateMaxPosition
|
|
75
|
+
calculateMaxPosition,
|
|
76
|
+
isVisible
|
|
56
77
|
});
|
|
57
78
|
const [state, setState] = store.createStore(getStateWithFunctions());
|
|
58
79
|
solidJs.createEffect(() => setState(getStateWithFunctions()));
|
|
@@ -82,6 +103,12 @@ function createViewPortDimension(getState) {
|
|
|
82
103
|
size
|
|
83
104
|
};
|
|
84
105
|
}
|
|
106
|
+
function isVisible({
|
|
107
|
+
offset,
|
|
108
|
+
size
|
|
109
|
+
}) {
|
|
110
|
+
return offset + size > 0 && offset < state.pixelSize;
|
|
111
|
+
}
|
|
85
112
|
return state;
|
|
86
113
|
}
|
|
87
114
|
const clamp = (value, min, max) => Math.max(min, Math.min(max, value));
|
|
@@ -109,70 +136,11 @@ const useViewPortDimension = name => {
|
|
|
109
136
|
return viewPort;
|
|
110
137
|
};
|
|
111
138
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
return (() => {
|
|
116
|
-
const _el$ = _tmpl$$6.cloneNode(true);
|
|
117
|
-
web.insert(_el$, web.createComponent(solidJs.Index, {
|
|
118
|
-
each: keys,
|
|
119
|
-
children: key => {
|
|
120
|
-
const virtualDimensions = solidJs.createMemo(() => viewPort().calculatePixelDimensions(127 - key().number, 1));
|
|
121
|
-
return web.createComponent(solidJs.Show, {
|
|
122
|
-
get when() {
|
|
123
|
-
return virtualDimensions().size > 0;
|
|
124
|
-
},
|
|
125
|
-
get children() {
|
|
126
|
-
const _el$2 = _tmpl$$6.cloneNode(true);
|
|
127
|
-
web.effect(_p$ => {
|
|
128
|
-
const _v$ = {
|
|
129
|
-
[styles$2["Key"]]: true,
|
|
130
|
-
[styles$2["black"]]: key().isBlack,
|
|
131
|
-
[styles$2["white"]]: !key().isBlack,
|
|
132
|
-
[styles$2["whiteAndNextIsWhite"]]: !key().isBlack && !blackKeys.includes((key().number + 1) % 12),
|
|
133
|
-
[styles$2["whiteAndPreviousIsWhite"]]: !key().isBlack && !blackKeys.includes((key().number - 1) % 12)
|
|
134
|
-
},
|
|
135
|
-
_v$2 = key().name,
|
|
136
|
-
_v$3 = key().number % 12,
|
|
137
|
-
_v$4 = `${virtualDimensions().offset}px`,
|
|
138
|
-
_v$5 = `${virtualDimensions().size}px`;
|
|
139
|
-
_p$._v$ = web.classList(_el$2, _v$, _p$._v$);
|
|
140
|
-
_v$2 !== _p$._v$2 && web.setAttribute(_el$2, "title", _p$._v$2 = _v$2);
|
|
141
|
-
_v$3 !== _p$._v$3 && web.setAttribute(_el$2, "data-index", _p$._v$3 = _v$3);
|
|
142
|
-
_v$4 !== _p$._v$4 && _el$2.style.setProperty("top", _p$._v$4 = _v$4);
|
|
143
|
-
_v$5 !== _p$._v$5 && _el$2.style.setProperty("height", _p$._v$5 = _v$5);
|
|
144
|
-
return _p$;
|
|
145
|
-
}, {
|
|
146
|
-
_v$: undefined,
|
|
147
|
-
_v$2: undefined,
|
|
148
|
-
_v$3: undefined,
|
|
149
|
-
_v$4: undefined,
|
|
150
|
-
_v$5: undefined
|
|
151
|
-
});
|
|
152
|
-
return _el$2;
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
}));
|
|
157
|
-
web.effect(() => web.className(_el$, styles$2.PianoRollKeys));
|
|
158
|
-
return _el$;
|
|
159
|
-
})();
|
|
160
|
-
};
|
|
161
|
-
const blackKeys = [1, 3, 6, 8, 10];
|
|
162
|
-
const keyNames = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
|
|
163
|
-
const keys = Array.from({
|
|
164
|
-
length: 128
|
|
165
|
-
}).map((_, index) => ({
|
|
166
|
-
number: index,
|
|
167
|
-
name: `${keyNames[index % 12]} ${Math.floor(index / 12) - 2}`,
|
|
168
|
-
isBlack: blackKeys.includes(index % 12)
|
|
169
|
-
}));
|
|
170
|
-
|
|
171
|
-
var css_248z$1 = ".PianoRollNotes-module_PianoRollNotes__6pF-y {\n position: absolute;\n flex: 1;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\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: pointer;\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}";
|
|
172
|
-
var styles$1 = {"PianoRollNotes":"PianoRollNotes-module_PianoRollNotes__6pF-y","Note":"PianoRollNotes-module_Note__-jxLb","trimStart":"PianoRollNotes-module_trimStart__vuBlj","trimEnd":"PianoRollNotes-module_trimEnd__zPdjr"};
|
|
173
|
-
styleInject(css_248z$1);
|
|
139
|
+
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}";
|
|
140
|
+
var styles$2 = {"PianoRollNotes":"PianoRollNotes-module_PianoRollNotes__6pF-y","Note":"PianoRollNotes-module_Note__-jxLb","trimStart":"PianoRollNotes-module_trimStart__vuBlj","trimEnd":"PianoRollNotes-module_trimEnd__zPdjr"};
|
|
141
|
+
styleInject(css_248z$2);
|
|
174
142
|
|
|
175
|
-
const _tmpl$$
|
|
143
|
+
const _tmpl$$6 = /*#__PURE__*/web.template(`<div></div>`, 2);
|
|
176
144
|
const PianoRollNotes = props => {
|
|
177
145
|
const context = usePianoRollContext();
|
|
178
146
|
const verticalViewPort = solidJs.createMemo(() => useViewPortDimension("vertical"));
|
|
@@ -181,7 +149,7 @@ const PianoRollNotes = props => {
|
|
|
181
149
|
const snapValueToGridIfEnabled = (value, altKey) => context.snapToGrid && !altKey ? Math.round(value / gridDivisionTicks()) * gridDivisionTicks() : value;
|
|
182
150
|
const insertOrUpdateNote = event => {
|
|
183
151
|
const position = horizontalViewPort().calculatePosition(event.clientX);
|
|
184
|
-
const midi = 127 - Math.floor(verticalViewPort().calculatePosition(event.clientY));
|
|
152
|
+
const midi = context.condensed ? 60 : 127 - Math.floor(verticalViewPort().calculatePosition(event.clientY));
|
|
185
153
|
const eventPositionTicks = Math.floor(position / gridDivisionTicks()) * gridDivisionTicks();
|
|
186
154
|
const velocity = 127;
|
|
187
155
|
const existingNote = newNote();
|
|
@@ -206,10 +174,10 @@ const PianoRollNotes = props => {
|
|
|
206
174
|
const [isMouseDown, setIsMouseDown] = solidJs.createSignal(false);
|
|
207
175
|
const newNote = solidJs.createMemo(() => context.notes[newNoteIndex()]);
|
|
208
176
|
const getClasses = noteDragMode => {
|
|
209
|
-
return noteDragMode ? [styles$
|
|
177
|
+
return noteDragMode ? [styles$2.Note, styles$2[noteDragMode]] : [styles$2.Note];
|
|
210
178
|
};
|
|
211
179
|
return (() => {
|
|
212
|
-
const _el$ = _tmpl$$
|
|
180
|
+
const _el$ = _tmpl$$6.cloneNode(true);
|
|
213
181
|
_el$.$$click = event => {
|
|
214
182
|
if (newNote()) {
|
|
215
183
|
setNewNoteIndex(-1);
|
|
@@ -233,9 +201,6 @@ const PianoRollNotes = props => {
|
|
|
233
201
|
return;
|
|
234
202
|
}
|
|
235
203
|
const index = insertOrUpdateNote(event);
|
|
236
|
-
console.log({
|
|
237
|
-
index
|
|
238
|
-
});
|
|
239
204
|
setNewNoteIndex(index);
|
|
240
205
|
};
|
|
241
206
|
_el$.$$mousedown = () => {
|
|
@@ -249,14 +214,14 @@ const PianoRollNotes = props => {
|
|
|
249
214
|
return context.notes;
|
|
250
215
|
},
|
|
251
216
|
children: (note, index) => {
|
|
252
|
-
const
|
|
217
|
+
const verticalVirtualDimensions = solidJs.createMemo(() => verticalViewPort().calculatePixelDimensions(127 - note().midi, 1));
|
|
253
218
|
const horizontalDimensions = solidJs.createMemo(() => horizontalViewPort().calculatePixelDimensions(note().ticks, note().durationTicks));
|
|
254
219
|
return web.createComponent(solidJs.Show, {
|
|
255
220
|
get when() {
|
|
256
|
-
return web.memo(() =>
|
|
221
|
+
return web.memo(() => !!(verticalViewPort().isVisible(verticalVirtualDimensions()) || context.condensed))() && horizontalViewPort().isVisible(horizontalDimensions());
|
|
257
222
|
},
|
|
258
223
|
get children() {
|
|
259
|
-
const _el$2 = _tmpl$$
|
|
224
|
+
const _el$2 = _tmpl$$6.cloneNode(true);
|
|
260
225
|
_el$2.$$mousedown = event => {
|
|
261
226
|
event.stopPropagation();
|
|
262
227
|
setIsDragging(true);
|
|
@@ -266,7 +231,7 @@ const PianoRollNotes = props => {
|
|
|
266
231
|
const ticks = snapValueToGridIfEnabled(Math.max(horizontalViewPort().calculatePosition(mouseMoveEvent.clientX) - diffPosition, 0), mouseMoveEvent.altKey);
|
|
267
232
|
context.onNoteChange?.(index, {
|
|
268
233
|
...note(),
|
|
269
|
-
...(noteDragMode() === "move" && {
|
|
234
|
+
...(noteDragMode() === "move" && !context.condensed && {
|
|
270
235
|
midi: Math.round(127 - verticalViewPort().calculatePosition(mouseMoveEvent.clientY))
|
|
271
236
|
}),
|
|
272
237
|
...((noteDragMode() === "move" || noteDragMode() === "trimStart") && {
|
|
@@ -302,38 +267,37 @@ const PianoRollNotes = props => {
|
|
|
302
267
|
};
|
|
303
268
|
web.effect(_p$ => {
|
|
304
269
|
const _v$ = getClasses(noteDragMode()).join(" "),
|
|
305
|
-
_v$2 =
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
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
|
+
};
|
|
310
282
|
_v$ !== _p$._v$ && web.className(_el$2, _p$._v$ = _v$);
|
|
311
|
-
|
|
312
|
-
_v$3 !== _p$._v$3 && _el$2.style.setProperty("top", _p$._v$3 = _v$3);
|
|
313
|
-
_v$4 !== _p$._v$4 && _el$2.style.setProperty("height", _p$._v$4 = _v$4);
|
|
314
|
-
_v$5 !== _p$._v$5 && _el$2.style.setProperty("left", _p$._v$5 = _v$5);
|
|
315
|
-
_v$6 !== _p$._v$6 && _el$2.style.setProperty("width", _p$._v$6 = _v$6);
|
|
283
|
+
_p$._v$2 = web.style(_el$2, _v$2, _p$._v$2);
|
|
316
284
|
return _p$;
|
|
317
285
|
}, {
|
|
318
286
|
_v$: undefined,
|
|
319
|
-
_v$2: undefined
|
|
320
|
-
_v$3: undefined,
|
|
321
|
-
_v$4: undefined,
|
|
322
|
-
_v$5: undefined,
|
|
323
|
-
_v$6: undefined
|
|
287
|
+
_v$2: undefined
|
|
324
288
|
});
|
|
325
289
|
return _el$2;
|
|
326
290
|
}
|
|
327
291
|
});
|
|
328
292
|
}
|
|
329
293
|
}));
|
|
330
|
-
web.effect(() => web.className(_el$, styles$
|
|
294
|
+
web.effect(() => web.className(_el$, styles$2.PianoRollNotes));
|
|
331
295
|
return _el$;
|
|
332
296
|
})();
|
|
333
297
|
};
|
|
334
298
|
web.delegateEvents(["mousedown", "mousemove", "mouseup", "dblclick", "click"]);
|
|
335
299
|
|
|
336
|
-
const _tmpl$$
|
|
300
|
+
const _tmpl$$5 = /*#__PURE__*/web.template(`<div class="PianoRoll-Scroller"><div><div><div></div></div></div></div>`, 8);
|
|
337
301
|
const ScrollContainer = props => {
|
|
338
302
|
let scrollContentRef;
|
|
339
303
|
const verticalViewPort = solidJs.createMemo(() => useViewPortDimension("vertical"));
|
|
@@ -395,7 +359,7 @@ const ScrollContainer = props => {
|
|
|
395
359
|
});
|
|
396
360
|
});
|
|
397
361
|
return (() => {
|
|
398
|
-
const _el$ = _tmpl$$
|
|
362
|
+
const _el$ = _tmpl$$5.cloneNode(true),
|
|
399
363
|
_el$2 = _el$.firstChild,
|
|
400
364
|
_el$3 = _el$2.firstChild,
|
|
401
365
|
_el$4 = _el$3.firstChild;
|
|
@@ -436,6 +400,69 @@ const ScrollContainer = props => {
|
|
|
436
400
|
})();
|
|
437
401
|
};
|
|
438
402
|
|
|
403
|
+
var css_248z$1 = ".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";
|
|
404
|
+
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
|
+
styleInject(css_248z$1);
|
|
406
|
+
|
|
407
|
+
const _tmpl$$4 = /*#__PURE__*/web.template(`<div></div>`, 2);
|
|
408
|
+
const PianoRollKeys = () => {
|
|
409
|
+
const viewPort = solidJs.createMemo(() => useViewPortDimension("vertical"));
|
|
410
|
+
return (() => {
|
|
411
|
+
const _el$ = _tmpl$$4.cloneNode(true);
|
|
412
|
+
web.insert(_el$, web.createComponent(solidJs.Index, {
|
|
413
|
+
each: keys,
|
|
414
|
+
children: key => {
|
|
415
|
+
const virtualDimensions = solidJs.createMemo(() => viewPort().calculatePixelDimensions(127 - key().number, 1));
|
|
416
|
+
return web.createComponent(solidJs.Show, {
|
|
417
|
+
get when() {
|
|
418
|
+
return virtualDimensions().size > 0;
|
|
419
|
+
},
|
|
420
|
+
get children() {
|
|
421
|
+
const _el$2 = _tmpl$$4.cloneNode(true);
|
|
422
|
+
web.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$ = web.classList(_el$2, _v$, _p$._v$);
|
|
435
|
+
_v$2 !== _p$._v$2 && web.setAttribute(_el$2, "title", _p$._v$2 = _v$2);
|
|
436
|
+
_v$3 !== _p$._v$3 && web.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
|
+
web.effect(() => web.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
|
+
|
|
439
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";
|
|
440
467
|
var styles = {"PianoRollGrid":"PianoRollGrid-module_PianoRollGrid__tG119","PianoRollGrid-Key":"PianoRollGrid-module_PianoRollGrid-Key__VRbiB","PianoRollGrid-Time":"PianoRollGrid-module_PianoRollGrid-Time__jLz3E"};
|
|
441
468
|
styleInject(css_248z);
|
|
@@ -552,6 +579,30 @@ const PianoRollGrid = () => {
|
|
|
552
579
|
})();
|
|
553
580
|
};
|
|
554
581
|
|
|
582
|
+
const useNotes = () => {
|
|
583
|
+
const [notes, onNotesChange] = solidJs.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
|
+
|
|
555
606
|
const defaultRect = {
|
|
556
607
|
left: 0,
|
|
557
608
|
width: 0,
|
|
@@ -608,29 +659,198 @@ const VerticalZoomControl = props => {
|
|
|
608
659
|
})();
|
|
609
660
|
};
|
|
610
661
|
|
|
611
|
-
const _tmpl$$1 = /*#__PURE__*/web.template(`<
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
662
|
+
const _tmpl$$1 = /*#__PURE__*/web.template(`<ul></ul>`, 2),
|
|
663
|
+
_tmpl$2 = /*#__PURE__*/web.template(`<div><ul></ul><div><div></div></div></div>`, 8),
|
|
664
|
+
_tmpl$3 = /*#__PURE__*/web.template(`<li></li>`, 2);
|
|
665
|
+
const MultiTrackPianoRoll = allProps => {
|
|
666
|
+
const condensed = solidJs.createMemo(() => !allProps.selectedTrack);
|
|
667
|
+
const [ownProps, restProps] = solidJs.splitProps(allProps, ["tracks", "selectedTrack"]);
|
|
668
|
+
const [contextProps, divProps] = splitContextProps(solidJs.mergeProps(restProps, {
|
|
669
|
+
notes: [],
|
|
670
|
+
condensed: false
|
|
671
|
+
}));
|
|
672
|
+
const [scrollerRef, setScrollerRef] = solidJs.createSignal();
|
|
673
|
+
const clientRect = useBoundingClientRect(scrollerRef);
|
|
674
|
+
const zoomFactor = 500;
|
|
675
|
+
const minZoom = solidJs.createMemo(() => 1 / (zoomFactor / clientRect().width));
|
|
676
|
+
const maxZoom = solidJs.createMemo(() => 500 * (zoomFactor / clientRect().width));
|
|
677
|
+
const minVerticalZoom = solidJs.createMemo(() => 1 / (zoomFactor / clientRect().height));
|
|
678
|
+
const maxVerticalZoom = solidJs.createMemo(() => 10 * (zoomFactor / clientRect().height));
|
|
679
|
+
return web.createComponent(PianoRollContextProvider, {
|
|
680
|
+
get value() {
|
|
681
|
+
return {
|
|
682
|
+
...contextProps
|
|
683
|
+
};
|
|
684
|
+
},
|
|
685
|
+
get children() {
|
|
686
|
+
return web.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
|
+
web.insert(_el$2, web.createComponent(solidJs.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
|
+
web.insert(_el$6, () => track().name);
|
|
740
|
+
web.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
|
+
web.insert(_el$4, web.createComponent(solidJs.Show, {
|
|
746
|
+
get when() {
|
|
747
|
+
return !condensed();
|
|
748
|
+
},
|
|
749
|
+
get children() {
|
|
750
|
+
return web.createComponent(PianoRollKeys, {});
|
|
751
|
+
}
|
|
752
|
+
}), null);
|
|
753
|
+
web.insert(_el$4, web.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
|
+
web.insert(_el$5, web.createComponent(solidJs.Index, {
|
|
761
|
+
get each() {
|
|
762
|
+
return allProps.tracks;
|
|
763
|
+
},
|
|
764
|
+
children: track => {
|
|
765
|
+
const notes = useNotes();
|
|
766
|
+
solidJs.createEffect(() => {
|
|
767
|
+
notes.onNotesChange(track().notes);
|
|
768
|
+
});
|
|
769
|
+
const [context, setContext] = store.createStore({
|
|
770
|
+
...contextProps
|
|
771
|
+
});
|
|
772
|
+
solidJs.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 web.createComponent(solidJs.Show, {
|
|
784
|
+
get when() {
|
|
785
|
+
return condensed() || allProps.selectedTrack === track();
|
|
786
|
+
},
|
|
787
|
+
get children() {
|
|
788
|
+
return web.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
|
+
web.insert(_el$7, web.createComponent(PianoRollNotes, {}), null);
|
|
798
|
+
web.insert(_el$7, web.createComponent(PianoRollGrid, {}), null);
|
|
799
|
+
web.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
|
+
web.insert(_el$4, web.createComponent(solidJs.Show, {
|
|
811
|
+
get when() {
|
|
812
|
+
return !condensed();
|
|
813
|
+
},
|
|
814
|
+
get children() {
|
|
815
|
+
return web.createComponent(VerticalZoomControl, {
|
|
816
|
+
get value() {
|
|
817
|
+
return contextProps.verticalZoom;
|
|
818
|
+
},
|
|
819
|
+
onInput: event => contextProps.onVerticalZoomChange?.(event.currentTarget.valueAsNumber)
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
}), null);
|
|
823
|
+
web.insert(_el$3, web.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
|
+
web.effect(_p$ => {
|
|
834
|
+
const _v$ = styles$3.PianoRoll,
|
|
835
|
+
_v$2 = styles$3.PianoRollContainer;
|
|
836
|
+
_v$ !== _p$._v$ && web.className(_el$3, _p$._v$ = _v$);
|
|
837
|
+
_v$2 !== _p$._v$2 && web.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
|
+
});
|
|
629
848
|
};
|
|
849
|
+
web.delegateEvents(["click"]);
|
|
630
850
|
|
|
631
851
|
const _tmpl$ = /*#__PURE__*/web.template(`<div><div></div></div>`, 4);
|
|
632
852
|
const PianoRoll = allProps => {
|
|
633
|
-
const [contextProps, divProps] =
|
|
853
|
+
const [contextProps, divProps] = splitContextProps(allProps);
|
|
634
854
|
const [scrollerRef, setScrollerRef] = solidJs.createSignal();
|
|
635
855
|
const clientRect = useBoundingClientRect(scrollerRef);
|
|
636
856
|
const zoomFactor = 500;
|
|
@@ -701,33 +921,14 @@ const PianoRoll = allProps => {
|
|
|
701
921
|
|
|
702
922
|
const usePianoRoll = () => {
|
|
703
923
|
const [ppq, onPpqChange] = solidJs.createSignal(120);
|
|
924
|
+
const [condensed, onCondensedChange] = solidJs.createSignal(false);
|
|
704
925
|
const [position, onPositionChange] = solidJs.createSignal(0);
|
|
705
926
|
const [zoom, onZoomChange] = solidJs.createSignal(10);
|
|
706
927
|
const [verticalZoom, onVerticalZoomChange] = solidJs.createSignal(5);
|
|
707
928
|
const [verticalPosition, onVerticalPositionChange] = solidJs.createSignal(64);
|
|
708
929
|
const [gridDivision, onGridDivisionChange] = solidJs.createSignal(16);
|
|
709
930
|
const [snapToGrid, onSnapToGridChange] = solidJs.createSignal(true);
|
|
710
|
-
const [notes, onNotesChange] = solidJs.createSignal([]);
|
|
711
931
|
const [duration, onDurationChange] = solidJs.createSignal(0);
|
|
712
|
-
const onNoteChange = (index, note) => {
|
|
713
|
-
onNotesChange([...notes().slice(0, index), note, ...notes().splice(index + 1)]);
|
|
714
|
-
};
|
|
715
|
-
const onInsertNote = note => {
|
|
716
|
-
const index = Math.max(notes().findIndex(({
|
|
717
|
-
ticks
|
|
718
|
-
}) => ticks > note.ticks), 0);
|
|
719
|
-
onNotesChange([...notes().slice(0, index), note, ...notes().splice(index)]);
|
|
720
|
-
return index;
|
|
721
|
-
};
|
|
722
|
-
const onRemoveNote = index => {
|
|
723
|
-
onNotesChange([...notes().slice(0, index), ...notes().splice(index + 1)]);
|
|
724
|
-
};
|
|
725
|
-
solidJs.createEffect(() => {
|
|
726
|
-
const minDuration = Math.max((notes()[notes().length - 1]?.ticks ?? 0) + (notes()[notes().length - 1]?.durationTicks ?? 0), ppq() * 4 * 4);
|
|
727
|
-
if (duration() < minDuration) {
|
|
728
|
-
onDurationChange(minDuration);
|
|
729
|
-
}
|
|
730
|
-
});
|
|
731
932
|
return {
|
|
732
933
|
ppq,
|
|
733
934
|
onPpqChange,
|
|
@@ -743,16 +944,15 @@ const usePianoRoll = () => {
|
|
|
743
944
|
onGridDivisionChange,
|
|
744
945
|
snapToGrid,
|
|
745
946
|
onSnapToGridChange,
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
onNoteChange,
|
|
749
|
-
onInsertNote,
|
|
750
|
-
onRemoveNote,
|
|
947
|
+
condensed,
|
|
948
|
+
onCondensedChange,
|
|
751
949
|
duration,
|
|
752
950
|
onDurationChange
|
|
753
951
|
};
|
|
754
952
|
};
|
|
755
953
|
|
|
954
|
+
exports.MultiTrackPianoRoll = MultiTrackPianoRoll;
|
|
756
955
|
exports.PianoRoll = PianoRoll;
|
|
956
|
+
exports.useNotes = useNotes;
|
|
757
957
|
exports.usePianoRoll = usePianoRoll;
|
|
758
958
|
//# sourceMappingURL=index.js.map
|