solid-pianoroll 0.0.24 → 0.0.26
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 → dev.cjs} +408 -430
- package/dist/dev.css +212 -0
- package/dist/dev.js +1330 -0
- package/dist/dev.jsx +1130 -0
- package/dist/index.cjs +1330 -0
- package/dist/index.css +212 -0
- package/dist/{types/usePianoRollState.d.ts → index.d.ts} +38 -6
- package/dist/{esm/index.js → index.js} +412 -429
- package/dist/index.jsx +1130 -0
- package/package.json +46 -34
- package/dist/cjs/index.js.map +0 -1
- package/dist/esm/index.js.map +0 -1
- package/dist/source/PianoRoll.jsx +0 -82
- package/dist/source/PianoRollContext.jsx +0 -11
- package/dist/source/PianoRollGrid.jsx +0 -64
- package/dist/source/PianoRollKeys.jsx +0 -72
- package/dist/source/PianoRollNotes.jsx +0 -160
- package/dist/source/PianoRollNotesScroller.jsx +0 -16
- package/dist/source/PianoRollScale.jsx +0 -43
- package/dist/source/PianoRollScrollZoomViewPort.jsx +0 -49
- package/dist/source/PianoRollTrackList.jsx +0 -27
- package/dist/source/PianoRollTrackListScroller.jsx +0 -16
- package/dist/source/index.jsx +0 -5
- package/dist/source/types.js +0 -1
- package/dist/source/useBoundingClientRect.js +0 -29
- package/dist/source/useNotes.js +0 -23
- package/dist/source/usePianoRollGrid.js +0 -45
- package/dist/source/usePianoRollState.js +0 -126
- package/dist/source/viewport/PlayHead.jsx +0 -43
- package/dist/source/viewport/ScrollZoomContainer.jsx +0 -104
- package/dist/source/viewport/ScrollZoomViewPort.jsx +0 -31
- package/dist/source/viewport/ZoomSliderControl.jsx +0 -29
- package/dist/source/viewport/createViewPortDimension.js +0 -51
- package/dist/types/PianoRoll.d.ts +0 -8
- package/dist/types/PianoRollContext.d.ts +0 -45
- package/dist/types/PianoRollGrid.d.ts +0 -2
- package/dist/types/PianoRollKeys.d.ts +0 -9
- package/dist/types/PianoRollNotes.d.ts +0 -5
- package/dist/types/PianoRollNotesScroller.d.ts +0 -3
- package/dist/types/PianoRollScale.d.ts +0 -2
- package/dist/types/PianoRollScrollZoomViewPort.d.ts +0 -3
- package/dist/types/PianoRollTrackList.d.ts +0 -2
- package/dist/types/PianoRollTrackListScroller.d.ts +0 -3
- package/dist/types/index.d.ts +0 -6
- package/dist/types/types.d.ts +0 -8
- package/dist/types/useBoundingClientRect.d.ts +0 -3
- package/dist/types/useNotes.d.ts +0 -9
- package/dist/types/usePianoRollGrid.d.ts +0 -13
- package/dist/types/viewport/PlayHead.d.ts +0 -8
- package/dist/types/viewport/ScrollZoomContainer.d.ts +0 -8
- package/dist/types/viewport/ScrollZoomViewPort.d.ts +0 -39
- package/dist/types/viewport/ZoomSliderControl.d.ts +0 -6
- package/dist/types/viewport/createViewPortDimension.d.ts +0 -40
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1330 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var web = require('solid-js/web');
|
|
4
|
+
var solidJs = require('solid-js');
|
|
5
|
+
var store = require('solid-js/store');
|
|
6
|
+
|
|
7
|
+
var __defProp = Object.defineProperty;
|
|
8
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
9
|
+
|
|
10
|
+
// css-module:./PianoRoll.module.css#css-module
|
|
11
|
+
var PianoRoll_module_default = { "PianoRoll": "_PianoRoll_1v1e7_1", "PianoRollContainer": "_PianoRollContainer_1v1e7_10", "PianoRollLeftColumn": "_PianoRollLeftColumn_1v1e7_17", "showTrackList": "_showTrackList_1v1e7_24", "PianoRollRightColumn": "_PianoRollRightColumn_1v1e7_29" };
|
|
12
|
+
var defaultState = {
|
|
13
|
+
ppq: 0,
|
|
14
|
+
mode: "keys",
|
|
15
|
+
position: 0,
|
|
16
|
+
zoom: 10,
|
|
17
|
+
verticalZoom: 5,
|
|
18
|
+
verticalPosition: 44,
|
|
19
|
+
verticalTrackZoom: 0.5,
|
|
20
|
+
verticalTrackPosition: 0,
|
|
21
|
+
playHeadPosition: 0,
|
|
22
|
+
gridDivision: 4,
|
|
23
|
+
snapToGrid: true,
|
|
24
|
+
duration: 0,
|
|
25
|
+
tracks: [],
|
|
26
|
+
selectedTrackIndex: 0,
|
|
27
|
+
pressedKeys: {},
|
|
28
|
+
notesScrollerClientRect: { left: 0, width: 0, top: 0, height: 0 },
|
|
29
|
+
tracksScrollerClientRect: { left: 0, width: 0, top: 0, height: 0 }
|
|
30
|
+
};
|
|
31
|
+
var propNameToHandlerName = /* @__PURE__ */ __name((name) => `on${name[0]?.toUpperCase()}${name.slice(1)}Change`, "propNameToHandlerName");
|
|
32
|
+
var pianoRollStatePropNames = [
|
|
33
|
+
...Object.keys(defaultState),
|
|
34
|
+
...Object.keys(defaultState).map(propNameToHandlerName),
|
|
35
|
+
"onNoteChange",
|
|
36
|
+
"onInsertNote",
|
|
37
|
+
"onRemoveNote",
|
|
38
|
+
"onNoteDown",
|
|
39
|
+
"onNoteUp",
|
|
40
|
+
"isKeyDown",
|
|
41
|
+
"snapValueToGridIfEnabled"
|
|
42
|
+
];
|
|
43
|
+
var createPianoRollstate = /* @__PURE__ */ __name((initialState) => {
|
|
44
|
+
const [state, setState] = store.createStore({
|
|
45
|
+
...defaultState,
|
|
46
|
+
...initialState
|
|
47
|
+
});
|
|
48
|
+
const handlers = Object.fromEntries(
|
|
49
|
+
Object.entries(state).map((entry) => {
|
|
50
|
+
const handlerName = propNameToHandlerName(entry[0]);
|
|
51
|
+
return [
|
|
52
|
+
handlerName,
|
|
53
|
+
(value, originalEvent) => {
|
|
54
|
+
const handler = initialState?.[handlerName];
|
|
55
|
+
setState(entry[0], value);
|
|
56
|
+
if (handler) {
|
|
57
|
+
handler(value, originalEvent);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
];
|
|
61
|
+
})
|
|
62
|
+
);
|
|
63
|
+
const onPlayheadPositionChange = /* @__PURE__ */ __name((playheadPosition, originalEvent) => {
|
|
64
|
+
handlers.onPlayHeadPositionChange(
|
|
65
|
+
snapValueToGridIfEnabled(playheadPosition, !!originalEvent?.altKey)
|
|
66
|
+
);
|
|
67
|
+
}, "onPlayheadPositionChange");
|
|
68
|
+
const updateNotes = /* @__PURE__ */ __name(async (trackIndex, getNotes) => {
|
|
69
|
+
const track = state.tracks[trackIndex];
|
|
70
|
+
if (!track)
|
|
71
|
+
return;
|
|
72
|
+
const notes = track.notes;
|
|
73
|
+
handlers.onTracksChange([
|
|
74
|
+
...state.tracks.slice(0, trackIndex),
|
|
75
|
+
{ ...track, notes: getNotes(notes) },
|
|
76
|
+
...state.tracks.slice(trackIndex + 1)
|
|
77
|
+
]);
|
|
78
|
+
}, "updateNotes");
|
|
79
|
+
const onNoteChange = /* @__PURE__ */ __name((trackIndex, noteIndex, note) => {
|
|
80
|
+
updateNotes(trackIndex, (notes) => [
|
|
81
|
+
...notes.slice(0, noteIndex),
|
|
82
|
+
note,
|
|
83
|
+
...notes.slice(noteIndex + 1)
|
|
84
|
+
]);
|
|
85
|
+
}, "onNoteChange");
|
|
86
|
+
const onInsertNote = /* @__PURE__ */ __name((trackIndex, note) => {
|
|
87
|
+
const track = state.tracks[trackIndex];
|
|
88
|
+
if (!track)
|
|
89
|
+
return -1;
|
|
90
|
+
const notes = track.notes;
|
|
91
|
+
const newNoteIndex = Math.max(
|
|
92
|
+
notes.findIndex(({ ticks }) => ticks > note.ticks),
|
|
93
|
+
0
|
|
94
|
+
);
|
|
95
|
+
updateNotes(trackIndex, (notes2) => [
|
|
96
|
+
...notes2.slice(0, newNoteIndex),
|
|
97
|
+
note,
|
|
98
|
+
...notes2.slice(newNoteIndex)
|
|
99
|
+
]);
|
|
100
|
+
return newNoteIndex;
|
|
101
|
+
}, "onInsertNote");
|
|
102
|
+
const onRemoveNote = /* @__PURE__ */ __name((trackIndex, noteIndex) => {
|
|
103
|
+
updateNotes(trackIndex, (notes) => [
|
|
104
|
+
...notes.slice(0, noteIndex),
|
|
105
|
+
...notes.slice(noteIndex + 1)
|
|
106
|
+
]);
|
|
107
|
+
}, "onRemoveNote");
|
|
108
|
+
const updateKeyPressedState = /* @__PURE__ */ __name((trackIndex, keyNumber, value) => {
|
|
109
|
+
handlers.onPressedKeysChange?.({
|
|
110
|
+
...state.pressedKeys,
|
|
111
|
+
[trackIndex]: {
|
|
112
|
+
...state.pressedKeys[trackIndex],
|
|
113
|
+
[keyNumber]: value
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}, "updateKeyPressedState");
|
|
117
|
+
const onNoteDown = /* @__PURE__ */ __name((trackIndex, keyNumber) => {
|
|
118
|
+
updateKeyPressedState(trackIndex, keyNumber, true);
|
|
119
|
+
}, "onNoteDown");
|
|
120
|
+
const onNoteUp = /* @__PURE__ */ __name((trackIndex, keyNumber) => {
|
|
121
|
+
updateKeyPressedState(trackIndex, keyNumber, false);
|
|
122
|
+
}, "onNoteUp");
|
|
123
|
+
const isKeyDown = /* @__PURE__ */ __name((trackIndex, keyNumber) => !!state.pressedKeys[trackIndex]?.[keyNumber], "isKeyDown");
|
|
124
|
+
const snapValueToGridIfEnabled = /* @__PURE__ */ __name((value, altKey) => {
|
|
125
|
+
const gridDivisionTicks = state.ppq * 4 / state.gridDivision;
|
|
126
|
+
return state.snapToGrid && !altKey ? Math.round(value / gridDivisionTicks) * gridDivisionTicks : value;
|
|
127
|
+
}, "snapValueToGridIfEnabled");
|
|
128
|
+
return solidJs.mergeProps(state, {
|
|
129
|
+
...handlers,
|
|
130
|
+
onNoteChange,
|
|
131
|
+
onInsertNote,
|
|
132
|
+
onRemoveNote,
|
|
133
|
+
onNoteDown,
|
|
134
|
+
onNoteUp,
|
|
135
|
+
isKeyDown,
|
|
136
|
+
snapValueToGridIfEnabled,
|
|
137
|
+
onPlayheadPositionChange
|
|
138
|
+
});
|
|
139
|
+
}, "createPianoRollstate");
|
|
140
|
+
exports.createPianoRollstate = createPianoRollstate;
|
|
141
|
+
|
|
142
|
+
// src/PianoRollContext.tsx
|
|
143
|
+
var PianoRollContext = solidJs.createContext();
|
|
144
|
+
var PianoRollContextProvider = PianoRollContext.Provider;
|
|
145
|
+
var usePianoRollContext = /* @__PURE__ */ __name(() => {
|
|
146
|
+
const context = solidJs.useContext(PianoRollContext);
|
|
147
|
+
if (!context)
|
|
148
|
+
throw new Error("No PianoRollContext found");
|
|
149
|
+
return context;
|
|
150
|
+
}, "usePianoRollContext");
|
|
151
|
+
var splitContextProps = /* @__PURE__ */ __name((allProps) => solidJs.splitProps(allProps, [...pianoRollStatePropNames, "showAllTracks", "showTrackList"]), "splitContextProps");
|
|
152
|
+
|
|
153
|
+
// css-module:./PianoRollKeys.module.css#css-module
|
|
154
|
+
var PianoRollKeys_module_default = { "PianoRollKeys": "_PianoRollKeys_1ne9i_1", "Key": "_Key_1ne9i_14", "black": "_black_1ne9i_29", "white": "_white_1ne9i_38", "down": "_down_1ne9i_46" };
|
|
155
|
+
function createViewPortDimension(getState) {
|
|
156
|
+
const getStateWithFunctions = /* @__PURE__ */ __name(() => {
|
|
157
|
+
const state2 = getState();
|
|
158
|
+
const onZoomChange = /* @__PURE__ */ __name((zoom) => state2.onZoomChange?.(clamp(zoom, state2.minZoom, state2.maxZoom)), "onZoomChange");
|
|
159
|
+
const onPositionChange = /* @__PURE__ */ __name((position) => state2.onPositionChange?.(position), "onPositionChange");
|
|
160
|
+
return {
|
|
161
|
+
...state2,
|
|
162
|
+
onZoomChange,
|
|
163
|
+
onPositionChange,
|
|
164
|
+
calculatePixelOffset,
|
|
165
|
+
calculatePixelValue,
|
|
166
|
+
calculatePosition,
|
|
167
|
+
calculatePixelDimensions,
|
|
168
|
+
calculateVisibleRange,
|
|
169
|
+
calculateMaxPosition,
|
|
170
|
+
isVisible
|
|
171
|
+
};
|
|
172
|
+
}, "getStateWithFunctions");
|
|
173
|
+
const [state, setState] = store.createStore(getStateWithFunctions());
|
|
174
|
+
solidJs.createEffect(() => setState(getStateWithFunctions()));
|
|
175
|
+
function calculatePixelValue(position = state.position) {
|
|
176
|
+
const virtualSize = state.pixelSize * state.zoom;
|
|
177
|
+
return position / state.range * virtualSize;
|
|
178
|
+
}
|
|
179
|
+
__name(calculatePixelValue, "calculatePixelValue");
|
|
180
|
+
function calculatePixelOffset(position) {
|
|
181
|
+
return calculatePixelValue(position) - calculatePixelValue(state.position);
|
|
182
|
+
}
|
|
183
|
+
__name(calculatePixelOffset, "calculatePixelOffset");
|
|
184
|
+
function calculatePosition(offset) {
|
|
185
|
+
const percentX = (offset - state.pixelOffset) / state.pixelSize;
|
|
186
|
+
const position = state.position + percentX * calculateVisibleRange();
|
|
187
|
+
return position;
|
|
188
|
+
}
|
|
189
|
+
__name(calculatePosition, "calculatePosition");
|
|
190
|
+
function calculateVisibleRange() {
|
|
191
|
+
return state.range / state.zoom;
|
|
192
|
+
}
|
|
193
|
+
__name(calculateVisibleRange, "calculateVisibleRange");
|
|
194
|
+
function calculateMaxPosition() {
|
|
195
|
+
return state.range - state.range / state.zoom;
|
|
196
|
+
}
|
|
197
|
+
__name(calculateMaxPosition, "calculateMaxPosition");
|
|
198
|
+
function calculatePixelDimensions(position, length) {
|
|
199
|
+
const offset = calculatePixelOffset(position);
|
|
200
|
+
const size = calculatePixelValue(length);
|
|
201
|
+
return { offset, size };
|
|
202
|
+
}
|
|
203
|
+
__name(calculatePixelDimensions, "calculatePixelDimensions");
|
|
204
|
+
function isVisible({ offset, size }) {
|
|
205
|
+
return offset + size > 0 && offset < state.pixelSize;
|
|
206
|
+
}
|
|
207
|
+
__name(isVisible, "isVisible");
|
|
208
|
+
return state;
|
|
209
|
+
}
|
|
210
|
+
__name(createViewPortDimension, "createViewPortDimension");
|
|
211
|
+
var clamp = /* @__PURE__ */ __name((value, min, max) => Math.max(min, Math.min(max, value)), "clamp");
|
|
212
|
+
|
|
213
|
+
// src/viewport/ScrollZoomViewPort.tsx
|
|
214
|
+
var defaultViewPortProps = {
|
|
215
|
+
pixelOffset: 0,
|
|
216
|
+
position: 0,
|
|
217
|
+
range: 1,
|
|
218
|
+
zoom: 1,
|
|
219
|
+
minZoom: 1,
|
|
220
|
+
maxZoom: Infinity
|
|
221
|
+
};
|
|
222
|
+
var ScrollZoomViewPort = /* @__PURE__ */ __name((props) => {
|
|
223
|
+
const viewPorts = Object.entries(props.dimensions).map(([name, viewPortProps]) => createViewPortDimension(() => ({
|
|
224
|
+
name,
|
|
225
|
+
...defaultViewPortProps,
|
|
226
|
+
...viewPortProps()
|
|
227
|
+
})));
|
|
228
|
+
const parentViewPorts = solidJs.useContext(ScrollZoomViewPortContext);
|
|
229
|
+
return web.createComponent(ScrollZoomViewPortContext.Provider, {
|
|
230
|
+
get value() {
|
|
231
|
+
return [...parentViewPorts, ...viewPorts];
|
|
232
|
+
},
|
|
233
|
+
get children() {
|
|
234
|
+
return props.children;
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
}, "ScrollZoomViewPort");
|
|
238
|
+
var ScrollZoomViewPortContext = solidJs.createContext([]);
|
|
239
|
+
var useViewPortDimension = /* @__PURE__ */ __name((name) => {
|
|
240
|
+
const viewPorts = solidJs.useContext(ScrollZoomViewPortContext);
|
|
241
|
+
const viewPort = name ? viewPorts.find((viewPort2) => viewPort2.name === name) : viewPorts[viewPorts.length - 1];
|
|
242
|
+
if (!viewPort)
|
|
243
|
+
throw new Error(`ViewPort dimension "${name}" not found.`);
|
|
244
|
+
return viewPort;
|
|
245
|
+
}, "useViewPortDimension");
|
|
246
|
+
|
|
247
|
+
// css-module:./ScrollZoomContainer.module.css#css-module
|
|
248
|
+
var ScrollZoomContainer_module_default = { "ScrollZoomContainer": "_ScrollZoomContainer_f395r_1" };
|
|
249
|
+
|
|
250
|
+
// src/viewport/ScrollZoomContainer.tsx
|
|
251
|
+
var _tmpl$ = /* @__PURE__ */ web.template(`<div><div><div><div></div></div></div></div>`, 8);
|
|
252
|
+
var ScrollZoomContainer = /* @__PURE__ */ __name((props) => {
|
|
253
|
+
let scrollContentRef;
|
|
254
|
+
const [ownProps, divProps] = solidJs.splitProps(props, ["ref", "verticalDimensionName", "horizontalDimensionName", "showScrollbar"]);
|
|
255
|
+
const propsWithDefaults = solidJs.mergeProps({
|
|
256
|
+
verticalDimensionName: "vertical",
|
|
257
|
+
horizontalDimensionName: "horizontal",
|
|
258
|
+
showScrollbar: true
|
|
259
|
+
}, ownProps);
|
|
260
|
+
const verticalViewPort = solidJs.createMemo(() => useViewPortDimension(propsWithDefaults.verticalDimensionName));
|
|
261
|
+
const horizontalViewPort = solidJs.createMemo(() => useViewPortDimension(propsWithDefaults.horizontalDimensionName));
|
|
262
|
+
const handleScroll = /* @__PURE__ */ __name((event) => {
|
|
263
|
+
event.preventDefault();
|
|
264
|
+
if (didUpdateScroll) {
|
|
265
|
+
didUpdateScroll = false;
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
const maxVerticalPosition = verticalViewPort().calculateMaxPosition();
|
|
269
|
+
const maxPosition = horizontalViewPort().calculateMaxPosition();
|
|
270
|
+
const height = verticalViewPort().pixelSize;
|
|
271
|
+
const width = horizontalViewPort().pixelSize;
|
|
272
|
+
const {
|
|
273
|
+
scrollTop,
|
|
274
|
+
scrollLeft,
|
|
275
|
+
scrollWidth,
|
|
276
|
+
scrollHeight
|
|
277
|
+
} = event.currentTarget;
|
|
278
|
+
const scrollTopAmount = scrollTop / (scrollHeight - height);
|
|
279
|
+
const scrollLeftAmount = scrollLeft / (scrollWidth - width);
|
|
280
|
+
verticalViewPort().onPositionChange?.(maxVerticalPosition * scrollTopAmount);
|
|
281
|
+
horizontalViewPort().onPositionChange?.(maxPosition * scrollLeftAmount);
|
|
282
|
+
}, "handleScroll");
|
|
283
|
+
const handleWheel = /* @__PURE__ */ __name((event) => {
|
|
284
|
+
if (event.altKey) {
|
|
285
|
+
event.preventDefault();
|
|
286
|
+
if (Math.abs(event.deltaX) > Math.abs(event.deltaY)) {
|
|
287
|
+
horizontalViewPort()?.onZoomChange?.(horizontalViewPort().zoom / (1 + event.deltaX / horizontalViewPort().pixelSize));
|
|
288
|
+
const maxPosition = horizontalViewPort().calculateMaxPosition();
|
|
289
|
+
horizontalViewPort()?.onPositionChange?.(Math.min(maxPosition, horizontalViewPort()?.position));
|
|
290
|
+
} else {
|
|
291
|
+
verticalViewPort()?.onZoomChange?.(verticalViewPort().zoom / (1 + event.deltaY / verticalViewPort().pixelSize));
|
|
292
|
+
const maxVerticalPosition = verticalViewPort().calculateMaxPosition();
|
|
293
|
+
verticalViewPort()?.onPositionChange?.(Math.min(maxVerticalPosition, verticalViewPort()?.position));
|
|
294
|
+
}
|
|
295
|
+
} else if (!props.showScrollbar) {
|
|
296
|
+
event.preventDefault();
|
|
297
|
+
event.currentTarget.scrollLeft += event.deltaX;
|
|
298
|
+
event.currentTarget.scrollTop += event.deltaY;
|
|
299
|
+
}
|
|
300
|
+
}, "handleWheel");
|
|
301
|
+
let didUpdateScroll = false;
|
|
302
|
+
solidJs.createEffect(() => {
|
|
303
|
+
const maxVerticalPosition = verticalViewPort().calculateMaxPosition();
|
|
304
|
+
const maxPosition = horizontalViewPort().calculateMaxPosition();
|
|
305
|
+
const scrollTopAmount = maxVerticalPosition > 0 ? verticalViewPort().position / maxVerticalPosition : 0;
|
|
306
|
+
const scrollLeftAmount = maxPosition > 0 ? horizontalViewPort().position / maxPosition : 0;
|
|
307
|
+
const height = verticalViewPort().pixelSize;
|
|
308
|
+
const width = horizontalViewPort().pixelSize;
|
|
309
|
+
if (!scrollContentRef?.parentElement)
|
|
310
|
+
return;
|
|
311
|
+
const scrollDivHeight = verticalViewPort().zoom * verticalViewPort().pixelSize;
|
|
312
|
+
const scrollTop = scrollTopAmount * (scrollDivHeight - height);
|
|
313
|
+
const scrollDivWidth = horizontalViewPort().zoom * horizontalViewPort().pixelSize;
|
|
314
|
+
const scrollLeft = scrollLeftAmount * (scrollDivWidth - width);
|
|
315
|
+
didUpdateScroll = true;
|
|
316
|
+
scrollContentRef.style.height = `${scrollDivHeight}px`;
|
|
317
|
+
scrollContentRef.style.width = `${scrollDivWidth}px`;
|
|
318
|
+
scrollContentRef.parentElement.scrollTo({
|
|
319
|
+
left: scrollLeft,
|
|
320
|
+
top: scrollTop
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
return (() => {
|
|
324
|
+
const _el$ = _tmpl$.cloneNode(true), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild, _el$4 = _el$3.firstChild;
|
|
325
|
+
_el$.addEventListener("wheel", handleWheel);
|
|
326
|
+
_el$.addEventListener("scroll", handleScroll);
|
|
327
|
+
const _ref$ = props.ref;
|
|
328
|
+
typeof _ref$ === "function" ? web.use(_ref$, _el$) : props.ref = _el$;
|
|
329
|
+
web.spread(_el$, web.mergeProps(divProps, {
|
|
330
|
+
get style() {
|
|
331
|
+
return {
|
|
332
|
+
overflow: propsWithDefaults.showScrollbar ? "scroll" : "hidden",
|
|
333
|
+
...typeof divProps.style === "object" && divProps.style
|
|
334
|
+
};
|
|
335
|
+
},
|
|
336
|
+
get classList() {
|
|
337
|
+
return {
|
|
338
|
+
[ScrollZoomContainer_module_default.ScrollZoomContainer]: true,
|
|
339
|
+
...divProps.classList
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
}), false, true);
|
|
343
|
+
const _ref$2 = scrollContentRef;
|
|
344
|
+
typeof _ref$2 === "function" ? web.use(_ref$2, _el$2) : scrollContentRef = _el$2;
|
|
345
|
+
_el$3.style.setProperty("top", "0");
|
|
346
|
+
_el$3.style.setProperty("left", "0");
|
|
347
|
+
_el$3.style.setProperty("position", "sticky");
|
|
348
|
+
_el$3.style.setProperty("display", "flex");
|
|
349
|
+
_el$4.style.setProperty("position", "relative");
|
|
350
|
+
web.insert(_el$4, () => props.children);
|
|
351
|
+
web.effect((_p$) => {
|
|
352
|
+
const _v$ = `${verticalViewPort().pixelSize}px`, _v$2 = `${horizontalViewPort().pixelSize}px`, _v$3 = `${verticalViewPort().pixelSize}px`, _v$4 = `${horizontalViewPort().pixelSize}px`;
|
|
353
|
+
_v$ !== _p$._v$ && _el$3.style.setProperty("height", _p$._v$ = _v$);
|
|
354
|
+
_v$2 !== _p$._v$2 && _el$3.style.setProperty("width", _p$._v$2 = _v$2);
|
|
355
|
+
_v$3 !== _p$._v$3 && _el$4.style.setProperty("height", _p$._v$3 = _v$3);
|
|
356
|
+
_v$4 !== _p$._v$4 && _el$4.style.setProperty("width", _p$._v$4 = _v$4);
|
|
357
|
+
return _p$;
|
|
358
|
+
}, {
|
|
359
|
+
_v$: void 0,
|
|
360
|
+
_v$2: void 0,
|
|
361
|
+
_v$3: void 0,
|
|
362
|
+
_v$4: void 0
|
|
363
|
+
});
|
|
364
|
+
return _el$;
|
|
365
|
+
})();
|
|
366
|
+
}, "ScrollZoomContainer");
|
|
367
|
+
var ScrollZoomContainer_default = ScrollZoomContainer;
|
|
368
|
+
|
|
369
|
+
// src/PianoRollKeys.tsx
|
|
370
|
+
var _tmpl$2 = /* @__PURE__ */ web.template(`<div></div>`, 2);
|
|
371
|
+
var PianoRollKeys = /* @__PURE__ */ __name(() => {
|
|
372
|
+
const verticalViewPort = solidJs.createMemo(() => useViewPortDimension("vertical"));
|
|
373
|
+
const horizontalViewPort = solidJs.createMemo(() => useViewPortDimension("horizontalKeys"));
|
|
374
|
+
const [isMouseDown, setIsMouseDown] = solidJs.createSignal(false);
|
|
375
|
+
const context = usePianoRollContext();
|
|
376
|
+
const handleMouseUp = /* @__PURE__ */ __name(() => {
|
|
377
|
+
setIsMouseDown(false);
|
|
378
|
+
}, "handleMouseUp");
|
|
379
|
+
solidJs.createEffect(() => {
|
|
380
|
+
if (isMouseDown()) {
|
|
381
|
+
window.addEventListener("mouseup", handleMouseUp);
|
|
382
|
+
} else {
|
|
383
|
+
window.removeEventListener("mouseup", handleMouseUp);
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
return (() => {
|
|
387
|
+
const _el$ = _tmpl$2.cloneNode(true);
|
|
388
|
+
web.insert(_el$, web.createComponent(ScrollZoomContainer_default, {
|
|
389
|
+
horizontalDimensionName: "horizontalKeys",
|
|
390
|
+
showScrollbar: false,
|
|
391
|
+
get children() {
|
|
392
|
+
return web.createComponent(solidJs.Index, {
|
|
393
|
+
each: keys,
|
|
394
|
+
children: (key) => {
|
|
395
|
+
const isDown = solidJs.createMemo(() => context.isKeyDown(context.selectedTrackIndex, key().number));
|
|
396
|
+
const virtualDimensions = solidJs.createMemo(() => verticalViewPort().calculatePixelDimensions(127 - key().number, 1));
|
|
397
|
+
const previousIsBlack = blackKeys.includes((key().number - 1) % 12);
|
|
398
|
+
const nextIsBlack = blackKeys.includes((key().number + 1) % 12);
|
|
399
|
+
return web.createComponent(solidJs.Show, {
|
|
400
|
+
get when() {
|
|
401
|
+
return verticalViewPort().isVisible(virtualDimensions());
|
|
402
|
+
},
|
|
403
|
+
get children() {
|
|
404
|
+
const _el$2 = _tmpl$2.cloneNode(true);
|
|
405
|
+
_el$2.addEventListener("mouseleave", () => {
|
|
406
|
+
if (isMouseDown()) {
|
|
407
|
+
context.onNoteUp(context.selectedTrackIndex, key().number);
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
_el$2.addEventListener("mouseenter", () => {
|
|
411
|
+
if (isMouseDown()) {
|
|
412
|
+
context.onNoteDown(context.selectedTrackIndex, key().number);
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
_el$2.$$mouseup = () => {
|
|
416
|
+
context.onNoteUp(context.selectedTrackIndex, key().number);
|
|
417
|
+
};
|
|
418
|
+
_el$2.$$mousedown = () => {
|
|
419
|
+
setIsMouseDown(true);
|
|
420
|
+
context.onNoteDown(context.selectedTrackIndex, key().number);
|
|
421
|
+
};
|
|
422
|
+
web.effect((_p$) => {
|
|
423
|
+
const _v$3 = {
|
|
424
|
+
[PianoRollKeys_module_default["Key"]]: true,
|
|
425
|
+
[PianoRollKeys_module_default["black"]]: key().isBlack,
|
|
426
|
+
[PianoRollKeys_module_default["white"]]: !key().isBlack,
|
|
427
|
+
[PianoRollKeys_module_default["down"]]: isDown()
|
|
428
|
+
}, _v$4 = key().name, _v$5 = key().number % 12, _v$6 = `${virtualDimensions().offset - virtualDimensions().size * (!key().isBlack ? nextIsBlack ? 1 / 2 : 0 : 0)}px`, _v$7 = `${virtualDimensions().size + (!key().isBlack && nextIsBlack ? virtualDimensions().size / 2 : 0) + (!key().isBlack && previousIsBlack ? virtualDimensions().size / 2 : 0)}px`, _v$8 = `0px 0px ${Math.min(virtualDimensions().size / 20, 1)}px ${Math.min(virtualDimensions().size / 50, 1)}px rgba(0, 0, 0, 0.5) ${key().isBlack ? "" : "inset"}` + isDown() ? `0px 0px ${Math.min(virtualDimensions().size / 8, 2)}px ${Math.min(virtualDimensions().size / 20, 2)}px rgba(0, 0, 0, 0.5) inset` : "";
|
|
429
|
+
_p$._v$3 = web.classList(_el$2, _v$3, _p$._v$3);
|
|
430
|
+
_v$4 !== _p$._v$4 && web.setAttribute(_el$2, "title", _p$._v$4 = _v$4);
|
|
431
|
+
_v$5 !== _p$._v$5 && web.setAttribute(_el$2, "data-index", _p$._v$5 = _v$5);
|
|
432
|
+
_v$6 !== _p$._v$6 && _el$2.style.setProperty("top", _p$._v$6 = _v$6);
|
|
433
|
+
_v$7 !== _p$._v$7 && _el$2.style.setProperty("height", _p$._v$7 = _v$7);
|
|
434
|
+
_v$8 !== _p$._v$8 && _el$2.style.setProperty("box-shadow", _p$._v$8 = _v$8);
|
|
435
|
+
return _p$;
|
|
436
|
+
}, {
|
|
437
|
+
_v$3: void 0,
|
|
438
|
+
_v$4: void 0,
|
|
439
|
+
_v$5: void 0,
|
|
440
|
+
_v$6: void 0,
|
|
441
|
+
_v$7: void 0,
|
|
442
|
+
_v$8: void 0
|
|
443
|
+
});
|
|
444
|
+
return _el$2;
|
|
445
|
+
}
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
}));
|
|
451
|
+
web.effect((_p$) => {
|
|
452
|
+
const _v$ = PianoRollKeys_module_default.PianoRollKeys, _v$2 = `${horizontalViewPort().pixelSize}px`;
|
|
453
|
+
_v$ !== _p$._v$ && web.className(_el$, _p$._v$ = _v$);
|
|
454
|
+
_v$2 !== _p$._v$2 && _el$.style.setProperty("width", _p$._v$2 = _v$2);
|
|
455
|
+
return _p$;
|
|
456
|
+
}, {
|
|
457
|
+
_v$: void 0,
|
|
458
|
+
_v$2: void 0
|
|
459
|
+
});
|
|
460
|
+
return _el$;
|
|
461
|
+
})();
|
|
462
|
+
}, "PianoRollKeys");
|
|
463
|
+
var blackKeys = [1, 3, 6, 8, 10];
|
|
464
|
+
var keyNames = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
|
|
465
|
+
var keys = Array.from({
|
|
466
|
+
length: 128
|
|
467
|
+
}).map((_, index) => ({
|
|
468
|
+
number: index,
|
|
469
|
+
name: `${keyNames[index % 12]} ${Math.floor(index / 12) - 2}`,
|
|
470
|
+
isBlack: blackKeys.includes(index % 12)
|
|
471
|
+
}));
|
|
472
|
+
var PianoRollKeys_default = PianoRollKeys;
|
|
473
|
+
web.delegateEvents(["mousedown", "mouseup"]);
|
|
474
|
+
|
|
475
|
+
// css-module:./PianoRollNotes.module.css#css-module
|
|
476
|
+
var PianoRollNotes_module_default = { "PianoRollNotes": "_PianoRollNotes_u3pew_1", "Note": "_Note_u3pew_12", "trimStart": "_trimStart_u3pew_22", "trimEnd": "_trimEnd_u3pew_26" };
|
|
477
|
+
|
|
478
|
+
// src/PianoRollNotes.tsx
|
|
479
|
+
var _tmpl$3 = /* @__PURE__ */ web.template(`<div></div>`, 2);
|
|
480
|
+
var PianoRollNotes = /* @__PURE__ */ __name((props) => {
|
|
481
|
+
const context = usePianoRollContext();
|
|
482
|
+
const verticalViewPort = solidJs.createMemo(() => useViewPortDimension(context.mode === "keys" ? "vertical" : "verticalTracks"));
|
|
483
|
+
const horizontalViewPort = solidJs.createMemo(() => useViewPortDimension("horizontal"));
|
|
484
|
+
const gridDivisionTicks = solidJs.createMemo(() => context.ppq * 4 / context.gridDivision);
|
|
485
|
+
const [isDragging, setIsDragging] = solidJs.createSignal(false);
|
|
486
|
+
const [noteDragMode, setNoteDragMode] = solidJs.createSignal();
|
|
487
|
+
const [currentNoteIndex, setCurrentNoteIndex] = solidJs.createSignal(-1);
|
|
488
|
+
const [currentNoteTrackIndex, setCurrentNoteTrackIndex] = solidJs.createSignal(-1);
|
|
489
|
+
const [diffPosition, setDiffPosition] = solidJs.createSignal(0);
|
|
490
|
+
const [getInitialNote, setInitialNote] = solidJs.createSignal();
|
|
491
|
+
const calculateNoteDragValues = /* @__PURE__ */ __name((event) => {
|
|
492
|
+
const targetTrackIndex = context.mode === "tracks" ? clamp(Math.floor(verticalViewPort().calculatePosition(event.clientY)), 0, context.tracks.length - 1) : currentNoteTrackIndex() > -1 ? currentNoteTrackIndex() : context.selectedTrackIndex;
|
|
493
|
+
const midi = context.mode === "keys" ? Math.floor(128 - verticalViewPort().calculatePosition(event.clientY)) : getInitialNote()?.midi ?? 60;
|
|
494
|
+
const horiontalPosition = horizontalViewPort().calculatePosition(event.clientX);
|
|
495
|
+
return {
|
|
496
|
+
targetTrackIndex,
|
|
497
|
+
midi,
|
|
498
|
+
horiontalPosition
|
|
499
|
+
};
|
|
500
|
+
}, "calculateNoteDragValues");
|
|
501
|
+
const handleMouseMove = /* @__PURE__ */ __name((mouseMoveEvent) => {
|
|
502
|
+
mouseMoveEvent.preventDefault();
|
|
503
|
+
mouseMoveEvent.stopPropagation();
|
|
504
|
+
const note = getInitialNote();
|
|
505
|
+
if (!note)
|
|
506
|
+
return;
|
|
507
|
+
const {
|
|
508
|
+
targetTrackIndex,
|
|
509
|
+
midi,
|
|
510
|
+
horiontalPosition
|
|
511
|
+
} = calculateNoteDragValues(mouseMoveEvent);
|
|
512
|
+
const ticks = context.snapValueToGridIfEnabled(horiontalPosition - diffPosition(), mouseMoveEvent.altKey);
|
|
513
|
+
const updatedNote = {
|
|
514
|
+
...note,
|
|
515
|
+
midi,
|
|
516
|
+
...noteDragMode() === "move" && {
|
|
517
|
+
ticks
|
|
518
|
+
},
|
|
519
|
+
...noteDragMode() === "trimStart" && {
|
|
520
|
+
ticks: ticks < note.ticks + note.durationTicks ? ticks : note.ticks + note.durationTicks,
|
|
521
|
+
durationTicks: ticks < note.ticks + note.durationTicks ? note.ticks + note.durationTicks - ticks : context.snapValueToGridIfEnabled(horiontalPosition - note.ticks, mouseMoveEvent.altKey)
|
|
522
|
+
},
|
|
523
|
+
...noteDragMode() === "trimEnd" && {
|
|
524
|
+
ticks: ticks < note.ticks ? ticks : note.ticks,
|
|
525
|
+
durationTicks: ticks < note.ticks ? note.ticks - ticks : context.snapValueToGridIfEnabled(horiontalPosition - note.ticks, mouseMoveEvent.altKey)
|
|
526
|
+
}
|
|
527
|
+
};
|
|
528
|
+
const previousTrackIndex = currentNoteTrackIndex();
|
|
529
|
+
const previousNoteIndex = currentNoteIndex();
|
|
530
|
+
if (targetTrackIndex === previousTrackIndex) {
|
|
531
|
+
context.onNoteChange?.(previousTrackIndex, previousNoteIndex, updatedNote);
|
|
532
|
+
} else {
|
|
533
|
+
if (context.onInsertNote) {
|
|
534
|
+
context.onRemoveNote?.(previousTrackIndex, previousNoteIndex);
|
|
535
|
+
const newNoteIndex = context.onInsertNote(targetTrackIndex, updatedNote);
|
|
536
|
+
setCurrentNoteTrackIndex(targetTrackIndex);
|
|
537
|
+
setCurrentNoteIndex(newNoteIndex);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}, "handleMouseMove");
|
|
541
|
+
const stopDragging = /* @__PURE__ */ __name(() => {
|
|
542
|
+
window.removeEventListener("mousemove", handleMouseMove);
|
|
543
|
+
window.removeEventListener("mouseup", stopDragging);
|
|
544
|
+
setIsDragging(false);
|
|
545
|
+
setCurrentNoteIndex(-1);
|
|
546
|
+
setCurrentNoteTrackIndex(-1);
|
|
547
|
+
}, "stopDragging");
|
|
548
|
+
const startDragging = /* @__PURE__ */ __name(() => {
|
|
549
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
550
|
+
window.addEventListener("mouseup", stopDragging);
|
|
551
|
+
}, "startDragging");
|
|
552
|
+
const getClasses = /* @__PURE__ */ __name((noteDragMode2) => {
|
|
553
|
+
return noteDragMode2 ? [PianoRollNotes_module_default.Note, PianoRollNotes_module_default[noteDragMode2]] : [PianoRollNotes_module_default.Note];
|
|
554
|
+
}, "getClasses");
|
|
555
|
+
return (() => {
|
|
556
|
+
const _el$ = _tmpl$3.cloneNode(true);
|
|
557
|
+
_el$.$$mousedown = (mouseDownEvent) => {
|
|
558
|
+
mouseDownEvent.preventDefault();
|
|
559
|
+
mouseDownEvent.stopPropagation();
|
|
560
|
+
const {
|
|
561
|
+
targetTrackIndex,
|
|
562
|
+
midi,
|
|
563
|
+
horiontalPosition
|
|
564
|
+
} = calculateNoteDragValues(mouseDownEvent);
|
|
565
|
+
const ticks = context.snapValueToGridIfEnabled(horiontalPosition, mouseDownEvent.altKey, context);
|
|
566
|
+
const durationTicks = gridDivisionTicks();
|
|
567
|
+
const newNote = {
|
|
568
|
+
midi,
|
|
569
|
+
ticks,
|
|
570
|
+
durationTicks,
|
|
571
|
+
velocity: 100
|
|
572
|
+
};
|
|
573
|
+
const newNoteIndex = context.onInsertNote(targetTrackIndex, newNote);
|
|
574
|
+
setIsDragging(true);
|
|
575
|
+
setCurrentNoteTrackIndex(targetTrackIndex);
|
|
576
|
+
setCurrentNoteIndex(newNoteIndex);
|
|
577
|
+
setInitialNote(newNote);
|
|
578
|
+
setDiffPosition(0);
|
|
579
|
+
setNoteDragMode("trimEnd");
|
|
580
|
+
startDragging();
|
|
581
|
+
};
|
|
582
|
+
const _ref$ = props.ref;
|
|
583
|
+
typeof _ref$ === "function" ? web.use(_ref$, _el$) : props.ref = _el$;
|
|
584
|
+
web.insert(_el$, web.createComponent(solidJs.For, {
|
|
585
|
+
get each() {
|
|
586
|
+
return context.tracks;
|
|
587
|
+
},
|
|
588
|
+
children: (track, trackIndex) => {
|
|
589
|
+
return web.createComponent(solidJs.Show, {
|
|
590
|
+
get when() {
|
|
591
|
+
return trackIndex() === context.selectedTrackIndex || context.showAllTracks || context.mode === "tracks";
|
|
592
|
+
},
|
|
593
|
+
get children() {
|
|
594
|
+
return web.createComponent(solidJs.For, {
|
|
595
|
+
get each() {
|
|
596
|
+
return track.notes;
|
|
597
|
+
},
|
|
598
|
+
children: (note, noteIndex) => {
|
|
599
|
+
const verticalVirtualDimensions = solidJs.createMemo(() => verticalViewPort().calculatePixelDimensions(context.mode === "keys" ? 127 - note.midi : trackIndex(), 1));
|
|
600
|
+
const horizontalDimensions = solidJs.createMemo(() => horizontalViewPort().calculatePixelDimensions(note.ticks, note.durationTicks));
|
|
601
|
+
return web.createComponent(solidJs.Show, {
|
|
602
|
+
get when() {
|
|
603
|
+
return web.memo(() => !!verticalViewPort().isVisible(verticalVirtualDimensions()))() && horizontalViewPort().isVisible(horizontalDimensions());
|
|
604
|
+
},
|
|
605
|
+
get children() {
|
|
606
|
+
const _el$2 = _tmpl$3.cloneNode(true);
|
|
607
|
+
_el$2.$$mousedown = (event) => {
|
|
608
|
+
event.stopPropagation();
|
|
609
|
+
const initialPosition = horizontalViewPort().calculatePosition(event.clientX);
|
|
610
|
+
setDiffPosition(noteDragMode() === "trimEnd" ? -(note.ticks + note.durationTicks - initialPosition) : initialPosition - note.ticks);
|
|
611
|
+
setIsDragging(true);
|
|
612
|
+
setCurrentNoteIndex(noteIndex());
|
|
613
|
+
setCurrentNoteTrackIndex(trackIndex());
|
|
614
|
+
setInitialNote(note);
|
|
615
|
+
startDragging();
|
|
616
|
+
};
|
|
617
|
+
_el$2.$$dblclick = (event) => {
|
|
618
|
+
event.stopPropagation();
|
|
619
|
+
context.onRemoveNote?.(trackIndex(), noteIndex());
|
|
620
|
+
};
|
|
621
|
+
_el$2.$$mousemove = (event) => {
|
|
622
|
+
if (isDragging())
|
|
623
|
+
return;
|
|
624
|
+
event.stopPropagation();
|
|
625
|
+
const relativeX = horizontalViewPort().calculatePixelValue(horizontalViewPort().calculatePosition(event.clientX));
|
|
626
|
+
const noteStartX = horizontalViewPort().calculatePixelValue(note.ticks);
|
|
627
|
+
const noteEndX = horizontalViewPort().calculatePixelValue(note.ticks + note.durationTicks);
|
|
628
|
+
setNoteDragMode(relativeX - noteStartX < 3 ? "trimStart" : noteEndX - relativeX < 3 ? "trimEnd" : "move");
|
|
629
|
+
};
|
|
630
|
+
web.setAttribute(_el$2, "draggable", false);
|
|
631
|
+
web.effect((_p$) => {
|
|
632
|
+
const _v$ = getClasses(noteDragMode()).join(" "), _v$2 = `${track.color}`, _v$3 = (note.velocity / 128 + 2) / 3, _v$4 = `${verticalVirtualDimensions().offset}px`, _v$5 = `${verticalVirtualDimensions().size}px`, _v$6 = `${horizontalDimensions().offset}px`, _v$7 = `${horizontalDimensions().size}px`;
|
|
633
|
+
_v$ !== _p$._v$ && web.className(_el$2, _p$._v$ = _v$);
|
|
634
|
+
_v$2 !== _p$._v$2 && _el$2.style.setProperty("background-color", _p$._v$2 = _v$2);
|
|
635
|
+
_v$3 !== _p$._v$3 && _el$2.style.setProperty("opacity", _p$._v$3 = _v$3);
|
|
636
|
+
_v$4 !== _p$._v$4 && _el$2.style.setProperty("top", _p$._v$4 = _v$4);
|
|
637
|
+
_v$5 !== _p$._v$5 && _el$2.style.setProperty("height", _p$._v$5 = _v$5);
|
|
638
|
+
_v$6 !== _p$._v$6 && _el$2.style.setProperty("left", _p$._v$6 = _v$6);
|
|
639
|
+
_v$7 !== _p$._v$7 && _el$2.style.setProperty("width", _p$._v$7 = _v$7);
|
|
640
|
+
return _p$;
|
|
641
|
+
}, {
|
|
642
|
+
_v$: void 0,
|
|
643
|
+
_v$2: void 0,
|
|
644
|
+
_v$3: void 0,
|
|
645
|
+
_v$4: void 0,
|
|
646
|
+
_v$5: void 0,
|
|
647
|
+
_v$6: void 0,
|
|
648
|
+
_v$7: void 0
|
|
649
|
+
});
|
|
650
|
+
return _el$2;
|
|
651
|
+
}
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
}));
|
|
659
|
+
web.effect((_$p) => web.classList(_el$, {
|
|
660
|
+
[PianoRollNotes_module_default.PianoRollNotes]: true
|
|
661
|
+
}, _$p));
|
|
662
|
+
return _el$;
|
|
663
|
+
})();
|
|
664
|
+
}, "PianoRollNotes");
|
|
665
|
+
var PianoRollNotes_default = PianoRollNotes;
|
|
666
|
+
web.delegateEvents(["mousedown", "mousemove", "dblclick"]);
|
|
667
|
+
|
|
668
|
+
// css-module:./PianoRollGrid.module.css#css-module
|
|
669
|
+
var PianoRollGrid_module_default = { "PianoRollGrid": "_PianoRollGrid_qke5f_1", "PianoRollGrid-Row": "_PianoRollGrid-Row_qke5f_7", "IsDark": "_IsDark_qke5f_14", "Key": "_Key_qke5f_18", "IsBlackAndNextIsWhite": "_IsBlackAndNextIsWhite_qke5f_21", "PianoRollGrid-Time": "_PianoRollGrid-Time_qke5f_26", "Highlighted": "_Highlighted_qke5f_37", "HighlightedBorder": "_HighlightedBorder_qke5f_41" };
|
|
670
|
+
var usePianoRollGrid = /* @__PURE__ */ __name(() => {
|
|
671
|
+
const context = usePianoRollContext();
|
|
672
|
+
const horizontalViewPort = solidJs.createMemo(() => useViewPortDimension("horizontal"));
|
|
673
|
+
const measureTicks = solidJs.createMemo(() => context.ppq * 4);
|
|
674
|
+
const selectedGridDivisorTicks = solidJs.createMemo(() => measureTicks() / context.gridDivision);
|
|
675
|
+
function calculateVisibleGridDivisorTicks(value) {
|
|
676
|
+
const visibleRange = horizontalViewPort().calculateVisibleRange();
|
|
677
|
+
if (visibleRange <= 0)
|
|
678
|
+
return 0;
|
|
679
|
+
if (visibleRange / value > 100) {
|
|
680
|
+
return calculateVisibleGridDivisorTicks(value * 2);
|
|
681
|
+
}
|
|
682
|
+
if (visibleRange / value < 30) {
|
|
683
|
+
return calculateVisibleGridDivisorTicks(value / 2);
|
|
684
|
+
}
|
|
685
|
+
return value;
|
|
686
|
+
}
|
|
687
|
+
__name(calculateVisibleGridDivisorTicks, "calculateVisibleGridDivisorTicks");
|
|
688
|
+
const gridDivisorTicks = solidJs.createMemo(
|
|
689
|
+
() => calculateVisibleGridDivisorTicks(selectedGridDivisorTicks())
|
|
690
|
+
);
|
|
691
|
+
const gridArray = solidJs.createMemo(() => {
|
|
692
|
+
const numberOfLines = Math.ceil(
|
|
693
|
+
horizontalViewPort().calculateVisibleRange() / gridDivisorTicks() + 1
|
|
694
|
+
);
|
|
695
|
+
const startIndex = Math.floor(context.position / gridDivisorTicks());
|
|
696
|
+
return Array.from({ length: numberOfLines }).map((_, i) => {
|
|
697
|
+
const index = i + startIndex;
|
|
698
|
+
const ticks = index * gridDivisorTicks();
|
|
699
|
+
const measurePosition = ticks / context.ppq / 4 + 1;
|
|
700
|
+
const bars = Math.floor(measurePosition);
|
|
701
|
+
const beats = Math.floor((measurePosition - bars) * 4);
|
|
702
|
+
const label = `${bars}${beats ? `.${beats}` : ""}`;
|
|
703
|
+
return {
|
|
704
|
+
index,
|
|
705
|
+
ticks,
|
|
706
|
+
isHighlighted: Math.ceil((index + 1) * selectedGridDivisorTicks() / measureTicks()) % 2 === 0,
|
|
707
|
+
hasHighlightedBorder: index * gridDivisorTicks() % selectedGridDivisorTicks() === 0,
|
|
708
|
+
showLabel: index * selectedGridDivisorTicks() / measureTicks() % 2 === 0,
|
|
709
|
+
virtualDimensions: horizontalViewPort().calculatePixelDimensions(ticks, gridDivisorTicks()),
|
|
710
|
+
label
|
|
711
|
+
};
|
|
712
|
+
});
|
|
713
|
+
});
|
|
714
|
+
return gridArray;
|
|
715
|
+
}, "usePianoRollGrid");
|
|
716
|
+
var usePianoRollGrid_default = usePianoRollGrid;
|
|
717
|
+
|
|
718
|
+
// src/PianoRollGrid.tsx
|
|
719
|
+
var _tmpl$4 = /* @__PURE__ */ web.template(`<div></div>`, 2);
|
|
720
|
+
var PianoRollGrid = /* @__PURE__ */ __name(() => {
|
|
721
|
+
const context = usePianoRollContext();
|
|
722
|
+
const verticalViewPort = solidJs.createMemo(() => useViewPortDimension(context.mode === "keys" ? "vertical" : "verticalTracks"));
|
|
723
|
+
const horizontalViewPort = solidJs.createMemo(() => useViewPortDimension("horizontal"));
|
|
724
|
+
const gridArray = usePianoRollGrid_default();
|
|
725
|
+
return (() => {
|
|
726
|
+
const _el$ = _tmpl$4.cloneNode(true);
|
|
727
|
+
web.insert(_el$, web.createComponent(solidJs.Index, {
|
|
728
|
+
get each() {
|
|
729
|
+
return gridArray();
|
|
730
|
+
},
|
|
731
|
+
children: (entry) => {
|
|
732
|
+
return web.createComponent(solidJs.Show, {
|
|
733
|
+
get when() {
|
|
734
|
+
return horizontalViewPort().isVisible(entry().virtualDimensions);
|
|
735
|
+
},
|
|
736
|
+
get children() {
|
|
737
|
+
const _el$2 = _tmpl$4.cloneNode(true);
|
|
738
|
+
web.effect((_p$) => {
|
|
739
|
+
const _v$ = {
|
|
740
|
+
[PianoRollGrid_module_default["PianoRollGrid-Time"]]: true,
|
|
741
|
+
[PianoRollGrid_module_default["Highlighted"]]: entry().isHighlighted,
|
|
742
|
+
[PianoRollGrid_module_default["HighlightedBorder"]]: entry().hasHighlightedBorder
|
|
743
|
+
}, _v$2 = `${entry().virtualDimensions.offset}px`, _v$3 = `${entry().virtualDimensions.size}px`;
|
|
744
|
+
_p$._v$ = web.classList(_el$2, _v$, _p$._v$);
|
|
745
|
+
_v$2 !== _p$._v$2 && _el$2.style.setProperty("left", _p$._v$2 = _v$2);
|
|
746
|
+
_v$3 !== _p$._v$3 && _el$2.style.setProperty("width", _p$._v$3 = _v$3);
|
|
747
|
+
return _p$;
|
|
748
|
+
}, {
|
|
749
|
+
_v$: void 0,
|
|
750
|
+
_v$2: void 0,
|
|
751
|
+
_v$3: void 0
|
|
752
|
+
});
|
|
753
|
+
return _el$2;
|
|
754
|
+
}
|
|
755
|
+
});
|
|
756
|
+
}
|
|
757
|
+
}), null);
|
|
758
|
+
web.insert(_el$, web.createComponent(solidJs.Show, {
|
|
759
|
+
get when() {
|
|
760
|
+
return context.mode === "keys";
|
|
761
|
+
},
|
|
762
|
+
get children() {
|
|
763
|
+
return web.createComponent(solidJs.Index, {
|
|
764
|
+
each: keys,
|
|
765
|
+
children: (key) => {
|
|
766
|
+
const virtualDimensions = solidJs.createMemo(() => verticalViewPort().calculatePixelDimensions(127 - key().number, 1));
|
|
767
|
+
return web.createComponent(solidJs.Show, {
|
|
768
|
+
get when() {
|
|
769
|
+
return verticalViewPort().isVisible(virtualDimensions());
|
|
770
|
+
},
|
|
771
|
+
get children() {
|
|
772
|
+
const _el$3 = _tmpl$4.cloneNode(true);
|
|
773
|
+
web.effect((_p$) => {
|
|
774
|
+
const _v$4 = {
|
|
775
|
+
[PianoRollGrid_module_default["PianoRollGrid-Row"]]: true,
|
|
776
|
+
[PianoRollGrid_module_default["Key"]]: true,
|
|
777
|
+
[PianoRollGrid_module_default["IsDark"]]: key().isBlack,
|
|
778
|
+
[PianoRollGrid_module_default["IsBlackAndNextIsWhite"]]: !key().isBlack && !blackKeys.includes((key().number + 1) % 12)
|
|
779
|
+
}, _v$5 = `${virtualDimensions().offset}px`, _v$6 = `${virtualDimensions().size}px`;
|
|
780
|
+
_p$._v$4 = web.classList(_el$3, _v$4, _p$._v$4);
|
|
781
|
+
_v$5 !== _p$._v$5 && _el$3.style.setProperty("top", _p$._v$5 = _v$5);
|
|
782
|
+
_v$6 !== _p$._v$6 && _el$3.style.setProperty("height", _p$._v$6 = _v$6);
|
|
783
|
+
return _p$;
|
|
784
|
+
}, {
|
|
785
|
+
_v$4: void 0,
|
|
786
|
+
_v$5: void 0,
|
|
787
|
+
_v$6: void 0
|
|
788
|
+
});
|
|
789
|
+
return _el$3;
|
|
790
|
+
}
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
}), null);
|
|
796
|
+
web.insert(_el$, web.createComponent(solidJs.Show, {
|
|
797
|
+
get when() {
|
|
798
|
+
return context.mode === "tracks";
|
|
799
|
+
},
|
|
800
|
+
get children() {
|
|
801
|
+
return web.createComponent(solidJs.For, {
|
|
802
|
+
get each() {
|
|
803
|
+
return context.tracks;
|
|
804
|
+
},
|
|
805
|
+
children: (track, index) => {
|
|
806
|
+
const virtualDimensions = solidJs.createMemo(() => verticalViewPort().calculatePixelDimensions(index(), 1));
|
|
807
|
+
return web.createComponent(solidJs.Show, {
|
|
808
|
+
get when() {
|
|
809
|
+
return verticalViewPort().isVisible(virtualDimensions());
|
|
810
|
+
},
|
|
811
|
+
get children() {
|
|
812
|
+
const _el$4 = _tmpl$4.cloneNode(true);
|
|
813
|
+
web.effect((_p$) => {
|
|
814
|
+
const _v$7 = {
|
|
815
|
+
[PianoRollGrid_module_default["PianoRollGrid-Row"]]: true,
|
|
816
|
+
[PianoRollGrid_module_default["IsDark"]]: index() % 2 === 0
|
|
817
|
+
}, _v$8 = `${virtualDimensions().offset}px`, _v$9 = `${virtualDimensions().size}px`;
|
|
818
|
+
_p$._v$7 = web.classList(_el$4, _v$7, _p$._v$7);
|
|
819
|
+
_v$8 !== _p$._v$8 && _el$4.style.setProperty("top", _p$._v$8 = _v$8);
|
|
820
|
+
_v$9 !== _p$._v$9 && _el$4.style.setProperty("height", _p$._v$9 = _v$9);
|
|
821
|
+
return _p$;
|
|
822
|
+
}, {
|
|
823
|
+
_v$7: void 0,
|
|
824
|
+
_v$8: void 0,
|
|
825
|
+
_v$9: void 0
|
|
826
|
+
});
|
|
827
|
+
return _el$4;
|
|
828
|
+
}
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
}), null);
|
|
834
|
+
web.effect(() => web.className(_el$, PianoRollGrid_module_default.PianoRollGrid));
|
|
835
|
+
return _el$;
|
|
836
|
+
})();
|
|
837
|
+
}, "PianoRollGrid");
|
|
838
|
+
var PianoRollGrid_default = PianoRollGrid;
|
|
839
|
+
var _tmpl$5 = /* @__PURE__ */ web.template(`<input step="0.01">`, 1);
|
|
840
|
+
var ZoomSliderControl = /* @__PURE__ */ __name((props) => {
|
|
841
|
+
const propsWithDefaults = solidJs.mergeProps({
|
|
842
|
+
orientation: "horizontal"
|
|
843
|
+
}, props);
|
|
844
|
+
const dimension = solidJs.createMemo(() => useViewPortDimension(props.dimensionName ?? propsWithDefaults.orientation));
|
|
845
|
+
return (() => {
|
|
846
|
+
const _el$ = _tmpl$5.cloneNode(true);
|
|
847
|
+
web.spread(_el$, web.mergeProps({
|
|
848
|
+
get min() {
|
|
849
|
+
return dimension().minZoom;
|
|
850
|
+
},
|
|
851
|
+
get max() {
|
|
852
|
+
return dimension().maxZoom;
|
|
853
|
+
}
|
|
854
|
+
}, props, {
|
|
855
|
+
get value() {
|
|
856
|
+
return dimension().zoom;
|
|
857
|
+
},
|
|
858
|
+
"onInput": (event) => {
|
|
859
|
+
const value = event.currentTarget.valueAsNumber;
|
|
860
|
+
dimension().onZoomChange?.(value);
|
|
861
|
+
},
|
|
862
|
+
"type": "range"
|
|
863
|
+
}, () => ({
|
|
864
|
+
orient: propsWithDefaults.orientation
|
|
865
|
+
}), {
|
|
866
|
+
get style() {
|
|
867
|
+
return propsWithDefaults.orientation === "vertical" ? {
|
|
868
|
+
margin: 0,
|
|
869
|
+
"margin-left": "4px",
|
|
870
|
+
"margin-right": "4px",
|
|
871
|
+
width: "16px",
|
|
872
|
+
transform: "rotate(180deg)",
|
|
873
|
+
...{
|
|
874
|
+
"writing-mode": "bt-lr",
|
|
875
|
+
"-webkit-appearance": "slider-vertical"
|
|
876
|
+
},
|
|
877
|
+
...typeof props.style === "object" && props.style
|
|
878
|
+
} : {
|
|
879
|
+
margin: 0,
|
|
880
|
+
"margin-top": "4px",
|
|
881
|
+
"margin-bottom": "4px",
|
|
882
|
+
...typeof props.style === "object" && props.style
|
|
883
|
+
};
|
|
884
|
+
}
|
|
885
|
+
}), false, false);
|
|
886
|
+
return _el$;
|
|
887
|
+
})();
|
|
888
|
+
}, "ZoomSliderControl");
|
|
889
|
+
var ZoomSliderControl_default = ZoomSliderControl;
|
|
890
|
+
|
|
891
|
+
// css-module:./PianoRollTrackList.module.css#css-module
|
|
892
|
+
var PianoRollTrackList_module_default = { "PianoRollTrackList": "_PianoRollTrackList_11kti_1", "Track": "_Track_11kti_7", "selected": "_selected_11kti_21" };
|
|
893
|
+
var _tmpl$6 = /* @__PURE__ */ web.template(`<div></div>`, 2);
|
|
894
|
+
var _tmpl$22 = /* @__PURE__ */ web.template(`<div> </div>`, 2);
|
|
895
|
+
var PianoRollTrackList = /* @__PURE__ */ __name(() => {
|
|
896
|
+
const viewPort = solidJs.createMemo(() => useViewPortDimension("verticalTracks"));
|
|
897
|
+
const context = usePianoRollContext();
|
|
898
|
+
return (() => {
|
|
899
|
+
const _el$ = _tmpl$6.cloneNode(true);
|
|
900
|
+
web.insert(_el$, web.createComponent(solidJs.Index, {
|
|
901
|
+
get each() {
|
|
902
|
+
return context.tracks;
|
|
903
|
+
},
|
|
904
|
+
children: (track, index) => {
|
|
905
|
+
const virtualDimensions = solidJs.createMemo(() => viewPort().calculatePixelDimensions(index, 1));
|
|
906
|
+
return web.createComponent(solidJs.Show, {
|
|
907
|
+
get when() {
|
|
908
|
+
return virtualDimensions().size > 0;
|
|
909
|
+
},
|
|
910
|
+
get children() {
|
|
911
|
+
const _el$2 = _tmpl$22.cloneNode(true), _el$3 = _el$2.firstChild;
|
|
912
|
+
_el$2.$$click = () => context.onSelectedTrackIndexChange?.(index);
|
|
913
|
+
web.insert(_el$2, index, _el$3);
|
|
914
|
+
web.insert(_el$2, () => track().name || "[unnamed track]", null);
|
|
915
|
+
web.effect((_p$) => {
|
|
916
|
+
const _v$ = {
|
|
917
|
+
[PianoRollTrackList_module_default["Track"]]: true,
|
|
918
|
+
[PianoRollTrackList_module_default["selected"]]: index === context.selectedTrackIndex
|
|
919
|
+
}, _v$2 = track().name, _v$3 = `${virtualDimensions().offset}px`, _v$4 = `${virtualDimensions().size}px`;
|
|
920
|
+
_p$._v$ = web.classList(_el$2, _v$, _p$._v$);
|
|
921
|
+
_v$2 !== _p$._v$2 && web.setAttribute(_el$2, "title", _p$._v$2 = _v$2);
|
|
922
|
+
_v$3 !== _p$._v$3 && _el$2.style.setProperty("top", _p$._v$3 = _v$3);
|
|
923
|
+
_v$4 !== _p$._v$4 && _el$2.style.setProperty("height", _p$._v$4 = _v$4);
|
|
924
|
+
return _p$;
|
|
925
|
+
}, {
|
|
926
|
+
_v$: void 0,
|
|
927
|
+
_v$2: void 0,
|
|
928
|
+
_v$3: void 0,
|
|
929
|
+
_v$4: void 0
|
|
930
|
+
});
|
|
931
|
+
return _el$2;
|
|
932
|
+
}
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
}));
|
|
936
|
+
web.effect(() => web.className(_el$, PianoRollTrackList_module_default.PianoRollTrackList));
|
|
937
|
+
return _el$;
|
|
938
|
+
})();
|
|
939
|
+
}, "PianoRollTrackList");
|
|
940
|
+
var PianoRollTrackList_default = PianoRollTrackList;
|
|
941
|
+
web.delegateEvents(["click"]);
|
|
942
|
+
var PianoRollScrollZoomViewPort = /* @__PURE__ */ __name((props) => {
|
|
943
|
+
const zoomFactor = 500;
|
|
944
|
+
const context = usePianoRollContext();
|
|
945
|
+
return web.createComponent(ScrollZoomViewPort, {
|
|
946
|
+
dimensions: {
|
|
947
|
+
horizontal: () => ({
|
|
948
|
+
pixelOffset: context.notesScrollerClientRect.left,
|
|
949
|
+
pixelSize: context.notesScrollerClientRect.width,
|
|
950
|
+
position: context.position,
|
|
951
|
+
range: context.duration,
|
|
952
|
+
zoom: context.zoom * (zoomFactor / context.notesScrollerClientRect.width),
|
|
953
|
+
onPositionChange: context.onPositionChange,
|
|
954
|
+
onZoomChange: (zoom) => context.onZoomChange?.(zoom / (zoomFactor / context.notesScrollerClientRect.width)),
|
|
955
|
+
minZoom: 1,
|
|
956
|
+
maxZoom: 500
|
|
957
|
+
}),
|
|
958
|
+
vertical: () => ({
|
|
959
|
+
pixelOffset: context.notesScrollerClientRect.top,
|
|
960
|
+
pixelSize: context.notesScrollerClientRect.height,
|
|
961
|
+
position: context.verticalPosition,
|
|
962
|
+
range: 128,
|
|
963
|
+
zoom: context.verticalZoom * (zoomFactor / context.notesScrollerClientRect.height),
|
|
964
|
+
onPositionChange: context.onVerticalPositionChange,
|
|
965
|
+
onZoomChange: (verticalZoom) => context.onVerticalZoomChange?.(verticalZoom / (zoomFactor / context.notesScrollerClientRect.height)),
|
|
966
|
+
minZoom: 1,
|
|
967
|
+
maxZoom: 10
|
|
968
|
+
}),
|
|
969
|
+
horizontalTracks: () => ({
|
|
970
|
+
pixelOffset: 0,
|
|
971
|
+
pixelSize: context.tracksScrollerClientRect.width
|
|
972
|
+
}),
|
|
973
|
+
verticalTracks: () => ({
|
|
974
|
+
pixelOffset: context.tracksScrollerClientRect.top,
|
|
975
|
+
pixelSize: context.tracksScrollerClientRect.height,
|
|
976
|
+
position: context.verticalTrackPosition,
|
|
977
|
+
range: context.tracks.length,
|
|
978
|
+
zoom: context.verticalTrackZoom * (zoomFactor / context.tracksScrollerClientRect.height),
|
|
979
|
+
onPositionChange: context.onVerticalTrackPositionChange,
|
|
980
|
+
onZoomChange: (verticalTrackZoom) => context.onVerticalTrackZoomChange?.(verticalTrackZoom / (zoomFactor / context.tracksScrollerClientRect.height)),
|
|
981
|
+
minZoom: 0.8,
|
|
982
|
+
maxZoom: 3
|
|
983
|
+
}),
|
|
984
|
+
horizontalKeys: () => ({
|
|
985
|
+
pixelSize: 60
|
|
986
|
+
})
|
|
987
|
+
},
|
|
988
|
+
get children() {
|
|
989
|
+
return props.children;
|
|
990
|
+
}
|
|
991
|
+
});
|
|
992
|
+
}, "PianoRollScrollZoomViewPort");
|
|
993
|
+
var PianoRollScrollZoomViewPort_default = PianoRollScrollZoomViewPort;
|
|
994
|
+
var defaultRect = {
|
|
995
|
+
left: 0,
|
|
996
|
+
width: 0,
|
|
997
|
+
top: 0,
|
|
998
|
+
height: 0,
|
|
999
|
+
bottom: 0,
|
|
1000
|
+
right: 0,
|
|
1001
|
+
x: 0,
|
|
1002
|
+
y: 0
|
|
1003
|
+
};
|
|
1004
|
+
function useBoundingClientRect(containerRef) {
|
|
1005
|
+
const [boundingClientRect, setBoundingClientRect] = solidJs.createSignal(defaultRect);
|
|
1006
|
+
solidJs.createEffect(() => {
|
|
1007
|
+
const container = containerRef();
|
|
1008
|
+
if (!container)
|
|
1009
|
+
return;
|
|
1010
|
+
const updateBoundingClientRect = /* @__PURE__ */ __name(() => {
|
|
1011
|
+
setBoundingClientRect(container.getBoundingClientRect() ?? defaultRect);
|
|
1012
|
+
}, "updateBoundingClientRect");
|
|
1013
|
+
const resizeObserver = new ResizeObserver(updateBoundingClientRect);
|
|
1014
|
+
resizeObserver.observe(container);
|
|
1015
|
+
updateBoundingClientRect();
|
|
1016
|
+
return () => {
|
|
1017
|
+
resizeObserver.disconnect();
|
|
1018
|
+
};
|
|
1019
|
+
});
|
|
1020
|
+
return boundingClientRect;
|
|
1021
|
+
}
|
|
1022
|
+
__name(useBoundingClientRect, "useBoundingClientRect");
|
|
1023
|
+
|
|
1024
|
+
// src/PianoRollNotesScroller.tsx
|
|
1025
|
+
var PianoRollNotesScroller = /* @__PURE__ */ __name((props) => {
|
|
1026
|
+
const context = usePianoRollContext();
|
|
1027
|
+
const [ref, setRef] = solidJs.createSignal();
|
|
1028
|
+
const clientRect = useBoundingClientRect(ref);
|
|
1029
|
+
solidJs.createEffect(() => {
|
|
1030
|
+
context.onNotesScrollerClientRectChange(clientRect());
|
|
1031
|
+
});
|
|
1032
|
+
return web.createComponent(ScrollZoomContainer_default, {
|
|
1033
|
+
ref: setRef,
|
|
1034
|
+
get verticalDimensionName() {
|
|
1035
|
+
return context.mode === "keys" ? "vertical" : "verticalTracks";
|
|
1036
|
+
},
|
|
1037
|
+
get children() {
|
|
1038
|
+
return props.children;
|
|
1039
|
+
}
|
|
1040
|
+
});
|
|
1041
|
+
}, "PianoRollNotesScroller");
|
|
1042
|
+
var PianoRollNotesScroller_default = PianoRollNotesScroller;
|
|
1043
|
+
var PianoRollTrackListScroller = /* @__PURE__ */ __name((props) => {
|
|
1044
|
+
const context = usePianoRollContext();
|
|
1045
|
+
const [ref, setRef] = solidJs.createSignal();
|
|
1046
|
+
const clientRect = useBoundingClientRect(ref);
|
|
1047
|
+
solidJs.createEffect(() => {
|
|
1048
|
+
context.onTracksScrollerClientRectChange(clientRect());
|
|
1049
|
+
});
|
|
1050
|
+
return web.createComponent(ScrollZoomContainer_default, {
|
|
1051
|
+
ref: setRef,
|
|
1052
|
+
horizontalDimensionName: "horizontalTracks",
|
|
1053
|
+
verticalDimensionName: "verticalTracks",
|
|
1054
|
+
get showScrollbar() {
|
|
1055
|
+
return context.mode === "keys";
|
|
1056
|
+
},
|
|
1057
|
+
get children() {
|
|
1058
|
+
return props.children;
|
|
1059
|
+
}
|
|
1060
|
+
});
|
|
1061
|
+
}, "PianoRollTrackListScroller");
|
|
1062
|
+
var PianoRollTrackListScroller_default = PianoRollTrackListScroller;
|
|
1063
|
+
|
|
1064
|
+
// css-module:./PianoRollScale.module.css#css-module
|
|
1065
|
+
var PianoRollScale_module_default = { "PianoRollScale": "_PianoRollScale_1khhn_1", "PianoRollScale-Time": "_PianoRollScale-Time_1khhn_7", "PianoRollScale-Label": "_PianoRollScale-Label_1khhn_23", "Highlighted": "_Highlighted_1khhn_31", "HighlightedBorder": "_HighlightedBorder_1khhn_35" };
|
|
1066
|
+
|
|
1067
|
+
// src/PianoRollScale.tsx
|
|
1068
|
+
var _tmpl$7 = /* @__PURE__ */ web.template(`<div></div>`, 2);
|
|
1069
|
+
var PianoRollScale = /* @__PURE__ */ __name(() => {
|
|
1070
|
+
const horizontalViewPort = solidJs.createMemo(() => useViewPortDimension("horizontal"));
|
|
1071
|
+
const grid = usePianoRollGrid_default();
|
|
1072
|
+
const context = usePianoRollContext();
|
|
1073
|
+
const updatePlayheadPosition = /* @__PURE__ */ __name((event) => {
|
|
1074
|
+
const position = horizontalViewPort().calculatePosition(event.clientX);
|
|
1075
|
+
context.onPlayHeadPositionChange(position, event);
|
|
1076
|
+
}, "updatePlayheadPosition");
|
|
1077
|
+
return (() => {
|
|
1078
|
+
const _el$ = _tmpl$7.cloneNode(true);
|
|
1079
|
+
_el$.$$mousedown = (event) => {
|
|
1080
|
+
updatePlayheadPosition(event);
|
|
1081
|
+
const handleMouseUp = /* @__PURE__ */ __name(() => {
|
|
1082
|
+
window.removeEventListener("mousemove", updatePlayheadPosition);
|
|
1083
|
+
window.removeEventListener("mouseup", handleMouseUp);
|
|
1084
|
+
}, "handleMouseUp");
|
|
1085
|
+
window.addEventListener("mousemove", updatePlayheadPosition);
|
|
1086
|
+
window.addEventListener("mouseup", handleMouseUp);
|
|
1087
|
+
};
|
|
1088
|
+
web.insert(_el$, web.createComponent(solidJs.Index, {
|
|
1089
|
+
get each() {
|
|
1090
|
+
return grid();
|
|
1091
|
+
},
|
|
1092
|
+
children: (entry) => {
|
|
1093
|
+
return web.createComponent(solidJs.Show, {
|
|
1094
|
+
get when() {
|
|
1095
|
+
return horizontalViewPort().isVisible(entry().virtualDimensions);
|
|
1096
|
+
},
|
|
1097
|
+
get children() {
|
|
1098
|
+
const _el$2 = _tmpl$7.cloneNode(true);
|
|
1099
|
+
web.insert(_el$2, web.createComponent(solidJs.Show, {
|
|
1100
|
+
get when() {
|
|
1101
|
+
return entry().showLabel;
|
|
1102
|
+
},
|
|
1103
|
+
get children() {
|
|
1104
|
+
const _el$3 = _tmpl$7.cloneNode(true);
|
|
1105
|
+
web.insert(_el$3, () => entry().label);
|
|
1106
|
+
web.effect(() => web.className(_el$3, PianoRollScale_module_default["PianoRollScale-Label"]));
|
|
1107
|
+
return _el$3;
|
|
1108
|
+
}
|
|
1109
|
+
}));
|
|
1110
|
+
web.effect((_p$) => {
|
|
1111
|
+
const _v$ = {
|
|
1112
|
+
[PianoRollScale_module_default["PianoRollScale-Time"]]: true,
|
|
1113
|
+
[PianoRollScale_module_default["Highlighted"]]: entry().isHighlighted,
|
|
1114
|
+
[PianoRollScale_module_default["HighlightedBorder"]]: entry().hasHighlightedBorder
|
|
1115
|
+
}, _v$2 = `${entry().virtualDimensions.offset}px`, _v$3 = `${entry().virtualDimensions.size}px`;
|
|
1116
|
+
_p$._v$ = web.classList(_el$2, _v$, _p$._v$);
|
|
1117
|
+
_v$2 !== _p$._v$2 && _el$2.style.setProperty("left", _p$._v$2 = _v$2);
|
|
1118
|
+
_v$3 !== _p$._v$3 && _el$2.style.setProperty("width", _p$._v$3 = _v$3);
|
|
1119
|
+
return _p$;
|
|
1120
|
+
}, {
|
|
1121
|
+
_v$: void 0,
|
|
1122
|
+
_v$2: void 0,
|
|
1123
|
+
_v$3: void 0
|
|
1124
|
+
});
|
|
1125
|
+
return _el$2;
|
|
1126
|
+
}
|
|
1127
|
+
});
|
|
1128
|
+
}
|
|
1129
|
+
}));
|
|
1130
|
+
web.effect(() => web.className(_el$, PianoRollScale_module_default.PianoRollScale));
|
|
1131
|
+
return _el$;
|
|
1132
|
+
})();
|
|
1133
|
+
}, "PianoRollScale");
|
|
1134
|
+
var PianoRollScale_default = PianoRollScale;
|
|
1135
|
+
web.delegateEvents(["mousedown"]);
|
|
1136
|
+
|
|
1137
|
+
// src/PianoRoll.tsx
|
|
1138
|
+
var _tmpl$8 = /* @__PURE__ */ web.template(`<div><button><div></div></button></div>`, 6);
|
|
1139
|
+
var _tmpl$23 = /* @__PURE__ */ web.template(`<div><div></div><div></div></div>`, 6);
|
|
1140
|
+
var _tmpl$32 = /* @__PURE__ */ web.template(`<div><div><div></div></div></div>`, 6);
|
|
1141
|
+
var _tmpl$42 = /* @__PURE__ */ web.template(`<div></div>`, 2);
|
|
1142
|
+
var PianoRoll = /* @__PURE__ */ __name((allProps) => {
|
|
1143
|
+
const propsWithDefaults = solidJs.mergeProps({
|
|
1144
|
+
showAllTracks: false
|
|
1145
|
+
}, allProps);
|
|
1146
|
+
const [context, divProps] = splitContextProps(propsWithDefaults);
|
|
1147
|
+
return web.createComponent(PianoRollContextProvider, {
|
|
1148
|
+
value: context,
|
|
1149
|
+
get children() {
|
|
1150
|
+
const _el$ = _tmpl$42.cloneNode(true);
|
|
1151
|
+
web.spread(_el$, web.mergeProps(divProps, {
|
|
1152
|
+
get ["class"]() {
|
|
1153
|
+
return PianoRoll_module_default.PianoRoll;
|
|
1154
|
+
}
|
|
1155
|
+
}), false, true);
|
|
1156
|
+
web.insert(_el$, web.createComponent(PianoRollScrollZoomViewPort_default, {
|
|
1157
|
+
get children() {
|
|
1158
|
+
return [(() => {
|
|
1159
|
+
const _el$2 = _tmpl$32.cloneNode(true), _el$3 = _el$2.firstChild, _el$7 = _el$3.firstChild;
|
|
1160
|
+
web.insert(_el$2, web.createComponent(ZoomSliderControl_default, {
|
|
1161
|
+
orientation: "vertical",
|
|
1162
|
+
dimensionName: "verticalTracks"
|
|
1163
|
+
}), _el$3);
|
|
1164
|
+
web.insert(_el$3, web.createComponent(solidJs.Show, {
|
|
1165
|
+
get when() {
|
|
1166
|
+
return context.showTrackList;
|
|
1167
|
+
},
|
|
1168
|
+
get children() {
|
|
1169
|
+
const _el$4 = _tmpl$8.cloneNode(true), _el$5 = _el$4.firstChild, _el$6 = _el$5.firstChild;
|
|
1170
|
+
_el$4.style.setProperty("height", "30px");
|
|
1171
|
+
_el$4.style.setProperty("border-right", "1px black solid");
|
|
1172
|
+
_el$5.$$click = () => context.onModeChange(context.mode === "keys" ? "tracks" : "keys");
|
|
1173
|
+
_el$5.style.setProperty("font-size", "16px");
|
|
1174
|
+
_el$5.style.setProperty("line-height", "16px");
|
|
1175
|
+
_el$5.style.setProperty("cursor", "pointer");
|
|
1176
|
+
_el$5.style.setProperty("overflow", "hidden");
|
|
1177
|
+
web.insert(_el$6, () => context.mode === "keys" ? "\u2261" : "\u{1F3B9}");
|
|
1178
|
+
web.effect(() => web.setAttribute(_el$5, "title", context.mode === "keys" ? "Tracks Mode" : "Keys Mode"));
|
|
1179
|
+
return _el$4;
|
|
1180
|
+
}
|
|
1181
|
+
}), _el$7);
|
|
1182
|
+
_el$7.style.setProperty("flex", "1");
|
|
1183
|
+
_el$7.style.setProperty("display", "flex");
|
|
1184
|
+
_el$7.style.setProperty("overflow", "hidden");
|
|
1185
|
+
web.insert(_el$7, web.createComponent(solidJs.Show, {
|
|
1186
|
+
get when() {
|
|
1187
|
+
return context.showTrackList;
|
|
1188
|
+
},
|
|
1189
|
+
get children() {
|
|
1190
|
+
return web.createComponent(PianoRollTrackListScroller_default, {
|
|
1191
|
+
get children() {
|
|
1192
|
+
return web.createComponent(PianoRollTrackList_default, {});
|
|
1193
|
+
}
|
|
1194
|
+
});
|
|
1195
|
+
}
|
|
1196
|
+
}), null);
|
|
1197
|
+
web.insert(_el$7, web.createComponent(solidJs.Show, {
|
|
1198
|
+
get when() {
|
|
1199
|
+
return context.mode === "keys";
|
|
1200
|
+
},
|
|
1201
|
+
get children() {
|
|
1202
|
+
return web.createComponent(PianoRollKeys_default, {});
|
|
1203
|
+
}
|
|
1204
|
+
}), null);
|
|
1205
|
+
web.insert(_el$2, web.createComponent(PianoRollNotesScroller_default, {
|
|
1206
|
+
get children() {
|
|
1207
|
+
return [web.memo(() => allProps.children), (() => {
|
|
1208
|
+
const _el$8 = _tmpl$23.cloneNode(true), _el$9 = _el$8.firstChild, _el$10 = _el$9.nextSibling;
|
|
1209
|
+
_el$8.style.setProperty("width", "100%");
|
|
1210
|
+
_el$8.style.setProperty("display", "flex");
|
|
1211
|
+
_el$8.style.setProperty("height", "100%");
|
|
1212
|
+
_el$8.style.setProperty("flex-direction", "column");
|
|
1213
|
+
_el$8.style.setProperty("overflow", "hidden");
|
|
1214
|
+
_el$9.style.setProperty("height", "30px");
|
|
1215
|
+
web.insert(_el$9, web.createComponent(PianoRollScale_default, {}));
|
|
1216
|
+
_el$10.style.setProperty("flex", "1");
|
|
1217
|
+
_el$10.style.setProperty("position", "relative");
|
|
1218
|
+
_el$10.style.setProperty("overflow", "hidden");
|
|
1219
|
+
web.insert(_el$10, web.createComponent(PianoRollGrid_default, {}), null);
|
|
1220
|
+
web.insert(_el$10, web.createComponent(PianoRollNotes_default, {}), null);
|
|
1221
|
+
return _el$8;
|
|
1222
|
+
})()];
|
|
1223
|
+
}
|
|
1224
|
+
}), null);
|
|
1225
|
+
web.insert(_el$2, web.createComponent(ZoomSliderControl_default, {
|
|
1226
|
+
orientation: "vertical",
|
|
1227
|
+
get disabled() {
|
|
1228
|
+
return context.mode !== "keys";
|
|
1229
|
+
}
|
|
1230
|
+
}), null);
|
|
1231
|
+
web.effect((_p$) => {
|
|
1232
|
+
const _v$ = PianoRoll_module_default.PianoRollContainer, _v$2 = {
|
|
1233
|
+
[PianoRoll_module_default.PianoRollLeftColumn]: true,
|
|
1234
|
+
[PianoRoll_module_default.showTrackList]: context.showTrackList
|
|
1235
|
+
};
|
|
1236
|
+
_v$ !== _p$._v$ && web.className(_el$2, _p$._v$ = _v$);
|
|
1237
|
+
_p$._v$2 = web.classList(_el$3, _v$2, _p$._v$2);
|
|
1238
|
+
return _p$;
|
|
1239
|
+
}, {
|
|
1240
|
+
_v$: void 0,
|
|
1241
|
+
_v$2: void 0
|
|
1242
|
+
});
|
|
1243
|
+
return _el$2;
|
|
1244
|
+
})(), web.createComponent(ZoomSliderControl_default, {
|
|
1245
|
+
orientation: "horizontal",
|
|
1246
|
+
get style() {
|
|
1247
|
+
return {
|
|
1248
|
+
"margin-left": `${context.tracksScrollerClientRect.width + 24}px`,
|
|
1249
|
+
"margin-right": "24px"
|
|
1250
|
+
};
|
|
1251
|
+
}
|
|
1252
|
+
})];
|
|
1253
|
+
}
|
|
1254
|
+
}));
|
|
1255
|
+
return _el$;
|
|
1256
|
+
}
|
|
1257
|
+
});
|
|
1258
|
+
}, "PianoRoll");
|
|
1259
|
+
exports.PianoRoll = PianoRoll;
|
|
1260
|
+
web.delegateEvents(["click"]);
|
|
1261
|
+
var _tmpl$9 = /* @__PURE__ */ web.template(`<div class="PlayHead"></div>`, 2);
|
|
1262
|
+
var PlayHead = /* @__PURE__ */ __name((allProps) => {
|
|
1263
|
+
const [props, divProps] = solidJs.splitProps(allProps, ["position", "sync", "onPositionChange", "dimensionName"]);
|
|
1264
|
+
const viewPort = useViewPortDimension(props.dimensionName ?? "horizontal");
|
|
1265
|
+
solidJs.createEffect(() => {
|
|
1266
|
+
if (!props.sync)
|
|
1267
|
+
return;
|
|
1268
|
+
const maxPosition = viewPort.range;
|
|
1269
|
+
const newPosition = clamp(props.position - viewPort.range / viewPort.zoom / 2, 0, maxPosition);
|
|
1270
|
+
viewPort.onPositionChange?.(newPosition);
|
|
1271
|
+
});
|
|
1272
|
+
const leftPosition = solidJs.createMemo(() => viewPort.calculatePixelOffset(props.position));
|
|
1273
|
+
return (() => {
|
|
1274
|
+
const _el$ = _tmpl$9.cloneNode(true);
|
|
1275
|
+
web.spread(_el$, web.mergeProps(divProps, {
|
|
1276
|
+
get style() {
|
|
1277
|
+
return {
|
|
1278
|
+
position: "absolute",
|
|
1279
|
+
height: "100%",
|
|
1280
|
+
width: "2px",
|
|
1281
|
+
left: `${leftPosition()}px`,
|
|
1282
|
+
"background-color": "green",
|
|
1283
|
+
cursor: "pointer",
|
|
1284
|
+
...typeof divProps.style === "object" && divProps.style
|
|
1285
|
+
};
|
|
1286
|
+
},
|
|
1287
|
+
"onMouseDown": (event) => {
|
|
1288
|
+
event.preventDefault();
|
|
1289
|
+
event.stopPropagation();
|
|
1290
|
+
const handleMouseMove = /* @__PURE__ */ __name((event2) => {
|
|
1291
|
+
const newPosition = viewPort.calculatePosition(event2.clientX);
|
|
1292
|
+
props.onPositionChange?.(newPosition, event2);
|
|
1293
|
+
}, "handleMouseMove");
|
|
1294
|
+
const handleMouseUp = /* @__PURE__ */ __name(() => {
|
|
1295
|
+
window.removeEventListener("mousemove", handleMouseMove);
|
|
1296
|
+
window.removeEventListener("mouseup", handleMouseUp);
|
|
1297
|
+
}, "handleMouseUp");
|
|
1298
|
+
window.addEventListener("mousemove", handleMouseMove);
|
|
1299
|
+
window.addEventListener("mouseup", handleMouseUp);
|
|
1300
|
+
}
|
|
1301
|
+
}), false, false);
|
|
1302
|
+
return _el$;
|
|
1303
|
+
})();
|
|
1304
|
+
}, "PlayHead");
|
|
1305
|
+
exports.PlayHead = PlayHead;
|
|
1306
|
+
var useNotes = /* @__PURE__ */ __name(() => {
|
|
1307
|
+
const [notes, onNotesChange] = solidJs.createSignal([]);
|
|
1308
|
+
const onNoteChange = /* @__PURE__ */ __name((index, note) => {
|
|
1309
|
+
onNotesChange([...notes().slice(0, index), note, ...notes().splice(index + 1)]);
|
|
1310
|
+
}, "onNoteChange");
|
|
1311
|
+
const onInsertNote = /* @__PURE__ */ __name((note) => {
|
|
1312
|
+
const index = Math.max(
|
|
1313
|
+
notes().findIndex(({ ticks }) => ticks > note.ticks),
|
|
1314
|
+
0
|
|
1315
|
+
);
|
|
1316
|
+
onNotesChange([...notes().slice(0, index), note, ...notes().splice(index)]);
|
|
1317
|
+
return index;
|
|
1318
|
+
}, "onInsertNote");
|
|
1319
|
+
const onRemoveNote = /* @__PURE__ */ __name((index) => {
|
|
1320
|
+
onNotesChange([...notes().slice(0, index), ...notes().splice(index + 1)]);
|
|
1321
|
+
}, "onRemoveNote");
|
|
1322
|
+
return {
|
|
1323
|
+
notes,
|
|
1324
|
+
onNotesChange,
|
|
1325
|
+
onNoteChange,
|
|
1326
|
+
onInsertNote,
|
|
1327
|
+
onRemoveNote
|
|
1328
|
+
};
|
|
1329
|
+
}, "useNotes");
|
|
1330
|
+
exports.useNotes = useNotes;
|