solid-pianoroll 0.0.16 → 0.0.18

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/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { createComponent, delegateEvents, insert, effect, className, classList, setAttribute, template, use, memo, spread, mergeProps } from 'solid-js/web';
2
- import { createContext, splitProps, useContext, createEffect, createMemo, Index, createSignal, Show, batch, For, mergeProps as mergeProps$1 } from 'solid-js';
1
+ import { createComponent, use, spread, mergeProps as mergeProps$1, insert, effect, template, delegateEvents, className, classList, setAttribute, memo } from 'solid-js/web';
2
+ import { createContext, splitProps, useContext, createEffect, mergeProps, createMemo, createSignal, Index, Show, batch, For } from 'solid-js';
3
3
  import { createStore } from 'solid-js/store';
4
4
 
5
5
  function styleInject(css, ref) {
@@ -27,9 +27,9 @@ function styleInject(css, ref) {
27
27
  }
28
28
  }
29
29
 
30
- var css_248z$4 = ".PianoRoll-module_PianoRoll__rkRYx {\n box-sizing: border-box;\n display: flex;\n overflow: hidden;\n flex-direction: column;\n}\n\n.PianoRoll-module_PianoRollContainer__Oyxr7 {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: row;\n}\n";
31
- var styles$4 = {"PianoRoll":"PianoRoll-module_PianoRoll__rkRYx","PianoRollContainer":"PianoRoll-module_PianoRollContainer__Oyxr7"};
32
- styleInject(css_248z$4);
30
+ var css_248z$5 = ".PianoRoll-module_PianoRoll__rkRYx {\n box-sizing: border-box;\n display: flex;\n overflow: hidden;\n flex-direction: column;\n height: 100%;\n}\n\n.PianoRoll-module_PianoRollContainer__Oyxr7 {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: row;\n}\n";
31
+ var styles$5 = {"PianoRoll":"PianoRoll-module_PianoRoll__rkRYx","PianoRollContainer":"PianoRoll-module_PianoRollContainer__Oyxr7"};
32
+ styleInject(css_248z$5);
33
33
 
34
34
  const PianoRollContext = createContext();
35
35
  const PianoRollContextProvider = PianoRollContext.Provider;
@@ -38,11 +38,11 @@ const usePianoRollContext = () => {
38
38
  if (!context) throw new Error("No PianoRollContext found");
39
39
  return context;
40
40
  };
41
- const splitContextProps = allProps => splitProps(allProps, ["mode", "duration", "gridDivision", "tracks", "position", "ppq", "snapToGrid", "verticalPosition", "verticalZoom", "zoom", "onInsertNote", "onNoteChange", "onPositionChange", "onRemoveNote", "onVerticalPositionChange", "onVerticalZoomChange", "onZoomChange", "showAllTracks", "selectedTrackIndex", "onSelectedTrackIndexChange"]);
41
+ const splitContextProps = allProps => splitProps(allProps, ["ppq", "mode", "position", "zoom", "verticalZoom", "verticalPosition", "verticalTrackZoom", "verticalTrackPosition", "gridDivision", "snapToGrid", "duration", "tracks", "selectedTrackIndex", "pressedKeys", "onPpqChange", "onModeChange", "onPositionChange", "onZoomChange", "onVerticalZoomChange", "onVerticalPositionChange", "onVerticalTrackZoomChange", "onVerticalTrackPositionChange", "onGridDivisionChange", "onSnapToGridChange", "onDurationChange", "onTracksChange", "onNoteChange", "onInsertNote", "onRemoveNote", "onSelectedTrackIndexChange", "onPressedKeysChange", "showAllTracks", "showTrackList"]);
42
42
 
43
- var css_248z$3 = ".PianoRollKeys-module_PianoRollKeys__5vnQ0 {\n position: relative;\n height: 100%;\n width: 50px;\n border-width: 0;\n border-color: #000;\n border-style: solid;\n border-right-width: 1px;\n border-left-width: 1px;\n background: white;\n cursor: pointer;\n overflow: hidden;\n}\n\n.PianoRollKeys-module_Key__jybNC {\n transition-property: background-color, box-shadow;\n transition-duration: 400ms;\n transition-timing-function: ease-out;\n border-width: 0px;\n position: absolute;\n box-sizing: border-box;\n width: 120%;\n left: -20%;\n border-color: #000;\n border-style: solid;\n}\n\n.PianoRollKeys-module_black__7rncB {\n background: black;\n border-top-right-radius: 12%;\n border-bottom-right-radius: 12%;\n margin-left: -20%;\n z-index: 1;\n}\n\n.PianoRollKeys-module_white__fR2Lm {\n background: white;\n border-top-width: 0.5px;\n border-bottom-width: 0.5px;\n}\n\n.PianoRollKeys-module_down__GcNeZ {\n transition: none;\n background: red;\n}\n";
44
- var styles$3 = {"PianoRollKeys":"PianoRollKeys-module_PianoRollKeys__5vnQ0","Key":"PianoRollKeys-module_Key__jybNC","black":"PianoRollKeys-module_black__7rncB","white":"PianoRollKeys-module_white__fR2Lm","down":"PianoRollKeys-module_down__GcNeZ"};
45
- styleInject(css_248z$3);
43
+ var css_248z$4 = ".PianoRollKeys-module_PianoRollKeys__5vnQ0 {\n position: relative;\n height: 100%;\n width: 50px;\n border-width: 0;\n border-color: #000;\n border-style: solid;\n border-right-width: 1px;\n border-left-width: 1px;\n background: white;\n cursor: pointer;\n overflow: hidden;\n}\n\n.PianoRollKeys-module_Key__jybNC {\n transition-property: background-color, box-shadow;\n transition-duration: 200ms;\n transition-timing-function: ease-out;\n border-width: 0px;\n position: absolute;\n box-sizing: border-box;\n width: 120%;\n left: -20%;\n border-color: #000;\n border-style: solid;\n}\n\n.PianoRollKeys-module_black__7rncB {\n background: black;\n border-top-right-radius: 12%;\n border-bottom-right-radius: 12%;\n margin-left: -20%;\n z-index: 1;\n}\n\n.PianoRollKeys-module_white__fR2Lm {\n background: white;\n border-top-width: 0.5px;\n border-bottom-width: 0.5px;\n}\n\n.PianoRollKeys-module_down__GcNeZ {\n transition: none;\n background: red;\n}\n";
44
+ var styles$4 = {"PianoRollKeys":"PianoRollKeys-module_PianoRollKeys__5vnQ0","Key":"PianoRollKeys-module_Key__jybNC","black":"PianoRollKeys-module_black__7rncB","white":"PianoRollKeys-module_white__fR2Lm","down":"PianoRollKeys-module_down__GcNeZ"};
45
+ styleInject(css_248z$4);
46
46
 
