solid-pianoroll 0.0.11 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -29,7 +29,7 @@ function styleInject(css, ref) {
29
29
  }
30
30
  }
31
31
 
32
- var css_248z$3 = ".PianoRoll-module_PianoRoll__rkRYx {\n box-sizing: border-box;\n display: flex;\n overflow: hidden;\n flex-direction: column;\n padding-top: 16px;\n padding-left: 16px;\n}\n\n.PianoRoll-module_PianoRollContainer__Oyxr7 {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: row;\n}\n";
32
+ var css_248z$3 = ".PianoRoll-module_PianoRoll__rkRYx {\n box-sizing: border-box;\n display: flex;\n overflow: hidden;\n flex-direction: column;\n}\n\n.PianoRoll-module_PianoRollContainer__Oyxr7 {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: row;\n}\n";
33
33
  var styles$3 = {"PianoRoll":"PianoRoll-module_PianoRoll__rkRYx","PianoRollContainer":"PianoRoll-module_PianoRollContainer__Oyxr7"};
34
34
  styleInject(css_248z$3);
35
35
 
@@ -40,10 +40,30 @@ const usePianoRollContext = () => {
40
40
  if (!context) throw new Error("No PianoRollContext found");
41
41
  return context;
42
42
  };
43
+ const splitContextProps = allProps => solidJs.splitProps(allProps, ["condensed", "duration", "gridDivision", "notes", "position", "ppq", "snapToGrid", "verticalPosition", "verticalZoom", "zoom", "onInsertNote", "onNoteChange", "onPositionChange", "onRemoveNote", "onVerticalPositionChange", "onVerticalZoomChange", "onZoomChange"]);
43
44
 
44
- var css_248z$2 = ".PianoRollKeys-module_PianoRollKeys__5vnQ0 {\n position: relative;\n height: 100%;\n width: 50px;\n}\n\n.PianoRollKeys-module_Key__jybNC {\n border-width: 0px;\n position: absolute;\n box-sizing: border-box;\n width: 100%;\n border-color: #000;\n border-style: solid;\n border-right-width: 1px;\n}\n\n.PianoRollKeys-module_black__7rncB {\n background: black;\n}\n\n.PianoRollKeys-module_white__fR2Lm {\n background: white;\n}\n\n.PianoRollKeys-module_whiteAndNextIsWhite__PN1O8 {\n border-top-width: 0.1px;\n}\n\n.PianoRollKeys-module_whiteAndPreviousIsWhite__-fP3q {\n border-bottom-width: 0.1px;\n}\n";
45
- var styles$2 = {"PianoRollKeys":"PianoRollKeys-module_PianoRollKeys__5vnQ0","Key":"PianoRollKeys-module_Key__jybNC","black":"PianoRollKeys-module_black__7rncB","white":"PianoRollKeys-module_white__fR2Lm","whiteAndNextIsWhite":"PianoRollKeys-module_whiteAndNextIsWhite__PN1O8","whiteAndPreviousIsWhite":"PianoRollKeys-module_whiteAndPreviousIsWhite__-fP3q"};
46
- styleInject(css_248z$2);
45
+ const _tmpl$$7 = /*#__PURE__*/web.template(`<input max="500" min="1" step="0.01">`, 1);
46
+ const HorizontalZoomControl = props => {
47
+ const context = usePianoRollContext();
48
+ return (() => {
49
+ const _el$ = _tmpl$$7.cloneNode(true);
50
+ web.spread(_el$, web.mergeProps(props, {
51
+ get value() {
52
+ return context.zoom;
53
+ },
54
+ "onInput": event => context.onZoomChange?.(event.currentTarget.valueAsNumber),
55
+ "type": "range",
56
+ get style() {
57
+ return {
58
+ "margin-left": "50px",
59
+ "margin-right": "16px",
60
+ ...(typeof props.style === "object" && props.style)
61
+ };
62
+ }
63
+ }), false, false);
64
+ return _el$;
65
+ })();
66
+ };
47
67
 
48
68
  function createViewPortDimension(getState) {
49
69
  const getStateWithFunctions = () => ({
@@ -52,7 +72,8 @@ function createViewPortDimension(getState) {
52
72
  calculatePosition,
53
73
  calculatePixelDimensions,
54
74
  calculateVisibleRange,
55
- calculateMaxPosition
75
+ calculateMaxPosition,
76
+ isVisible
56
77
  });
57
78
  const [state, setState] = store.createStore(getStateWithFunctions());
58
79
  solidJs.createEffect(() => setState(getStateWithFunctions()));
@@ -82,6 +103,12 @@ function createViewPortDimension(getState) {
82
103
  size
83
104
  };
84
105
  }
106
+ function isVisible({
107
+ offset,
108
+ size
109
+ }) {
110
+ return offset + size > 0 && offset < state.pixelSize;
111
+ }
85
112
  return state;
86
113
  }
87
114
  const clamp = (value, min, max) => Math.max(min, Math.min(max, value));
@@ -109,70 +136,11 @@ const useViewPortDimension = name => {
109
136
  return viewPort;
110
137
  };
111
138
 
112
- const _tmpl$$6 = /*#__PURE__*/web.template(`<div></div>`, 2);
113
- const PianoRollKeys = () => {
114
- const viewPort = solidJs.createMemo(() => useViewPortDimension("vertical"));
115
- return (() => {
116
- const _el$ = _tmpl$$6.cloneNode(true);
117
- web.insert(_el$, web.createComponent(solidJs.Index, {
118
- each: keys,
119
- children: key => {
120
- const virtualDimensions = solidJs.createMemo(() => viewPort().calculatePixelDimensions(127 - key().number, 1));
121
- return web.createComponent(solidJs.Show, {
122
- get when() {
123
- return virtualDimensions().size > 0;
124
- },
125
- get children() {
126
- const _el$2 = _tmpl$$6.cloneNode(true);
127
- web.effect(_p$ => {
128
- const _v$ = {
129
- [styles$2["Key"]]: true,
130
- [styles$2["black"]]: key().isBlack,
131
- [styles$2["white"]]: !key().isBlack,
132
- [styles$2["whiteAndNextIsWhite"]]: !key().isBlack && !blackKeys.includes((key().number + 1) % 12),
133
- [styles$2["whiteAndPreviousIsWhite"]]: !key().isBlack && !blackKeys.includes((key().number - 1) % 12)
134
- },
135
- _v$2 = key().name,
136
- _v$3 = key().number % 12,
137
- _v$4 = `${virtualDimensions().offset}px`,
138
- _v$5 = `${virtualDimensions().size}px`;
139
- _p$._v$ = web.classList(_el$2, _v$, _p$._v$);
140
- _v$2 !== _p$._v$2 && web.setAttribute(_el$2, "title", _p$._v$2 = _v$2);
141
- _v$3 !== _p$._v$3 && web.setAttribute(_el$2, "data-index", _p$._v$3 = _v$3);
142
- _v$4 !== _p$._v$4 && _el$2.style.setProperty("top", _p$._v$4 = _v$4);
143
- _v$5 !== _p$._v$5 && _el$2.style.setProperty("height", _p$._v$5 = _v$5);
144
- return _p$;
145
- }, {
146
- _v$: undefined,
147
- _v$2: undefined,
148
- _v$3: undefined,
149
- _v$4: undefined,
150
- _v$5: undefined
151
- });
152
- return _el$2;
153
- }
154
- });
155
- }
156
- }));
157
- web.effect(() => web.className(_el$, styles$2.PianoRollKeys));
158
- return _el$;
159
- })();
160
- };
161
- const blackKeys = [1, 3, 6, 8, 10];
162
- const keyNames = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
163
- const keys = Array.from({
164
- length: 128
165
- }).map((_, index) => ({
166
- number: index,
167
- name: `${keyNames[index % 12]} ${Math.floor(index / 12) - 2}`,
168
- isBlack: blackKeys.includes(index % 12)
169
- }));
170
-
171
- var css_248z$1 = ".PianoRollNotes-module_PianoRollNotes__6pF-y {\n position: absolute;\n flex: 1;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n}\n.PianoRollNotes-module_PianoRollNotes__6pF-y .PianoRollNotes-module_Note__-jxLb {\n position: absolute;\n box-sizing: border-box;\n border-width: 0.5px;\n border-style: solid;\n border-color: #a00;\n cursor: pointer;\n}\n.PianoRollNotes-module_PianoRollNotes__6pF-y .PianoRollNotes-module_Note__-jxLb.PianoRollNotes-module_trimStart__vuBlj {\n cursor: w-resize;\n}\n.PianoRollNotes-module_PianoRollNotes__6pF-y .PianoRollNotes-module_Note__-jxLb.PianoRollNotes-module_trimEnd__zPdjr {\n cursor: e-resize;\n}";
172
- var styles$1 = {"PianoRollNotes":"PianoRollNotes-module_PianoRollNotes__6pF-y","Note":"PianoRollNotes-module_Note__-jxLb","trimStart":"PianoRollNotes-module_trimStart__vuBlj","trimEnd":"PianoRollNotes-module_trimEnd__zPdjr"};
173
- styleInject(css_248z$1);
139
+ var css_248z$2 = ".PianoRollNotes-module_PianoRollNotes__6pF-y {\n position: absolute;\n flex: 1;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 1;\n cursor: grab;\n}\n.PianoRollNotes-module_PianoRollNotes__6pF-y .PianoRollNotes-module_Note__-jxLb {\n position: absolute;\n box-sizing: border-box;\n border-width: 0.5px;\n border-style: solid;\n border-color: #a00;\n cursor: move;\n}\n.PianoRollNotes-module_PianoRollNotes__6pF-y .PianoRollNotes-module_Note__-jxLb.PianoRollNotes-module_trimStart__vuBlj {\n cursor: w-resize;\n}\n.PianoRollNotes-module_PianoRollNotes__6pF-y .PianoRollNotes-module_Note__-jxLb.PianoRollNotes-module_trimEnd__zPdjr {\n cursor: e-resize;\n}";
140
+ var styles$2 = {"PianoRollNotes":"PianoRollNotes-module_PianoRollNotes__6pF-y","Note":"PianoRollNotes-module_Note__-jxLb","trimStart":"PianoRollNotes-module_trimStart__vuBlj","trimEnd":"PianoRollNotes-module_trimEnd__zPdjr"};
141
+ styleInject(css_248z$2);
174
142
 