47
47
  function createViewPortDimension(getState) {
48
48
  const getStateWithFunctions = () => ({
@@ -116,84 +116,248 @@ const useViewPortDimension = name => {
116
116
  return viewPort;
117
117
  };
118
118
 
119
- const _tmpl$$8 = /*#__PURE__*/template(`<div></div>`, 2);
120
- const PianoRollKeys = () => {
121
- const viewPort = createMemo(() => useViewPortDimension("vertical"));
119
+ var css_248z$3 = ".ScrollContainer-module_ScrollContainer__As0vK {\n height: 100%;\n width: 100%;\n z-index: 4;\n pointer-events: auto;\n}\n";
120
+ var styles$3 = {"ScrollContainer":"ScrollContainer-module_ScrollContainer__As0vK"};
121
+ styleInject(css_248z$3);
122
+
123
+ const _tmpl$$8 = /*#__PURE__*/template(`<div><div><div><div></div></div></div></div>`, 8);
124
+ const ScrollContainer = props => {
125
+ let scrollContentRef;
126
+ const [ownProps, divProps] = splitProps(props, ["ref", "verticalDimensionName", "horizontalDimensionName", "showScrollbar"]);
127
+ const propsWithDefaults = mergeProps({
128
+ verticalDimensionName: "vertical",
129
+ horizontalDimensionName: "horizontal",
130
+ showScrollbar: true
131
+ }, ownProps);
132
+ const verticalViewPort = createMemo(() => useViewPortDimension(propsWithDefaults.verticalDimensionName));
133
+ const horizontalViewPort = createMemo(() => useViewPortDimension(propsWithDefaults.horizontalDimensionName));
134
+ const handleScroll = event => {
135
+ event.preventDefault();
136
+ if (didUpdateScroll) {
137
+ didUpdateScroll = false;
138
+ return;
139
+ }
140
+ const maxVerticalPosition = verticalViewPort().calculateMaxPosition();
141
+ const maxPosition = horizontalViewPort().calculateMaxPosition();
142
+ const height = verticalViewPort().pixelSize;
143
+ const width = horizontalViewPort().pixelSize;
144
+ const {
145
+ scrollTop,
146
+ scrollLeft,
147
+ scrollWidth,
148
+ scrollHeight
149
+ } = event.currentTarget;
150
+ const scrollTopAmount = scrollTop / (scrollHeight - height);
151
+ const scrollLeftAmount = scrollLeft / (scrollWidth - width);
152
+ verticalViewPort().onPositionChange?.(maxVerticalPosition * scrollTopAmount);
153
+ horizontalViewPort().onPositionChange?.(maxPosition * scrollLeftAmount);
154
+ };
155
+ const handleWheel = event => {
156
+ if (event.altKey) {
157
+ event.preventDefault();
158
+ if (Math.abs(event.deltaX) > Math.abs(event.deltaY)) {
159
+ horizontalViewPort()?.onZoomChange?.(horizontalViewPort().zoom * (1 + event.deltaX / horizontalViewPort().pixelSize));
160
+ const maxPosition = horizontalViewPort().calculateMaxPosition();
161
+ horizontalViewPort()?.onPositionChange?.(Math.min(maxPosition, horizontalViewPort()?.position));
162
+ } else {
163
+ verticalViewPort()?.onZoomChange?.(verticalViewPort().zoom * (1 + event.deltaY / verticalViewPort().pixelSize));
164
+ const maxVerticalPosition = verticalViewPort().calculateMaxPosition();
165
+ verticalViewPort()?.onPositionChange?.(Math.min(maxVerticalPosition, verticalViewPort()?.position));
166
+ }
167
+ } else if (!props.showScrollbar) {
168
+ event.preventDefault();
169
+ event.currentTarget.scrollLeft += event.deltaX;
170
+ event.currentTarget.scrollTop += event.deltaY;
171
+ }
172
+ };
173
+ let didUpdateScroll = false;
174
+ createEffect(() => {
175
+ const maxVerticalPosition = verticalViewPort().calculateMaxPosition();
176
+ const maxPosition = horizontalViewPort().calculateMaxPosition();
177
+ const scrollTopAmount = maxVerticalPosition > 0 ? verticalViewPort().position / maxVerticalPosition : 0;
178
+ const scrollLeftAmount = maxPosition > 0 ? horizontalViewPort().position / maxPosition : 0;
179
+ const height = verticalViewPort().pixelSize;
180
+ const width = horizontalViewPort().pixelSize;
181
+ if (!scrollContentRef?.parentElement) return;
182
+ const scrollDivHeight = verticalViewPort().zoom * verticalViewPort().pixelSize;
183
+ const scrollTop = scrollTopAmount * (scrollDivHeight - height);
184
+ const scrollDivWidth = horizontalViewPort().zoom * horizontalViewPort().pixelSize;
185
+ const scrollLeft = scrollLeftAmount * (scrollDivWidth - width);
186
+ didUpdateScroll = true;
187
+ scrollContentRef.style.height = `${scrollDivHeight}px`;
188
+ scrollContentRef.style.width = `${scrollDivWidth}px`;
189
+ scrollContentRef.parentElement.scrollTo({
190
+ left: scrollLeft,
191
+ top: scrollTop
192
+ });
193
+ });
122
194
  return (() => {
123
- const _el$ = _tmpl$$8.cloneNode(true);
124
- insert(_el$, createComponent(Index, {
125
- each: keys,
126
- children: key => {
127
- const [isDown, setIsDown] = createSignal(false);
128
- const virtualDimensions = createMemo(() => viewPort().calculatePixelDimensions(127 - key().number, 1));
129
- const previousIsBlack = blackKeys.includes((key().number - 1) % 12);
130
- const nextIsBlack = blackKeys.includes((key().number + 1) % 12);
131
- return createComponent(Show, {
132
- get when() {
133
- return virtualDimensions().size > 0;
134
- },
135
- get children() {
136
- const _el$2 = _tmpl$$8.cloneNode(true);
137
- _el$2.$$mouseup = () => setIsDown(false);
138
- _el$2.$$mousedown = () => setIsDown(true);
139
- insert(_el$2, createComponent(Show, {
140
- get when() {
141
- return key().isBlack && false;
142
- },
143
- get children() {
144
- const _el$3 = _tmpl$$8.cloneNode(true);
145
- effect(_p$ => {
146
- const _v$ = styles$3["black-separator"],
147
- _v$2 = `${virtualDimensions().offset}px`,
148
- _v$3 = `${virtualDimensions().size / 2 - 0.25}px`;
149
- _v$ !== _p$._v$ && className(_el$3, _p$._v$ = _v$);
150
- _v$2 !== _p$._v$2 && _el$3.style.setProperty("top", _p$._v$2 = _v$2);
151
- _v$3 !== _p$._v$3 && _el$3.style.setProperty("height", _p$._v$3 = _v$3);
152
- return _p$;
153
- }, {
154
- _v$: undefined,
155
- _v$2: undefined,
156
- _v$3: undefined
157
- });
158
- return _el$3;
159
- }
160
- }));
161
- effect(_p$ => {
162
- const _v$4 = {
163
- [styles$3["Key"]]: true,
164
- [styles$3["black"]]: key().isBlack,
165
- [styles$3["white"]]: !key().isBlack,
166
- [styles$3["down"]]: isDown()
167
- },
168
- _v$5 = key().name,
169
- _v$6 = key().number % 12,
170
- _v$7 = `${virtualDimensions().offset - (!key().isBlack && nextIsBlack ? virtualDimensions().size / 2 : 0)}px`,
171
- _v$8 = `${virtualDimensions().size + (!key().isBlack && nextIsBlack ? virtualDimensions().size / 2 : 0) + (!key().isBlack && previousIsBlack ? virtualDimensions().size / 2 : 0)}px`,
172
- _v$9 = [`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`].filter(item => !!item).join(", ");
173
- _p$._v$4 = classList(_el$2, _v$4, _p$._v$4);
174
- _v$5 !== _p$._v$5 && setAttribute(_el$2, "title", _p$._v$5 = _v$5);
175
- _v$6 !== _p$._v$6 && setAttribute(_el$2, "data-index", _p$._v$6 = _v$6);
176
- _v$7 !== _p$._v$7 && _el$2.style.setProperty("top", _p$._v$7 = _v$7);
177
- _v$8 !== _p$._v$8 && _el$2.style.setProperty("height", _p$._v$8 = _v$8);
178
- _v$9 !== _p$._v$9 && _el$2.style.setProperty("box-shadow", _p$._v$9 = _v$9);
179
- return _p$;
180
- }, {
181
- _v$4: undefined,
182
- _v$5: undefined,
183
- _v$6: undefined,
184
- _v$7: undefined,
185
- _v$8: undefined,
186
- _v$9: undefined
187
- });
188
- return _el$2;
189
- }
190
- });
195
+ const _el$ = _tmpl$$8.cloneNode(true),
196
+ _el$2 = _el$.firstChild,
197
+ _el$3 = _el$2.firstChild,
198
+ _el$4 = _el$3.firstChild;
199
+ _el$.addEventListener("wheel", handleWheel);
200
+ _el$.addEventListener("scroll", handleScroll);
201
+ const _ref$ = props.ref;
202
+ typeof _ref$ === "function" ? use(_ref$, _el$) : props.ref = _el$;
203
+ spread(_el$, mergeProps$1({
204
+ get style() {
205
+ return {
206
+ overflow: propsWithDefaults.showScrollbar ? "scroll" : "hidden",
207
+ ...(typeof divProps.style === "object" && divProps.style)
208
+ };
209
+ },
210
+ get classList() {
211
+ return {
212
+ [styles$3.ScrollContainer]: true,
213
+ ...divProps.classList
214
+ };
191
215
  }
192
- }));
193
- effect(() => className(_el$, styles$3.PianoRollKeys));
216
+ }, divProps), false, true);
217
+ const _ref$2 = scrollContentRef;
218
+ typeof _ref$2 === "function" ? use(_ref$2, _el$2) : scrollContentRef = _el$2;
219
+ _el$3.style.setProperty("top", "0");
220
+ _el$3.style.setProperty("left", "0");
221
+ _el$3.style.setProperty("position", "sticky");
222
+ _el$3.style.setProperty("display", "flex");
223
+ _el$4.style.setProperty("position", "relative");
224
+ insert(_el$4, () => props.children);
225
+ effect(_p$ => {
226
+ const _v$ = `${verticalViewPort().pixelSize}px`,
227
+ _v$2 = `${horizontalViewPort().pixelSize}px`,
228
+ _v$3 = `${verticalViewPort().pixelSize}px`,
229
+ _v$4 = `${horizontalViewPort().pixelSize}px`;
230
+ _v$ !== _p$._v$ && _el$3.style.setProperty("height", _p$._v$ = _v$);
231
+ _v$2 !== _p$._v$2 && _el$3.style.setProperty("width", _p$._v$2 = _v$2);
232
+ _v$3 !== _p$._v$3 && _el$4.style.setProperty("height", _p$._v$3 = _v$3);
233
+ _v$4 !== _p$._v$4 && _el$4.style.setProperty("width", _p$._v$4 = _v$4);
234
+ return _p$;
235
+ }, {
236
+ _v$: undefined,
237
+ _v$2: undefined,
238
+ _v$3: undefined,
239
+ _v$4: undefined
240
+ });
194
241
  return _el$;
195
242
  })();
196
243
  };
244
+
245
+ const _tmpl$$7 = /*#__PURE__*/template(`<div></div>`, 2);
246
+ const PianoRollKeys = () => {
247
+ const viewPort = createMemo(() => useViewPortDimension("vertical"));
248
+ const [isMouseDown, setIsMouseDown] = createSignal(false);
249
+ const context = usePianoRollContext();
250
+ const handleMouseUp = () => {
251
+ setIsMouseDown(false);
252
+ };
253
+ createEffect(() => {
254
+ if (isMouseDown()) {
255
+ window.addEventListener("mouseup", handleMouseUp);
256
+ } else {
257
+ window.removeEventListener("mouseup", handleMouseUp);
258
+ }
259
+ });
260
+ return createComponent(ScrollContainer, {
261
+ get classList() {
262
+ return {
263
+ [styles$4.PianoRollKeys]: true
264
+ };
265
+ },
266
+ showScrollbar: false,
267
+ get children() {
268
+ return createComponent(Index, {
269
+ each: keys,
270
+ children: key => {
271
+ const isDown = createMemo(() => context.pressedKeys.includes(key().number));
272
+ const handleKeyDown = () => {
273
+ context.onPressedKeysChange?.([...context.pressedKeys, key().number]);
274
+ };
275
+ const handleKeyUp = () => {
276
+ context.onPressedKeysChange?.([...context.pressedKeys].filter(number => number !== key().number));
277
+ };
278
+ const virtualDimensions = createMemo(() => viewPort().calculatePixelDimensions(127 - key().number, 1));
279
+ const previousIsBlack = blackKeys.includes((key().number - 1) % 12);
280
+ const nextIsBlack = blackKeys.includes((key().number + 1) % 12);
281
+ return createComponent(Show, {
282
+ get when() {
283
+ return virtualDimensions().size > 0;
284
+ },
285
+ get children() {
286
+ const _el$ = _tmpl$$7.cloneNode(true);
287
+ _el$.addEventListener("mouseleave", () => {
288
+ if (isMouseDown()) {
289
+ handleKeyUp();
290
+ }
291
+ });
292
+ _el$.addEventListener("mouseenter", () => {
293
+ if (isMouseDown()) {
294
+ handleKeyDown();
295
+ }
296
+ });
297
+ _el$.$$mouseup = () => {
298
+ handleKeyUp();
299
+ };
300
+ _el$.$$mousedown = () => {
301
+ setIsMouseDown(true);
302
+ handleKeyDown();
303
+ };
304
+ insert(_el$, createComponent(Show, {
305
+ get when() {
306
+ return key().isBlack && false;
307
+ },
308
+ get children() {
309
+ const _el$2 = _tmpl$$7.cloneNode(true);
310
+ effect(_p$ => {
311
+ const _v$ = styles$4["black-separator"],
312
+ _v$2 = `${virtualDimensions().offset}px`,
313
+ _v$3 = `${virtualDimensions().size / 2 - 0.25}px`;
314
+ _v$ !== _p$._v$ && className(_el$2, _p$._v$ = _v$);
315
+ _v$2 !== _p$._v$2 && _el$2.style.setProperty("top", _p$._v$2 = _v$2);
316
+ _v$3 !== _p$._v$3 && _el$2.style.setProperty("height", _p$._v$3 = _v$3);
317
+ return _p$;
318
+ }, {
319
+ _v$: undefined,
320
+ _v$2: undefined,
321
+ _v$3: undefined
322
+ });
323
+ return _el$2;
324
+ }
325
+ }));
326
+ effect(_p$ => {
327
+ const _v$4 = {
328
+ [styles$4["Key"]]: true,
329
+ [styles$4["black"]]: key().isBlack,
330
+ [styles$4["white"]]: !key().isBlack,
331
+ [styles$4["down"]]: isDown()
332
+ },
333
+ _v$5 = key().name,
334
+ _v$6 = key().number % 12,
335
+ _v$7 = `${virtualDimensions().offset - (!key().isBlack && nextIsBlack ? virtualDimensions().size / 2 : 0)}px`,
336
+ _v$8 = `${virtualDimensions().size + (!key().isBlack && nextIsBlack ? virtualDimensions().size / 2 : 0) + (!key().isBlack && previousIsBlack ? virtualDimensions().size / 2 : 0)}px`,
337
+ _v$9 = [`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`].filter(item => !!item).join(", ");
338
+ _p$._v$4 = classList(_el$, _v$4, _p$._v$4);
339
+ _v$5 !== _p$._v$5 && setAttribute(_el$, "title", _p$._v$5 = _v$5);
340
+ _v$6 !== _p$._v$6 && setAttribute(_el$, "data-index", _p$._v$6 = _v$6);
341
+ _v$7 !== _p$._v$7 && _el$.style.setProperty("top", _p$._v$7 = _v$7);
342
+ _v$8 !== _p$._v$8 && _el$.style.setProperty("height", _p$._v$8 = _v$8);
343
+ _v$9 !== _p$._v$9 && _el$.style.setProperty("box-shadow", _p$._v$9 = _v$9);
344
+ return _p$;
345
+ }, {
346
+ _v$4: undefined,
347
+ _v$5: undefined,
348
+ _v$6: undefined,
349
+ _v$7: undefined,
350
+ _v$8: undefined,
351
+ _v$9: undefined
352
+ });
353
+ return _el$;
354
+ }
355
+ });
356
+ }
357
+ });
358
+ }
359
+ });
360
+ };
197
361
  const blackKeys = [1, 3, 6, 8, 10];
198
362
  const keyNames = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
199
363
  const keys = Array.from({
@@ -209,10 +373,10 @@ var css_248z$2 = ".PianoRollNotes-module_PianoRollNotes__6pF-y {\n position: ab
209
373
  var styles$2 = {"PianoRollNotes":"PianoRollNotes-module_PianoRollNotes__6pF-y","Note":"PianoRollNotes-module_Note__-jxLb","trimStart":"PianoRollNotes-module_trimStart__vuBlj","trimEnd":"PianoRollNotes-module_trimEnd__zPdjr"};
210
374
  styleInject(css_248z$2);
211
375
 
212
- const _tmpl$$7 = /*#__PURE__*/template(`<div></div>`, 2);
376
+ const _tmpl$$6 = /*#__PURE__*/template(`<div></div>`, 2);
213
377
  const PianoRollNotes = props => {
214
378
  const context = usePianoRollContext();
215
- const verticalViewPort = createMemo(() => useViewPortDimension("vertical"));
379
+ const verticalViewPort = createMemo(() => useViewPortDimension(context.mode === "keys" ? "vertical" : "verticalTracks"));
216
380
  const horizontalViewPort = createMemo(() => useViewPortDimension("horizontal"));
217
381
  const gridDivisionTicks = createMemo(() => context.ppq * 4 / context.gridDivision);
218
382
  const snapValueToGridIfEnabled = (value, altKey) => context.snapToGrid && !altKey ? Math.round(value / gridDivisionTicks()) * gridDivisionTicks() : value;
@@ -220,7 +384,7 @@ const PianoRollNotes = props => {
220
384
  const position = horizontalViewPort().calculatePosition(event.clientX);
221
385
  const existingNote = currentNote();
222
386
  const midi = context.mode === "keys" ? 127 - Math.floor(verticalViewPort().calculatePosition(event.clientY)) : existingNote?.midi ?? 60;
223
- const targetTrackIndex = context.mode === "tracks" ? Math.floor(verticalViewPort().calculatePosition(event.clientY)) : context.selectedTrackIndex ?? 0;
387
+ const targetTrackIndex = context.mode === "tracks" ? clamp(Math.floor(verticalViewPort().calculatePosition(event.clientY)), 0, context.tracks.length - 1) : context.selectedTrackIndex ?? 0;
224
388
  const eventPositionTicks = Math.floor(position / gridDivisionTicks()) * gridDivisionTicks();
225
389
  const velocity = 127;
226
390
  const ticks = existingNote?.ticks ?? eventPositionTicks;
@@ -248,7 +412,7 @@ const PianoRollNotes = props => {
248
412
  return noteDragMode ? [styles$2.Note, styles$2[noteDragMode]] : [styles$2.Note];
249
413
  };
250
414
  return (() => {
251
- const _el$ = _tmpl$$7.cloneNode(true);
415
+ const _el$ = _tmpl$$6.cloneNode(true);
252
416
  _el$.$$click = event => {
253
417
  if (currentNote()) {
254
418
  setCurrentNoteIndex(-1);
@@ -306,7 +470,7 @@ const PianoRollNotes = props => {
306
470
  return memo(() => !!verticalViewPort().isVisible(verticalVirtualDimensions()))() && horizontalViewPort().isVisible(horizontalDimensions());
307
471
  },
308
472
  get children() {
309
- const _el$2 = _tmpl$$7.cloneNode(true);
473
+ const _el$2 = _tmpl$$6.cloneNode(true);
310
474
  _el$2.$$mousedown = event => {
311
475
  event.stopPropagation();
312
476
  setIsDragging(true);
@@ -335,7 +499,7 @@ const PianoRollNotes = props => {
335
499
  };
336
500
  const previousTrackIndex = currentNoteTrackIndex();
337
501
  const previousNoteIndex = currentNoteIndex();
338
- const targetTrackIndex = context.mode === "tracks" ? Math.floor(verticalViewPort().calculatePosition(mouseMoveEvent.clientY)) : previousTrackIndex;
502
+ const targetTrackIndex = context.mode === "tracks" ? clamp(Math.floor(verticalViewPort().calculatePosition(mouseMoveEvent.clientY)), 0, context.tracks.length - 1) : previousTrackIndex;
339
503
  if (targetTrackIndex === previousTrackIndex) {
340
504
  context.onNoteChange?.(previousTrackIndex, previousNoteIndex, updatedNote);
341
505
  } else {
@@ -409,109 +573,6 @@ const PianoRollNotes = props => {
409
573
  };
410
574
  delegateEvents(["mousedown", "mousemove", "mouseup", "dblclick", "click"]);
411
575
 
412
- const _tmpl$$6 = /*#__PURE__*/template(`<div class="PianoRoll-Scroller"><div><div><div></div></div></div></div>`, 8);
413
- const ScrollContainer = props => {
414
- let scrollContentRef;
415
- const verticalViewPort = createMemo(() => useViewPortDimension("vertical"));
416
- const horizontalViewPort = createMemo(() => useViewPortDimension("horizontal"));
417
- const handleScroll = event => {
418
- event.preventDefault();
419
- if (didUpdateScroll) {
420
- didUpdateScroll = false;
421
- return;
422
- }
423
- const maxVerticalPosition = verticalViewPort().calculateMaxPosition();
424
- const maxPosition = horizontalViewPort().calculateMaxPosition();
425
- const height = verticalViewPort().pixelSize;
426
- const width = horizontalViewPort().pixelSize;
427
- const {
428
- scrollTop,
429
- scrollLeft,
430
- scrollWidth,
431
- scrollHeight
432
- } = event.currentTarget;
433
- const scrollTopAmount = scrollTop / (scrollHeight - height);
434
- const scrollLeftAmount = scrollLeft / (scrollWidth - width);
435
- verticalViewPort().onPositionChange?.(maxVerticalPosition * scrollTopAmount);
436
- horizontalViewPort().onPositionChange?.(maxPosition * scrollLeftAmount);
437
- };
438
- const handleWheel = event => {
439
- if (event.altKey) {
440
- event.preventDefault();
441
- if (Math.abs(event.deltaX) > Math.abs(event.deltaY)) {
442
- horizontalViewPort()?.onZoomChange?.(horizontalViewPort().zoom * (1 + event.deltaX / horizontalViewPort().pixelSize));
443
- const maxPosition = horizontalViewPort().calculateMaxPosition();
444
- horizontalViewPort()?.onPositionChange?.(Math.min(maxPosition, horizontalViewPort()?.position));
445
- } else {
446
- verticalViewPort()?.onZoomChange?.(verticalViewPort().zoom * (1 + event.deltaY / verticalViewPort().pixelSize));
447
- const maxVerticalPosition = verticalViewPort().calculateMaxPosition();
448
- verticalViewPort()?.onPositionChange?.(Math.min(maxVerticalPosition, verticalViewPort()?.position));
449
- }
450
- }
451
- };
452
- let didUpdateScroll = false;
453
- createEffect(() => {
454
- const maxVerticalPosition = verticalViewPort().calculateMaxPosition();
455
- const maxPosition = horizontalViewPort().calculateMaxPosition();
456
- const scrollTopAmount = maxVerticalPosition > 0 ? verticalViewPort().position / maxVerticalPosition : 0;
457
- const scrollLeftAmount = maxPosition > 0 ? horizontalViewPort().position / maxPosition : 0;
458
- const height = verticalViewPort().pixelSize;
459
- const width = horizontalViewPort().pixelSize;
460
- if (!scrollContentRef?.parentElement) return;
461
- const scrollDivHeight = verticalViewPort().zoom * verticalViewPort().pixelSize;
462
- const scrollTop = scrollTopAmount * (scrollDivHeight - height);
463
- const scrollDivWidth = horizontalViewPort().zoom * horizontalViewPort().pixelSize;
464
- const scrollLeft = scrollLeftAmount * (scrollDivWidth - width);
465
- didUpdateScroll = true;
466
- scrollContentRef.style.height = `${scrollDivHeight}px`;
467
- scrollContentRef.style.width = `${scrollDivWidth}px`;
468
- scrollContentRef.parentElement.scrollTo({
469
- left: scrollLeft,
470
- top: scrollTop
471
- });
472
- });
473
- return (() => {
474
- const _el$ = _tmpl$$6.cloneNode(true),
475
- _el$2 = _el$.firstChild,
476
- _el$3 = _el$2.firstChild,
477
- _el$4 = _el$3.firstChild;
478
- _el$.addEventListener("wheel", handleWheel);
479
- _el$.addEventListener("scroll", handleScroll);
480
- const _ref$ = props.ref;
481
- typeof _ref$ === "function" ? use(_ref$, _el$) : props.ref = _el$;
482
- _el$.style.setProperty("height", "100%");
483
- _el$.style.setProperty("width", "100%");
484
- _el$.style.setProperty("z-index", "4");
485
- _el$.style.setProperty("overflow", "scroll");
486
- _el$.style.setProperty("pointer-events", "auto");
487
- const _ref$2 = scrollContentRef;
488
- typeof _ref$2 === "function" ? use(_ref$2, _el$2) : scrollContentRef = _el$2;
489
- _el$3.style.setProperty("top", "0");
490
- _el$3.style.setProperty("left", "0");
491
- _el$3.style.setProperty("position", "sticky");
492
- _el$3.style.setProperty("display", "flex");
493
- _el$4.style.setProperty("position", "relative");
494
- insert(_el$4, () => props.children);
495
- effect(_p$ => {
496
- const _v$ = `${verticalViewPort().pixelSize}px`,
497
- _v$2 = `${horizontalViewPort().pixelSize}px`,
498
- _v$3 = `${verticalViewPort().pixelSize}px`,
499
- _v$4 = `${horizontalViewPort().pixelSize}px`;
500
- _v$ !== _p$._v$ && _el$3.style.setProperty("height", _p$._v$ = _v$);
501
- _v$2 !== _p$._v$2 && _el$3.style.setProperty("width", _p$._v$2 = _v$2);
502
- _v$3 !== _p$._v$3 && _el$4.style.setProperty("height", _p$._v$3 = _v$3);
503
- _v$4 !== _p$._v$4 && _el$4.style.setProperty("width", _p$._v$4 = _v$4);
504
- return _p$;
505
- }, {
506
- _v$: undefined,
507
- _v$2: undefined,
508
- _v$3: undefined,
509
- _v$4: undefined
510
- });
511
- return _el$;
512
- })();
513
- };
514
-
515
576
  var css_248z$1 = ".PianoRollGrid-module_PianoRollGrid__tG119 {\n position: relative;\n width: 100%;\n height: 100%;\n}\n\n.PianoRollGrid-module_PianoRollGrid-Row__nRMCs {\n position: absolute;\n border-style: solid;\n border-color: gray;\n}\n\n.PianoRollGrid-module_PianoRollGrid-Time__jLz3E {\n position: absolute;\n box-sizing: border-box;\n top: 0px;\n height: 100%;\n border-left-style: solid;\n border-left-width: 0.5px;\n}\n";
516
577
  var styles$1 = {"PianoRollGrid":"PianoRollGrid-module_PianoRollGrid__tG119","PianoRollGrid-Row":"PianoRollGrid-module_PianoRollGrid-Row__nRMCs","PianoRollGrid-Time":"PianoRollGrid-module_PianoRollGrid-Time__jLz3E"};
517
578
  styleInject(css_248z$1);
@@ -519,7 +580,7 @@ styleInject(css_248z$1);
519
580
  const _tmpl$$5 = /*#__PURE__*/template(`<div></div>`, 2);
520
581
  const PianoRollGrid = () => {
521
582
  const context = usePianoRollContext();
522
- const verticalViewPort = createMemo(() => useViewPortDimension("vertical"));
583
+ const verticalViewPort = createMemo(() => useViewPortDimension(context.mode === "keys" ? "vertical" : "verticalTracks"));
523
584
  const horizontalViewPort = createMemo(() => useViewPortDimension("horizontal"));
524
585
  const measureTicks = createMemo(() => context.ppq * 4);
525
586
  const selectedGridDivisorTicks = createMemo(() => measureTicks() / context.gridDivision);
@@ -702,14 +763,14 @@ function useBoundingClientRect(containerRef) {
702
763
 
703
764
  const _tmpl$$4 = /*#__PURE__*/template(`<input min="1" max="11" step="0.01">`, 1);
704
765
  const VerticalZoomControl = props => {
705
- const context = usePianoRollContext();
766
+ const dimension = createMemo(() => useViewPortDimension(props.dimensionName ?? "vertical"));
706
767
  return (() => {
707
768
  const _el$ = _tmpl$$4.cloneNode(true);
708
- spread(_el$, mergeProps(props, {
769
+ spread(_el$, mergeProps$1(props, {
709
770
  get value() {
710
- return context.verticalZoom;
771
+ return dimension().zoom;
711
772
  },
712
- "onInput": event => context.onVerticalZoomChange?.(event.currentTarget.valueAsNumber),
773
+ "onInput": event => dimension().onZoomChange?.(event.currentTarget.valueAsNumber),
713
774
  "type": "range"
714
775
  }, {
715
776
  orient: "vertical"
@@ -717,6 +778,7 @@ const VerticalZoomControl = props => {
717
778
  get style() {
718
779
  return {
719
780
  width: "16px",
781
+ transform: "rotate(180deg)",
720
782
  ...{
721
783
  "writing-mode": "bt-lr" /* IE */,
722
784
  "-webkit-appearance": "slider-vertical" /* WebKit */
@@ -730,14 +792,14 @@ const VerticalZoomControl = props => {
730
792
 
731
793
  const _tmpl$$3 = /*#__PURE__*/template(`<input max="500" min="1" step="0.01">`, 1);
732
794
  const HorizontalZoomControl = props => {
733
- const context = usePianoRollContext();
795
+ const dimension = createMemo(() => useViewPortDimension(props.dimensionName ?? "horizontal"));
734
796
  return (() => {
735
797
  const _el$ = _tmpl$$3.cloneNode(true);
736
- spread(_el$, mergeProps(props, {
798
+ spread(_el$, mergeProps$1(props, {
737
799
  get value() {
738
- return context.zoom;
800
+ return dimension().zoom;
739
801
  },
740
- "onInput": event => context.onZoomChange?.(event.currentTarget.valueAsNumber),
802
+ "onInput": event => dimension().onZoomChange?.(event.currentTarget.valueAsNumber),
741
803
  "type": "range",
742
804
  get style() {
743
805
  return {
@@ -758,7 +820,7 @@ styleInject(css_248z);
758
820
  const _tmpl$$2 = /*#__PURE__*/template(`<div></div>`, 2),
759
821
  _tmpl$2$1 = /*#__PURE__*/template(`<div> </div>`, 2);
760
822
  const PianoRollTrackList = () => {
761
- const viewPort = createMemo(() => useViewPortDimension("vertical"));
823
+ const viewPort = createMemo(() => useViewPortDimension("verticalTracks"));
762
824
  const context = usePianoRollContext();
763
825
  return (() => {
764
826
  const _el$ = _tmpl$$2.cloneNode(true);
@@ -767,7 +829,7 @@ const PianoRollTrackList = () => {
767
829
  return context.tracks;
768
830
  },
769
831
  children: (track, index) => {
770
- const virtualDimensions = createMemo(() => viewPort().calculatePixelDimensions(context.mode === "tracks" ? index : index * 8, context.mode === "tracks" ? 1 : 8));
832
+ const virtualDimensions = createMemo(() => viewPort().calculatePixelDimensions(index, 1));
771
833
  return createComponent(Show, {
772
834
  get when() {
773
835
  return virtualDimensions().size > 0;
@@ -811,100 +873,149 @@ const PianoRollTrackList = () => {
811
873
  };
812
874
  delegateEvents(["click"]);
813
875
 
814
- const _tmpl$$1 = /*#__PURE__*/template(`<div></div>`, 2),
815
- _tmpl$2 = /*#__PURE__*/template(`<div><div></div></div>`, 4);
876
+ const _tmpl$$1 = /*#__PURE__*/template(`<div><div></div></div>`, 4),
877
+ _tmpl$2 = /*#__PURE__*/template(`<div></div>`, 2);
816
878
  const PianoRoll = allProps => {
817
- const [contextProps, divProps] = splitContextProps(allProps);
879
+ const propsWithDefaults = mergeProps({
880
+ showAllTracks: false
881
+ }, allProps);
882
+ const [context, divProps] = splitContextProps(propsWithDefaults);
818
883
  const [scrollerRef, setScrollerRef] = createSignal();
884
+ const [trackScrollerRef, setTrackScrollerRef] = createSignal();
819
885
  const clientRect = useBoundingClientRect(scrollerRef);
886
+ const trackClientRef = useBoundingClientRect(trackScrollerRef);
820
887
  const zoomFactor = 500;
821
888
  const minZoom = createMemo(() => 1 / (zoomFactor / clientRect().width));
822
889
  const maxZoom = createMemo(() => 500 * (zoomFactor / clientRect().width));
823
890
  const minVerticalZoom = createMemo(() => 1 / (zoomFactor / clientRect().height));
824
891
  const maxVerticalZoom = createMemo(() => 10 * (zoomFactor / clientRect().height));
892
+ const minVerticalTracksZoom = createMemo(() => 0.8 / (zoomFactor / trackClientRef().height));
893
+ const maxVerticalTracksZoom = createMemo(() => 3 * (zoomFactor / trackClientRef().height));
825
894
  createEffect(isInitial => {
826
895
  if (isInitial) return false;
827
- if (contextProps.mode === "tracks") {
828
- contextProps.onVerticalPositionChange?.(0);
896
+ if (context.mode === "tracks") {
897
+ context.onVerticalPositionChange?.(0);
829
898
  }
830
899
  }, true);
831
900
  return createComponent(PianoRollContextProvider, {
832
- value: contextProps,
901
+ value: context,
833
902
  get children() {
834
- const _el$ = _tmpl$2.cloneNode(true),
835
- _el$2 = _el$.firstChild;
836
- spread(_el$, mergeProps(divProps, {
903
+ const _el$ = _tmpl$2.cloneNode(true);
904
+ spread(_el$, mergeProps$1(divProps, {
837
905
  get ["class"]() {
838
- return styles$4.PianoRoll;
906
+ return styles$5.PianoRoll;
839
907
  }
840
908
  }), false, true);
841
- insert(_el$2, createComponent(ScrollZoomViewPort, {
909
+ insert(_el$, createComponent(ScrollZoomViewPort, {
842
910
  dimensions: {
843
911
  horizontal: () => ({
844
912
  pixelOffset: clientRect().left,
845
913
  pixelSize: clientRect().width,
846
- position: contextProps.position,
847
- range: contextProps.duration,
848
- zoom: contextProps.zoom * (zoomFactor / clientRect().width),
849
- onPositionChange: contextProps.onPositionChange,
850
- onZoomChange: zoom => contextProps.onZoomChange?.(clamp(zoom / (zoomFactor / clientRect().width), minZoom(), maxZoom()))
914
+ position: context.position,
915
+ range: context.duration,
916
+ zoom: context.zoom * (zoomFactor / clientRect().width),
917
+ onPositionChange: context.onPositionChange,
918
+ onZoomChange: zoom => context.onZoomChange?.(clamp(zoom / (zoomFactor / clientRect().width), minZoom(), maxZoom()))
851
919
  }),
852
920
  vertical: () => ({
853
921
  pixelOffset: clientRect().top,
854
922
  pixelSize: clientRect().height,
855
- position: contextProps.verticalPosition,
856
- range: contextProps.mode === "keys" ? 128 : Math.max(contextProps.tracks.length, 16),
857
- zoom: contextProps.verticalZoom * (zoomFactor / clientRect().height),
858
- onPositionChange: contextProps.onVerticalPositionChange,
859
- onZoomChange: verticalZoom => contextProps.onVerticalZoomChange?.(clamp(verticalZoom / (zoomFactor / clientRect().height), minVerticalZoom(), maxVerticalZoom()))
923
+ position: context.verticalPosition,
924
+ range: 128,
925
+ zoom: context.verticalZoom * (zoomFactor / clientRect().height),
926
+ onPositionChange: context.onVerticalPositionChange,
927
+ onZoomChange: verticalZoom => context.onVerticalZoomChange?.(clamp(verticalZoom / (zoomFactor / clientRect().height), minVerticalZoom(), maxVerticalZoom()))
928
+ }),
929
+ horizontalTracks: () => ({
930
+ pixelOffset: clientRect().left,
931
+ pixelSize: clientRect().width,
932
+ position: 0,
933
+ range: 1,
934
+ zoom: 1
935
+ }),
936
+ verticalTracks: () => ({
937
+ pixelOffset: trackClientRef().top,
938
+ pixelSize: trackClientRef().height,
939
+ position: context.verticalTrackPosition,
940
+ range: context.tracks.length,
941
+ zoom: context.verticalTrackZoom * (zoomFactor / trackClientRef().height),
942
+ onPositionChange: context.onVerticalTrackPositionChange,
943
+ onZoomChange: verticalTrackZoom => context.onVerticalTrackZoomChange?.(clamp(verticalTrackZoom / (zoomFactor / trackClientRef().height), minVerticalTracksZoom(), maxVerticalTracksZoom()))
860
944
  })
861
945
  },
862
946
  get children() {
863
947
  return [(() => {
864
- const _el$3 = _tmpl$$1.cloneNode(true);
948
+ const _el$2 = _tmpl$$1.cloneNode(true),
949
+ _el$3 = _el$2.firstChild;
950
+ insert(_el$2, createComponent(VerticalZoomControl, {
951
+ get min() {
952
+ return minVerticalTracksZoom();
953
+ },
954
+ get max() {
955
+ return maxVerticalTracksZoom();
956
+ },
957
+ dimensionName: "verticalTracks"
958
+ }), _el$3);
865
959
  _el$3.style.setProperty("display", "flex");
866
960
  _el$3.style.setProperty("width", "20%");
867
961
  insert(_el$3, createComponent(Show, {
868
962
  get when() {
869
- return allProps.showTrackList;
963
+ return context.showTrackList;
870
964
  },
871
965
  get children() {
872
- return createComponent(PianoRollTrackList, {});
966
+ return createComponent(ScrollContainer, {
967
+ ref: setTrackScrollerRef,
968
+ horizontalDimensionName: "horizontalTracks",
969
+ verticalDimensionName: "verticalTracks",
970
+ get showScrollbar() {
971
+ return context.mode === "keys";
972
+ },
973
+ get children() {
974
+ return createComponent(PianoRollTrackList, {});
975
+ }
976
+ });
873
977
  }
874
978
  }), null);
875
979
  insert(_el$3, createComponent(Show, {
876
980
  get when() {
877
- return contextProps.mode === "keys";
981
+ return context.mode === "keys";
878
982
  },
879
983
  get children() {
880
984
  return createComponent(PianoRollKeys, {});
881
985
  }
882
986
  }), null);
883
- return _el$3;
884
- })(), createComponent(ScrollContainer, {
885
- ref: setScrollerRef,
886
- get children() {
887
- return [memo(() => allProps.children), createComponent(PianoRollGrid, {}), createComponent(PianoRollNotes, {})];
888
- }
889
- }), createComponent(VerticalZoomControl, {
987
+ insert(_el$2, createComponent(ScrollContainer, {
988
+ ref: setScrollerRef,
989
+ get verticalDimensionName() {
990
+ return context.mode === "keys" ? "vertical" : "verticalTracks";
991
+ },
992
+ get children() {
993
+ return [memo(() => allProps.children), createComponent(PianoRollGrid, {}), createComponent(PianoRollNotes, {})];
994
+ }
995
+ }), null);
996
+ insert(_el$2, createComponent(VerticalZoomControl, {
997
+ get min() {
998
+ return minVerticalZoom();
999
+ },
1000
+ get max() {
1001
+ return maxVerticalZoom();
1002
+ },
1003
+ get disabled() {
1004
+ return context.mode !== "keys";
1005
+ }
1006
+ }), null);
1007
+ effect(() => className(_el$2, styles$5.PianoRollContainer));
1008
+ return _el$2;
1009
+ })(), createComponent(HorizontalZoomControl, {
890
1010
  get min() {
891
- return minVerticalZoom();
1011
+ return minZoom();
892
1012
  },
893
1013
  get max() {
894
- return maxVerticalZoom();
1014
+ return maxZoom();
895
1015
  }
896
1016
  })];
897
1017
  }
898
1018
  }));
899
- insert(_el$, createComponent(HorizontalZoomControl, {
900
- get min() {
901
- return minZoom();
902
- },
903
- get max() {
904
- return maxZoom();
905
- }
906
- }), null);
907
- effect(() => className(_el$2, styles$4.PianoRollContainer));
908
1019
  return _el$;
909
1020
  }
910
1021
  });
@@ -912,7 +1023,7 @@ const PianoRoll = allProps => {
912
1023
 
913
1024
  const _tmpl$ = /*#__PURE__*/template(`<div class="PlayHead"></div>`, 2);
914
1025
  const PlayHead = allProps => {
915
- const propsWithDefauls = mergeProps$1({
1026
+ const propsWithDefauls = mergeProps({
916
1027
  playHeadPosition: 0,
917
1028
  sync: false
918
1029
  }, allProps);
@@ -927,7 +1038,7 @@ const PlayHead = allProps => {
927
1038
  const leftPosition = createMemo(() => viewPort.calculatePixelOffset(props.playHeadPosition));
928
1039
  return (() => {
929
1040
  const _el$ = _tmpl$.cloneNode(true);
930
- spread(_el$, mergeProps(divProps, {
1041
+ spread(_el$, mergeProps$1(divProps, {
931
1042
  get style() {
932
1043
  return {
933
1044
  position: "absolute",
@@ -988,37 +1099,83 @@ const useNotes = () => {
988
1099
  };
989
1100
  };
990
1101
 
991
- const usePianoRoll = () => {
992
- const [ppq, onPpqChange] = createSignal(120);
993
- const [mode, onModeChange] = createSignal("tracks");
994
- const [position, onPositionChange] = createSignal(0);
995
- const [zoom, onZoomChange] = createSignal(10);
996
- const [verticalZoom, onVerticalZoomChange] = createSignal(5);
997
- const [verticalPosition, onVerticalPositionChange] = createSignal(44);
998
- const [gridDivision, onGridDivisionChange] = createSignal(4);
999
- const [snapToGrid, onSnapToGridChange] = createSignal(true);
1000
- const [duration, onDurationChange] = createSignal(0);
1001
- return {
1002
- ppq,
1102
+ const createPianoRollstate = defaultState => {
1103
+ const [state, setState] = createStore({
1104
+ ppq: 0,
1105
+ mode: "keys",
1106
+ position: 0,
1107
+ zoom: 10,
1108
+ verticalZoom: 5,
1109
+ verticalPosition: 44,
1110
+ verticalTrackZoom: 0.5,
1111
+ verticalTrackPosition: 0,
1112
+ gridDivision: 4,
1113
+ snapToGrid: true,
1114
+ duration: 0,
1115
+ tracks: [],
1116
+ selectedTrackIndex: 0,
1117
+ pressedKeys: [],
1118
+ ...defaultState
1119
+ });
1120
+ const updateNotes = async (trackIndex, getNotes) => {
1121
+ const track = state.tracks[trackIndex];
1122
+ if (!track) return;
1123
+ const notes = track.notes;
1124
+ onTracksChange([...state.tracks.slice(0, trackIndex), {
1125
+ ...track,
1126
+ notes: getNotes(notes)
1127
+ }, ...state.tracks.slice(trackIndex + 1)]);
1128
+ };
1129
+ const onNoteChange = (trackIndex, noteIndex, note) => {
1130
+ updateNotes(trackIndex, notes => [...notes.slice(0, noteIndex), note, ...notes.slice(noteIndex + 1)]);
1131
+ };
1132
+ const onInsertNote = (trackIndex, note) => {
1133
+ const track = state.tracks[trackIndex];
1134
+ if (!track) return -1;
1135
+ const notes = track.notes;
1136
+ const newNoteIndex = Math.max(notes.findIndex(({
1137
+ ticks
1138
+ }) => ticks > note.ticks), 0);
1139
+ updateNotes(trackIndex, notes => [...notes.slice(0, newNoteIndex), note, ...notes.slice(newNoteIndex)]);
1140
+ return newNoteIndex;
1141
+ };
1142
+ const onRemoveNote = (trackIndex, noteIndex) => {
1143
+ updateNotes(trackIndex, notes => [...notes.slice(0, noteIndex), ...notes.slice(noteIndex + 1)]);
1144
+ };
1145
+ const onPpqChange = ppq => setState("ppq", ppq);
1146
+ const onModeChange = mode => setState("mode", mode);
1147
+ const onPositionChange = position => setState("position", position);
1148
+ const onZoomChange = zoom => setState("zoom", zoom);
1149
+ const onVerticalZoomChange = verticalZoom => setState("verticalZoom", verticalZoom);
1150
+ const onVerticalPositionChange = verticalPosition => setState("verticalPosition", verticalPosition);
1151
+ const onVerticalTrackZoomChange = verticalTrackZoom => setState("verticalTrackZoom", verticalTrackZoom);
1152
+ const onVerticalTrackPositionChange = verticalTrackPosition => setState("verticalTrackPosition", verticalTrackPosition);
1153
+ const onGridDivisionChange = gridDivision => setState("gridDivision", gridDivision);
1154
+ const onSnapToGridChange = snapToGrid => setState("snapToGrid", snapToGrid);
1155
+ const onDurationChange = duration => setState("duration", duration);
1156
+ const onTracksChange = tracks => setState("tracks", tracks);
1157
+ const onSelectedTrackIndexChange = selectedTrackIndex => setState("selectedTrackIndex", selectedTrackIndex);
1158
+ const onPressedKeysChange = pressedKeys => setState("pressedKeys", pressedKeys);
1159
+ return mergeProps(state, {
1003
1160
  onPpqChange,
1004
- position,
1161
+ onModeChange,
1005
1162
  onPositionChange,
1006
- zoom,
1007
1163
  onZoomChange,
1008
- verticalPosition,
1009
- onVerticalPositionChange,
1010
- verticalZoom,
1011
1164
  onVerticalZoomChange,
1012
- gridDivision,
1165
+ onVerticalPositionChange,
1166
+ onVerticalTrackZoomChange,
1167
+ onVerticalTrackPositionChange,
1013
1168
  onGridDivisionChange,
1014
- snapToGrid,
1015
1169
  onSnapToGridChange,
1016
- mode,
1017
- onModeChange,
1018
- duration,
1019
- onDurationChange
1020
- };
1170
+ onDurationChange,
1171
+ onTracksChange,
1172
+ onNoteChange,
1173
+ onInsertNote,
1174
+ onRemoveNote,
1175
+ onSelectedTrackIndexChange,
1176
+ onPressedKeysChange
1177
+ });
1021
1178
  };
1022
1179
 
1023
- export { PianoRoll, PlayHead, useNotes, usePianoRoll };
1180
+ export { PianoRoll, PlayHead, createPianoRollstate, useNotes };
1024
1181
  //# sourceMappingURL=index.js.map