175
- const _tmpl$$5 = /*#__PURE__*/web.template(`<div></div>`, 2);
143
+ const _tmpl$$6 = /*#__PURE__*/web.template(`<div></div>`, 2);
176
144
  const PianoRollNotes = props => {
177
145
  const context = usePianoRollContext();
178
146
  const verticalViewPort = solidJs.createMemo(() => useViewPortDimension("vertical"));
@@ -181,7 +149,7 @@ const PianoRollNotes = props => {
181
149
  const snapValueToGridIfEnabled = (value, altKey) => context.snapToGrid && !altKey ? Math.round(value / gridDivisionTicks()) * gridDivisionTicks() : value;
182
150
  const insertOrUpdateNote = event => {
183
151
  const position = horizontalViewPort().calculatePosition(event.clientX);
184
- const midi = 127 - Math.floor(verticalViewPort().calculatePosition(event.clientY));
152
+ const midi = context.condensed ? 60 : 127 - Math.floor(verticalViewPort().calculatePosition(event.clientY));
185
153
  const eventPositionTicks = Math.floor(position / gridDivisionTicks()) * gridDivisionTicks();
186
154
  const velocity = 127;
187
155
  const existingNote = newNote();
@@ -206,10 +174,10 @@ const PianoRollNotes = props => {
206
174
  const [isMouseDown, setIsMouseDown] = solidJs.createSignal(false);
207
175
  const newNote = solidJs.createMemo(() => context.notes[newNoteIndex()]);
208
176
  const getClasses = noteDragMode => {
209
- return noteDragMode ? [styles$1.Note, styles$1[noteDragMode]] : [styles$1.Note];
177
+ return noteDragMode ? [styles$2.Note, styles$2[noteDragMode]] : [styles$2.Note];
210
178
  };
211
179
  return (() => {
212
- const _el$ = _tmpl$$5.cloneNode(true);
180
+ const _el$ = _tmpl$$6.cloneNode(true);
213
181
  _el$.$$click = event => {
214
182
  if (newNote()) {
215
183
  setNewNoteIndex(-1);
@@ -233,9 +201,6 @@ const PianoRollNotes = props => {
233
201
  return;
234
202
  }
235
203
  const index = insertOrUpdateNote(event);
236
- console.log({
237
- index
238
- });
239
204
  setNewNoteIndex(index);
240
205
  };
241
206
  _el$.$$mousedown = () => {
@@ -249,14 +214,14 @@ const PianoRollNotes = props => {
249
214
  return context.notes;
250
215
  },
251
216
  children: (note, index) => {
252
- const verticalVirtualDimensionss = solidJs.createMemo(() => verticalViewPort().calculatePixelDimensions(127 - note().midi, 1));
217
+ const verticalVirtualDimensions = solidJs.createMemo(() => verticalViewPort().calculatePixelDimensions(127 - note().midi, 1));
253
218
  const horizontalDimensions = solidJs.createMemo(() => horizontalViewPort().calculatePixelDimensions(note().ticks, note().durationTicks));
254
219
  return web.createComponent(solidJs.Show, {
255
220
  get when() {
256
- return web.memo(() => !!!!verticalVirtualDimensionss().size)() && !!horizontalDimensions().size;
221
+ return web.memo(() => !!(verticalViewPort().isVisible(verticalVirtualDimensions()) || context.condensed))() && horizontalViewPort().isVisible(horizontalDimensions());
257
222
  },
258
223
  get children() {
259
- const _el$2 = _tmpl$$5.cloneNode(true);
224
+ const _el$2 = _tmpl$$6.cloneNode(true);
260
225
  _el$2.$$mousedown = event => {
261
226
  event.stopPropagation();
262
227
  setIsDragging(true);
@@ -266,7 +231,7 @@ const PianoRollNotes = props => {
266
231
  const ticks = snapValueToGridIfEnabled(Math.max(horizontalViewPort().calculatePosition(mouseMoveEvent.clientX) - diffPosition, 0), mouseMoveEvent.altKey);
267
232
  context.onNoteChange?.(index, {
268
233
  ...note(),
269
- ...(noteDragMode() === "move" && {
234
+ ...(noteDragMode() === "move" && !context.condensed && {
270
235
  midi: Math.round(127 - verticalViewPort().calculatePosition(mouseMoveEvent.clientY))
271
236
  }),
272
237
  ...((noteDragMode() === "move" || noteDragMode() === "trimStart") && {
@@ -302,38 +267,37 @@ const PianoRollNotes = props => {
302
267
  };
303
268
  web.effect(_p$ => {
304
269
  const _v$ = getClasses(noteDragMode()).join(" "),
305
- _v$2 = `rgba(255,0,0, ${(128 + note().velocity) / 256})`,
306
- _v$3 = `${verticalVirtualDimensionss().offset}px`,
307
- _v$4 = `${verticalVirtualDimensionss().size}px`,
308
- _v$5 = `${horizontalDimensions().offset}px`,
309
- _v$6 = `${horizontalDimensions().size}px`;
270
+ _v$2 = {
271
+ "background-color": `rgba(255,0,0, ${(128 + note().velocity) / 256})`,
272
+ ...(context.condensed ? {
273
+ top: 0,
274
+ height: "100%"
275
+ } : {
276
+ top: `${verticalVirtualDimensions().offset}px`,
277
+ height: `${verticalVirtualDimensions().size}px`
278
+ }),
279
+ left: `${horizontalDimensions().offset}px`,
280
+ width: `${horizontalDimensions().size}px`
281
+ };
310
282
  _v$ !== _p$._v$ && web.className(_el$2, _p$._v$ = _v$);
311
- _v$2 !== _p$._v$2 && _el$2.style.setProperty("background-color", _p$._v$2 = _v$2);
312
- _v$3 !== _p$._v$3 && _el$2.style.setProperty("top", _p$._v$3 = _v$3);
313
- _v$4 !== _p$._v$4 && _el$2.style.setProperty("height", _p$._v$4 = _v$4);
314
- _v$5 !== _p$._v$5 && _el$2.style.setProperty("left", _p$._v$5 = _v$5);
315
- _v$6 !== _p$._v$6 && _el$2.style.setProperty("width", _p$._v$6 = _v$6);
283
+ _p$._v$2 = web.style(_el$2, _v$2, _p$._v$2);
316
284
  return _p$;
317
285
  }, {
318
286
  _v$: undefined,
319
- _v$2: undefined,
320
- _v$3: undefined,
321
- _v$4: undefined,
322
- _v$5: undefined,
323
- _v$6: undefined
287
+ _v$2: undefined
324
288
  });
325
289
  return _el$2;
326
290
  }
327
291
  });
328
292
  }
329
293
  }));
330
- web.effect(() => web.className(_el$, styles$1.PianoRollNotes));
294
+ web.effect(() => web.className(_el$, styles$2.PianoRollNotes));
331
295
  return _el$;
332
296
  })();
333
297
  };
334
298
  web.delegateEvents(["mousedown", "mousemove", "mouseup", "dblclick", "click"]);
335
299
 
336
- const _tmpl$$4 = /*#__PURE__*/web.template(`<div class="PianoRoll-Scroller"><div><div><div></div></div></div></div>`, 8);
300
+ const _tmpl$$5 = /*#__PURE__*/web.template(`<div class="PianoRoll-Scroller"><div><div><div></div></div></div></div>`, 8);
337
301
  const ScrollContainer = props => {
338
302
  let scrollContentRef;
339
303
  const verticalViewPort = solidJs.createMemo(() => useViewPortDimension("vertical"));
@@ -395,7 +359,7 @@ const ScrollContainer = props => {
395
359
  });
396
360
  });
397
361
  return (() => {
398
- const _el$ = _tmpl$$4.cloneNode(true),
362
+ const _el$ = _tmpl$$5.cloneNode(true),
399
363
  _el$2 = _el$.firstChild,
400
364
  _el$3 = _el$2.firstChild,
401
365
  _el$4 = _el$3.firstChild;
@@ -436,6 +400,69 @@ const ScrollContainer = props => {
436
400
  })();
437
401
  };
438
402
 
403
+ var css_248z$1 = ".PianoRollKeys-module_PianoRollKeys__5vnQ0 {\n position: relative;\n height: 100%;\n width: 50px;\n}\n\n.PianoRollKeys-module_Key__jybNC {\n border-width: 0px;\n position: absolute;\n box-sizing: border-box;\n width: 100%;\n border-color: #000;\n border-style: solid;\n border-right-width: 1px;\n}\n\n.PianoRollKeys-module_black__7rncB {\n background: black;\n}\n\n.PianoRollKeys-module_white__fR2Lm {\n background: white;\n}\n\n.PianoRollKeys-module_whiteAndNextIsWhite__PN1O8 {\n border-top-width: 0.1px;\n}\n\n.PianoRollKeys-module_whiteAndPreviousIsWhite__-fP3q {\n border-bottom-width: 0.1px;\n}\n";
404
+ var styles$1 = {"PianoRollKeys":"PianoRollKeys-module_PianoRollKeys__5vnQ0","Key":"PianoRollKeys-module_Key__jybNC","black":"PianoRollKeys-module_black__7rncB","white":"PianoRollKeys-module_white__fR2Lm","whiteAndNextIsWhite":"PianoRollKeys-module_whiteAndNextIsWhite__PN1O8","whiteAndPreviousIsWhite":"PianoRollKeys-module_whiteAndPreviousIsWhite__-fP3q"};
405
+ styleInject(css_248z$1);
406
+
407
+ const _tmpl$$4 = /*#__PURE__*/web.template(`<div></div>`, 2);
408
+ const PianoRollKeys = () => {
409
+ const viewPort = solidJs.createMemo(() => useViewPortDimension("vertical"));
410
+ return (() => {
411
+ const _el$ = _tmpl$$4.cloneNode(true);
412
+ web.insert(_el$, web.createComponent(solidJs.Index, {
413
+ each: keys,
414
+ children: key => {
415
+ const virtualDimensions = solidJs.createMemo(() => viewPort().calculatePixelDimensions(127 - key().number, 1));
416
+ return web.createComponent(solidJs.Show, {
417
+ get when() {
418
+ return virtualDimensions().size > 0;
419
+ },
420
+ get children() {
421
+ const _el$2 = _tmpl$$4.cloneNode(true);
422
+ web.effect(_p$ => {
423
+ const _v$ = {
424
+ [styles$1["Key"]]: true,
425
+ [styles$1["black"]]: key().isBlack,
426
+ [styles$1["white"]]: !key().isBlack,
427
+ [styles$1["whiteAndNextIsWhite"]]: !key().isBlack && !blackKeys.includes((key().number + 1) % 12),
428
+ [styles$1["whiteAndPreviousIsWhite"]]: !key().isBlack && !blackKeys.includes((key().number - 1) % 12)
429
+ },
430
+ _v$2 = key().name,
431
+ _v$3 = key().number % 12,
432
+ _v$4 = `${virtualDimensions().offset}px`,
433
+ _v$5 = `${virtualDimensions().size}px`;
434
+ _p$._v$ = web.classList(_el$2, _v$, _p$._v$);
435
+ _v$2 !== _p$._v$2 && web.setAttribute(_el$2, "title", _p$._v$2 = _v$2);
436
+ _v$3 !== _p$._v$3 && web.setAttribute(_el$2, "data-index", _p$._v$3 = _v$3);
437
+ _v$4 !== _p$._v$4 && _el$2.style.setProperty("top", _p$._v$4 = _v$4);
438
+ _v$5 !== _p$._v$5 && _el$2.style.setProperty("height", _p$._v$5 = _v$5);
439
+ return _p$;
440
+ }, {
441
+ _v$: undefined,
442
+ _v$2: undefined,
443
+ _v$3: undefined,
444
+ _v$4: undefined,
445
+ _v$5: undefined
446
+ });
447
+ return _el$2;
448
+ }
449
+ });
450
+ }
451
+ }));
452
+ web.effect(() => web.className(_el$, styles$1.PianoRollKeys));
453
+ return _el$;
454
+ })();
455
+ };
456
+ const blackKeys = [1, 3, 6, 8, 10];
457
+ const keyNames = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
458
+ const keys = Array.from({
459
+ length: 128
460
+ }).map((_, index) => ({
461
+ number: index,
462
+ name: `${keyNames[index % 12]} ${Math.floor(index / 12) - 2}`,
463
+ isBlack: blackKeys.includes(index % 12)
464
+ }));
465
+
439
466
  var css_248z = ".PianoRollGrid-module_PianoRollGrid__tG119 {\n position: relative;\n width: 100%;\n height: 100%;\n}\n\n.PianoRollGrid-module_PianoRollGrid-Key__VRbiB {\n position: absolute;\n border-style: solid;\n border-color: gray;\n}\n\n.PianoRollGrid-module_PianoRollGrid-Time__jLz3E {\n position: absolute;\n box-sizing: border-box;\n top: 0px;\n height: 100%;\n border-left-style: solid;\n border-left-width: 0.5px;\n}\n";
440
467
  var styles = {"PianoRollGrid":"PianoRollGrid-module_PianoRollGrid__tG119","PianoRollGrid-Key":"PianoRollGrid-module_PianoRollGrid-Key__VRbiB","PianoRollGrid-Time":"PianoRollGrid-module_PianoRollGrid-Time__jLz3E"};
441
468
  styleInject(css_248z);
@@ -552,6 +579,30 @@ const PianoRollGrid = () => {
552
579
  })();
553
580
  };
554
581
 
582
+ const useNotes = () => {
583
+ const [notes, onNotesChange] = solidJs.createSignal([]);
584
+ const onNoteChange = (index, note) => {
585
+ onNotesChange([...notes().slice(0, index), note, ...notes().splice(index + 1)]);
586
+ };
587
+ const onInsertNote = note => {
588
+ const index = Math.max(notes().findIndex(({
589
+ ticks
590
+ }) => ticks > note.ticks), 0);
591
+ onNotesChange([...notes().slice(0, index), note, ...notes().splice(index)]);
592
+ return index;
593
+ };
594
+ const onRemoveNote = index => {
595
+ onNotesChange([...notes().slice(0, index), ...notes().splice(index + 1)]);
596
+ };
597
+ return {
598
+ notes,
599
+ onNotesChange,
600
+ onNoteChange,
601
+ onInsertNote,
602
+ onRemoveNote
603
+ };
604
+ };
605
+
555
606
  const defaultRect = {
556
607
  left: 0,
557
608
  width: 0,
@@ -608,29 +659,198 @@ const VerticalZoomControl = props => {
608
659
  })();
609
660
  };
610
661
 
611
- const _tmpl$$1 = /*#__PURE__*/web.template(`<input max="500" min="1" step="0.01">`, 1);
612
- const HorizontalZoomControl = props => {
613
- const context = usePianoRollContext();
614
- return (() => {
615
- const _el$ = _tmpl$$1.cloneNode(true);
616
- web.spread(_el$, web.mergeProps(props, {
617
- get value() {
618
- return context.zoom;
619
- },
620
- "onInput": event => context.onZoomChange?.(event.currentTarget.valueAsNumber),
621
- "type": "range",
622
- "style": {
623
- "margin-left": "50px",
624
- "margin-right": "16px"
625
- }
626
- }), false, false);
627
- return _el$;
628
- })();
662
+ const _tmpl$$1 = /*#__PURE__*/web.template(`<ul></ul>`, 2),
663
+ _tmpl$2 = /*#__PURE__*/web.template(`<div><ul></ul><div><div></div></div></div>`, 8),
664
+ _tmpl$3 = /*#__PURE__*/web.template(`<li></li>`, 2);
665
+ const MultiTrackPianoRoll = allProps => {
666
+ const condensed = solidJs.createMemo(() => !allProps.selectedTrack);
667
+ const [ownProps, restProps] = solidJs.splitProps(allProps, ["tracks", "selectedTrack"]);
668
+ const [contextProps, divProps] = splitContextProps(solidJs.mergeProps(restProps, {
669
+ notes: [],
670
+ condensed: false
671
+ }));
672
+ const [scrollerRef, setScrollerRef] = solidJs.createSignal();
673
+ const clientRect = useBoundingClientRect(scrollerRef);
674
+ const zoomFactor = 500;
675
+ const minZoom = solidJs.createMemo(() => 1 / (zoomFactor / clientRect().width));
676
+ const maxZoom = solidJs.createMemo(() => 500 * (zoomFactor / clientRect().width));
677
+ const minVerticalZoom = solidJs.createMemo(() => 1 / (zoomFactor / clientRect().height));
678
+ const maxVerticalZoom = solidJs.createMemo(() => 10 * (zoomFactor / clientRect().height));
679
+ return web.createComponent(PianoRollContextProvider, {
680
+ get value() {
681
+ return {
682
+ ...contextProps
683
+ };
684
+ },
685
+ get children() {
686
+ return web.createComponent(ScrollZoomViewPort, {
687
+ dimensions: {
688
+ horizontal: () => ({
689
+ pixelOffset: clientRect().left,
690
+ pixelSize: clientRect().width,
691
+ position: contextProps.position,
692
+ range: contextProps.duration,
693
+ zoom: contextProps.zoom * (zoomFactor / clientRect().width),
694
+ onPositionChange: contextProps.onPositionChange,
695
+ onZoomChange: zoom => contextProps.onZoomChange?.(clamp(zoom / (zoomFactor / clientRect().width), minZoom(), maxZoom()))
696
+ }),
697
+ vertical: () => ({
698
+ pixelOffset: clientRect().top,
699
+ pixelSize: clientRect().height,
700
+ position: contextProps.verticalPosition,
701
+ range: 128,
702
+ zoom: contextProps.verticalZoom * (zoomFactor / clientRect().height),
703
+ onPositionChange: contextProps.onVerticalPositionChange,
704
+ onZoomChange: verticalZoom => contextProps.onVerticalZoomChange?.(clamp(verticalZoom / (zoomFactor / clientRect().height), minVerticalZoom(), maxVerticalZoom()))
705
+ })
706
+ },
707
+ get children() {
708
+ const _el$ = _tmpl$2.cloneNode(true),
709
+ _el$2 = _el$.firstChild,
710
+ _el$3 = _el$2.nextSibling,
711
+ _el$4 = _el$3.firstChild;
712
+ _el$.style.setProperty("display", "flex");
713
+ _el$.style.setProperty("flex", "1");
714
+ _el$.style.setProperty("height", "100%");
715
+ _el$.style.setProperty("flex-direction", "row");
716
+ _el$2.style.setProperty("margin-block-start", "0");
717
+ _el$2.style.setProperty("padding-inline-start", "0");
718
+ _el$2.style.setProperty("width", "150px");
719
+ web.insert(_el$2, web.createComponent(solidJs.Index, {
720
+ get each() {
721
+ return allProps.tracks;
722
+ },
723
+ children: track => (() => {
724
+ const _el$6 = _tmpl$3.cloneNode(true);
725
+ _el$6.$$click = () => {
726
+ if (track() === allProps.selectedTrack) {
727
+ allProps.onSelectedTrackChange(undefined);
728
+ } else {
729
+ allProps.onSelectedTrackChange(track());
730
+ }
731
+ };
732
+ _el$6.style.setProperty("width", "150px");
733
+ _el$6.style.setProperty("height", "30px");
734
+ _el$6.style.setProperty("list-style", "none");
735
+ _el$6.style.setProperty("display", "flex");
736
+ _el$6.style.setProperty("align-items", "center");
737
+ _el$6.style.setProperty("border-top", "1px black solid");
738
+ _el$6.style.setProperty("cursor", "pointer");
739
+ web.insert(_el$6, () => track().name);
740
+ web.effect(() => _el$6.style.setProperty("background", track() === allProps.selectedTrack ? "lightgray" : "none"));
741
+ return _el$6;
742
+ })()
743
+ }));
744
+ _el$3.style.setProperty("flex", "1");
745
+ web.insert(_el$4, web.createComponent(solidJs.Show, {
746
+ get when() {
747
+ return !condensed();
748
+ },
749
+ get children() {
750
+ return web.createComponent(PianoRollKeys, {});
751
+ }
752
+ }), null);
753
+ web.insert(_el$4, web.createComponent(ScrollContainer, {
754
+ ref: setScrollerRef,
755
+ get children() {
756
+ const _el$5 = _tmpl$$1.cloneNode(true);
757
+ _el$5.style.setProperty("margin", "0");
758
+ _el$5.style.setProperty("margin-block-start", "0");
759
+ _el$5.style.setProperty("padding-inline-start", "0");
760
+ web.insert(_el$5, web.createComponent(solidJs.Index, {
761
+ get each() {
762
+ return allProps.tracks;
763
+ },
764
+ children: track => {
765
+ const notes = useNotes();
766
+ solidJs.createEffect(() => {
767
+ notes.onNotesChange(track().notes);
768
+ });
769
+ const [context, setContext] = store.createStore({
770
+ ...contextProps
771
+ });
772
+ solidJs.createEffect(() => {
773
+ setContext({
774
+ ...contextProps,
775
+ condensed: condensed(),
776
+ notes: notes.notes(),
777
+ onNoteChange: notes.onNoteChange,
778
+ onInsertNote: notes.onInsertNote,
779
+ onRemoveNote: notes.onRemoveNote
780
+ });
781
+ });
782
+ const verticalViewPort = useViewPortDimension("vertical");
783
+ return web.createComponent(solidJs.Show, {
784
+ get when() {
785
+ return condensed() || allProps.selectedTrack === track();
786
+ },
787
+ get children() {
788
+ return web.createComponent(PianoRollContextProvider, {
789
+ value: context,
790
+ get children() {
791
+ const _el$7 = _tmpl$3.cloneNode(true);
792
+ _el$7.style.setProperty("display", "flex");
793
+ _el$7.style.setProperty("position", "relative");
794
+ _el$7.style.setProperty("list-style", "none");
795
+ _el$7.style.setProperty("flex-direction", "row");
796
+ _el$7.style.setProperty("border-top", "1px black solid");
797
+ web.insert(_el$7, web.createComponent(PianoRollNotes, {}), null);
798
+ web.insert(_el$7, web.createComponent(PianoRollGrid, {}), null);
799
+ web.effect(() => _el$7.style.setProperty("height", condensed() ? "30px" : `${verticalViewPort.pixelSize}px`));
800
+ return _el$7;
801
+ }
802
+ });
803
+ }
804
+ });
805
+ }
806
+ }));
807
+ return _el$5;
808
+ }
809
+ }), null);
810
+ web.insert(_el$4, web.createComponent(solidJs.Show, {
811
+ get when() {
812
+ return !condensed();
813
+ },
814
+ get children() {
815
+ return web.createComponent(VerticalZoomControl, {
816
+ get value() {
817
+ return contextProps.verticalZoom;
818
+ },
819
+ onInput: event => contextProps.onVerticalZoomChange?.(event.currentTarget.valueAsNumber)
820
+ });
821
+ }
822
+ }), null);
823
+ web.insert(_el$3, web.createComponent(HorizontalZoomControl, {
824
+ style: {
825
+ width: "100%",
826
+ "margin-left": 0
827
+ },
828
+ get value() {
829
+ return contextProps.zoom;
830
+ },
831
+ onInput: event => contextProps.onZoomChange?.(event.currentTarget.valueAsNumber)
832
+ }), null);
833
+ web.effect(_p$ => {
834
+ const _v$ = styles$3.PianoRoll,
835
+ _v$2 = styles$3.PianoRollContainer;
836
+ _v$ !== _p$._v$ && web.className(_el$3, _p$._v$ = _v$);
837
+ _v$2 !== _p$._v$2 && web.className(_el$4, _p$._v$2 = _v$2);
838
+ return _p$;
839
+ }, {
840
+ _v$: undefined,
841
+ _v$2: undefined
842
+ });
843
+ return _el$;
844
+ }
845
+ });
846
+ }
847
+ });
629
848
  };
849
+ web.delegateEvents(["click"]);
630
850
 
631
851
  const _tmpl$ = /*#__PURE__*/web.template(`<div><div></div></div>`, 4);
632
852
  const PianoRoll = allProps => {
633
- const [contextProps, divProps] = solidJs.splitProps(allProps, ["ppq", "notes", "position", "duration", "zoom", "verticalPosition", "verticalZoom", "onVerticalZoomChange", "onVerticalPositionChange", "onZoomChange", "onPositionChange", "onNoteChange", "gridDivision", "snapToGrid", "onInsertNote", "onRemoveNote"]);
853
+ const [contextProps, divProps] = splitContextProps(allProps);
634
854
  const [scrollerRef, setScrollerRef] = solidJs.createSignal();
635
855
  const clientRect = useBoundingClientRect(scrollerRef);
636
856
  const zoomFactor = 500;
@@ -701,33 +921,14 @@ const PianoRoll = allProps => {
701
921
 
702
922
  const usePianoRoll = () => {
703
923
  const [ppq, onPpqChange] = solidJs.createSignal(120);
924
+ const [condensed, onCondensedChange] = solidJs.createSignal(false);
704
925
  const [position, onPositionChange] = solidJs.createSignal(0);
705
926
  const [zoom, onZoomChange] = solidJs.createSignal(10);
706
927
  const [verticalZoom, onVerticalZoomChange] = solidJs.createSignal(5);
707
928
  const [verticalPosition, onVerticalPositionChange] = solidJs.createSignal(64);
708
929
  const [gridDivision, onGridDivisionChange] = solidJs.createSignal(16);
709
930
  const [snapToGrid, onSnapToGridChange] = solidJs.createSignal(true);
710
- const [notes, onNotesChange] = solidJs.createSignal([]);
711
931
  const [duration, onDurationChange] = solidJs.createSignal(0);
712
- const onNoteChange = (index, note) => {
713
- onNotesChange([...notes().slice(0, index), note, ...notes().splice(index + 1)]);
714
- };
715
- const onInsertNote = note => {
716
- const index = Math.max(notes().findIndex(({
717
- ticks
718
- }) => ticks > note.ticks), 0);
719
- onNotesChange([...notes().slice(0, index), note, ...notes().splice(index)]);
720
- return index;
721
- };
722
- const onRemoveNote = index => {
723
- onNotesChange([...notes().slice(0, index), ...notes().splice(index + 1)]);
724
- };
725
- solidJs.createEffect(() => {
726
- const minDuration = Math.max((notes()[notes().length - 1]?.ticks ?? 0) + (notes()[notes().length - 1]?.durationTicks ?? 0), ppq() * 4 * 4);
727
- if (duration() < minDuration) {
728
- onDurationChange(minDuration);
729
- }
730
- });
731
932
  return {
732
933
  ppq,
733
934
  onPpqChange,
@@ -743,16 +944,15 @@ const usePianoRoll = () => {
743
944
  onGridDivisionChange,
744
945
  snapToGrid,
745
946
  onSnapToGridChange,
746
- notes,
747
- onNotesChange,
748
- onNoteChange,
749
- onInsertNote,
750
- onRemoveNote,
947
+ condensed,
948
+ onCondensedChange,
751
949
  duration,
752
950
  onDurationChange
753
951
  };
754
952
  };
755
953
 
954
+ exports.MultiTrackPianoRoll = MultiTrackPianoRoll;
756
955
  exports.PianoRoll = PianoRoll;
956
+ exports.useNotes = useNotes;
757
957
  exports.usePianoRoll = usePianoRoll;
758
958
  //# sourceMappingURL=index.js.map