solid-pianoroll 0.0.11 → 0.0.13

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,14 +201,13 @@ 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
- _el$.$$mousedown = () => {
206
+ _el$.$$mousedown = event => {
242
207
  console.log("down");
243
208
  setIsMouseDown(true);
209
+ const index = insertOrUpdateNote(event);
210
+ setNewNoteIndex(index);
244
211
  };
245
212
  const _ref$ = props.ref;
246
213
  typeof _ref$ === "function" ? web.use(_ref$, _el$) : props.ref = _el$;
@@ -249,14 +216,14 @@ const PianoRollNotes = props => {
249
216
  return context.notes;
250
217
  },
251
218
  children: (note, index) => {
252
- const verticalVirtualDimensionss = solidJs.createMemo(() => verticalViewPort().calculatePixelDimensions(127 - note().midi, 1));
219
+ const verticalVirtualDimensions = solidJs.createMemo(() => verticalViewPort().calculatePixelDimensions(127 - note().midi, 1));
253
220
  const horizontalDimensions = solidJs.createMemo(() => horizontalViewPort().calculatePixelDimensions(note().ticks, note().durationTicks));
254
221
  return web.createComponent(solidJs.Show, {
255
222
  get when() {
256
- return web.memo(() => !!!!verticalVirtualDimensionss().size)() && !!horizontalDimensions().size;
223
+ return web.memo(() => !!(verticalViewPort().isVisible(verticalVirtualDimensions()) || context.condensed))() && horizontalViewPort().isVisible(horizontalDimensions());
257
224
  },
258
225
  get children() {
259
- const _el$2 = _tmpl$$5.cloneNode(true);
226
+ const _el$2 = _tmpl$$6.cloneNode(true);
260
227
  _el$2.$$mousedown = event => {
261
228
  event.stopPropagation();
262
229
  setIsDragging(true);
@@ -266,7 +233,7 @@ const PianoRollNotes = props => {
266
233
  const ticks = snapValueToGridIfEnabled(Math.max(horizontalViewPort().calculatePosition(mouseMoveEvent.clientX) - diffPosition, 0), mouseMoveEvent.altKey);
267
234
  context.onNoteChange?.(index, {
268
235
  ...note(),
269
- ...(noteDragMode() === "move" && {
236
+ ...(noteDragMode() === "move" && !context.condensed && {
270
237
  midi: Math.round(127 - verticalViewPort().calculatePosition(mouseMoveEvent.clientY))
271
238
  }),
272
239
  ...((noteDragMode() === "move" || noteDragMode() === "trimStart") && {
@@ -302,38 +269,37 @@ const PianoRollNotes = props => {
302
269
  };
303
270
  web.effect(_p$ => {
304
271
  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`;
272
+ _v$2 = {
273
+ "background-color": `rgba(255,0,0, ${(128 + note().velocity) / 256})`,
274
+ ...(context.condensed ? {
275
+ top: 0,
276
+ height: "100%"
277
+ } : {
278
+ top: `${verticalVirtualDimensions().offset}px`,
279
+ height: `${verticalVirtualDimensions().size}px`
280
+ }),
281
+ left: `${horizontalDimensions().offset}px`,
282
+ width: `${horizontalDimensions().size}px`
283
+ };
310
284
  _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);
285
+ _p$._v$2 = web.style(_el$2, _v$2, _p$._v$2);
316
286
  return _p$;
317
287
  }, {
318
288
  _v$: undefined,
319
- _v$2: undefined,
320
- _v$3: undefined,
321
- _v$4: undefined,
322
- _v$5: undefined,
323
- _v$6: undefined
289
+ _v$2: undefined
324
290
  });
325
291
  return _el$2;
326
292
  }
327
293
  });
328
294
  }
329
295
  }));
330
- web.effect(() => web.className(_el$, styles$1.PianoRollNotes));
296
+ web.effect(() => web.className(_el$, styles$2.PianoRollNotes));
331
297
  return _el$;
332
298
  })();
333
299
  };
334
300
  web.delegateEvents(["mousedown", "mousemove", "mouseup", "dblclick", "click"]);
335
301
 
336
- const _tmpl$$4 = /*#__PURE__*/web.template(`<div class="PianoRoll-Scroller"><div><div><div></div></div></div></div>`, 8);
302
+ const _tmpl$$5 = /*#__PURE__*/web.template(`<div class="PianoRoll-Scroller"><div><div><div></div></div></div></div>`, 8);
337
303
  const ScrollContainer = props => {
338
304
  let scrollContentRef;
339
305
  const verticalViewPort = solidJs.createMemo(() => useViewPortDimension("vertical"));
@@ -395,7 +361,7 @@ const ScrollContainer = props => {
395
361
  });
396
362
  });
397
363
  return (() => {
398
- const _el$ = _tmpl$$4.cloneNode(true),
364
+ const _el$ = _tmpl$$5.cloneNode(true),
399
365
  _el$2 = _el$.firstChild,
400
366
  _el$3 = _el$2.firstChild,
401
367
  _el$4 = _el$3.firstChild;
@@ -436,6 +402,69 @@ const ScrollContainer = props => {
436
402
  })();
437
403
  };
438
404
 
405
+ 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";
406
+ 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"};
407
+ styleInject(css_248z$1);
408
+
409
+ const _tmpl$$4 = /*#__PURE__*/web.template(`<div></div>`, 2);
410
+ const PianoRollKeys = () => {
411
+ const viewPort = solidJs.createMemo(() => useViewPortDimension("vertical"));
412
+ return (() => {
413
+ const _el$ = _tmpl$$4.cloneNode(true);
414
+ web.insert(_el$, web.createComponent(solidJs.Index, {
415
+ each: keys,
416
+ children: key => {
417
+ const virtualDimensions = solidJs.createMemo(() => viewPort().calculatePixelDimensions(127 - key().number, 1));
418
+ return web.createComponent(solidJs.Show, {
419
+ get when() {
420
+ return virtualDimensions().size > 0;
421
+ },
422
+ get children() {
423
+ const _el$2 = _tmpl$$4.cloneNode(true);
424
+ web.effect(_p$ => {
425
+ const _v$ = {
426
+ [styles$1["Key"]]: true,
427
+ [styles$1["black"]]: key().isBlack,
428
+ [styles$1["white"]]: !key().isBlack,
429
+ [styles$1["whiteAndNextIsWhite"]]: !key().isBlack && !blackKeys.includes((key().number + 1) % 12),
430
+ [styles$1["whiteAndPreviousIsWhite"]]: !key().isBlack && !blackKeys.includes((key().number - 1) % 12)
431
+ },
432
+ _v$2 = key().name,
433
+ _v$3 = key().number % 12,
434
+ _v$4 = `${virtualDimensions().offset}px`,
435
+ _v$5 = `${virtualDimensions().size}px`;
436
+ _p$._v$ = web.classList(_el$2, _v$, _p$._v$);
437
+ _v$2 !== _p$._v$2 && web.setAttribute(_el$2, "title", _p$._v$2 = _v$2);
438
+ _v$3 !== _p$._v$3 && web.setAttribute(_el$2, "data-index", _p$._v$3 = _v$3);
439
+ _v$4 !== _p$._v$4 && _el$2.style.setProperty("top", _p$._v$4 = _v$4);
440
+ _v$5 !== _p$._v$5 && _el$2.style.setProperty("height", _p$._v$5 = _v$5);
441
+ return _p$;
442
+ }, {
443
+ _v$: undefined,
444
+ _v$2: undefined,
445
+ _v$3: undefined,
446
+ _v$4: undefined,
447
+ _v$5: undefined
448
+ });
449
+ return _el$2;
450
+ }
451
+ });
452
+ }
453
+ }));
454
+ web.effect(() => web.className(_el$, styles$1.PianoRollKeys));
455
+ return _el$;
456
+ })();
457
+ };
458
+ const blackKeys = [1, 3, 6, 8, 10];
459
+ const keyNames = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
460
+ const keys = Array.from({
461
+ length: 128
462
+ }).map((_, index) => ({
463
+ number: index,
464
+ name: `${keyNames[index % 12]} ${Math.floor(index / 12) - 2}`,
465
+ isBlack: blackKeys.includes(index % 12)
466
+ }));
467
+
439
468
  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
469
  var styles = {"PianoRollGrid":"PianoRollGrid-module_PianoRollGrid__tG119","PianoRollGrid-Key":"PianoRollGrid-module_PianoRollGrid-Key__VRbiB","PianoRollGrid-Time":"PianoRollGrid-module_PianoRollGrid-Time__jLz3E"};
441
470
  styleInject(css_248z);
@@ -552,6 +581,30 @@ const PianoRollGrid = () => {
552
581
  })();
553
582
  };
554
583
 
584
+ const useNotes = () => {
585
+ const [notes, onNotesChange] = solidJs.createSignal([]);
586
+ const onNoteChange = (index, note) => {
587
+ onNotesChange([...notes().slice(0, index), note, ...notes().splice(index + 1)]);
588
+ };
589
+ const onInsertNote = note => {
590
+ const index = Math.max(notes().findIndex(({
591
+ ticks
592
+ }) => ticks > note.ticks), 0);
593
+ onNotesChange([...notes().slice(0, index), note, ...notes().splice(index)]);
594
+ return index;
595
+ };
596
+ const onRemoveNote = index => {
597
+ onNotesChange([...notes().slice(0, index), ...notes().splice(index + 1)]);
598
+ };
599
+ return {
600
+ notes,
601
+ onNotesChange,
602
+ onNoteChange,
603
+ onInsertNote,
604
+ onRemoveNote
605
+ };
606
+ };
607
+
555
608
  const defaultRect = {
556
609
  left: 0,
557
610
  width: 0,
@@ -608,29 +661,198 @@ const VerticalZoomControl = props => {
608
661
  })();
609
662
  };
610
663
 
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
- })();
664
+ const _tmpl$$1 = /*#__PURE__*/web.template(`<ul></ul>`, 2),
665
+ _tmpl$2 = /*#__PURE__*/web.template(`<div><ul></ul><div><div></div></div></div>`, 8),
666
+ _tmpl$3 = /*#__PURE__*/web.template(`<li></li>`, 2);
667
+ const MultiTrackPianoRoll = allProps => {
668
+ const condensed = solidJs.createMemo(() => !allProps.selectedTrack);
669
+ const [ownProps, restProps] = solidJs.splitProps(allProps, ["tracks", "selectedTrack"]);
670
+ const [contextProps, divProps] = splitContextProps(solidJs.mergeProps(restProps, {
671
+ notes: [],
672
+ condensed: false
673
+ }));
674
+ const [scrollerRef, setScrollerRef] = solidJs.createSignal();
675
+ const clientRect = useBoundingClientRect(scrollerRef);
676
+ const zoomFactor = 500;
677
+ const minZoom = solidJs.createMemo(() => 1 / (zoomFactor / clientRect().width));
678
+ const maxZoom = solidJs.createMemo(() => 500 * (zoomFactor / clientRect().width));
679
+ const minVerticalZoom = solidJs.createMemo(() => 1 / (zoomFactor / clientRect().height));
680
+ const maxVerticalZoom = solidJs.createMemo(() => 10 * (zoomFactor / clientRect().height));
681
+ return web.createComponent(PianoRollContextProvider, {
682
+ get value() {
683
+ return {
684
+ ...contextProps
685
+ };
686
+ },
687
+ get children() {
688
+ return web.createComponent(ScrollZoomViewPort, {
689
+ dimensions: {
690
+ horizontal: () => ({
691
+ pixelOffset: clientRect().left,
692
+ pixelSize: clientRect().width,
693
+ position: contextProps.position,
694
+ range: contextProps.duration,
695
+ zoom: contextProps.zoom * (zoomFactor / clientRect().width),
696
+ onPositionChange: contextProps.onPositionChange,
697
+ onZoomChange: zoom => contextProps.onZoomChange?.(clamp(zoom / (zoomFactor / clientRect().width), minZoom(), maxZoom()))
698
+ }),
699
+ vertical: () => ({
700
+ pixelOffset: clientRect().top,
701
+ pixelSize: clientRect().height,
702
+ position: contextProps.verticalPosition,
703
+ range: 128,
704
+ zoom: contextProps.verticalZoom * (zoomFactor / clientRect().height),
705
+ onPositionChange: contextProps.onVerticalPositionChange,
706
+ onZoomChange: verticalZoom => contextProps.onVerticalZoomChange?.(clamp(verticalZoom / (zoomFactor / clientRect().height), minVerticalZoom(), maxVerticalZoom()))
707
+ })
708
+ },
709
+ get children() {
710
+ const _el$ = _tmpl$2.cloneNode(true),
711
+ _el$2 = _el$.firstChild,
712
+ _el$3 = _el$2.nextSibling,
713
+ _el$4 = _el$3.firstChild;
714
+ _el$.style.setProperty("display", "flex");
715
+ _el$.style.setProperty("flex", "1");
716
+ _el$.style.setProperty("height", "100%");
717
+ _el$.style.setProperty("flex-direction", "row");
718
+ _el$2.style.setProperty("margin-block-start", "0");
719
+ _el$2.style.setProperty("padding-inline-start", "0");
720
+ _el$2.style.setProperty("width", "150px");
721
+ web.insert(_el$2, web.createComponent(solidJs.Index, {
722
+ get each() {
723
+ return allProps.tracks;
724
+ },
725
+ children: track => (() => {
726
+ const _el$6 = _tmpl$3.cloneNode(true);
727
+ _el$6.$$click = () => {
728
+ if (track() === allProps.selectedTrack) {
729
+ allProps.onSelectedTrackChange(undefined);
730
+ } else {
731
+ allProps.onSelectedTrackChange(track());
732
+ }
733
+ };
734
+ _el$6.style.setProperty("width", "150px");
735
+ _el$6.style.setProperty("height", "30px");
736
+ _el$6.style.setProperty("list-style", "none");
737
+ _el$6.style.setProperty("display", "flex");
738
+ _el$6.style.setProperty("align-items", "center");
739
+ _el$6.style.setProperty("border-top", "1px black solid");
740
+ _el$6.style.setProperty("cursor", "pointer");
741
+ web.insert(_el$6, () => track().name);
742
+ web.effect(() => _el$6.style.setProperty("background", track() === allProps.selectedTrack ? "lightgray" : "none"));
743
+ return _el$6;
744
+ })()
745
+ }));
746
+ _el$3.style.setProperty("flex", "1");
747
+ web.insert(_el$4, web.createComponent(solidJs.Show, {
748
+ get when() {
749
+ return !condensed();
750
+ },
751
+ get children() {
752
+ return web.createComponent(PianoRollKeys, {});
753
+ }
754
+ }), null);
755
+ web.insert(_el$4, web.createComponent(ScrollContainer, {
756
+ ref: setScrollerRef,
757
+ get children() {
758
+ const _el$5 = _tmpl$$1.cloneNode(true);
759
+ _el$5.style.setProperty("margin", "0");
760
+ _el$5.style.setProperty("margin-block-start", "0");
761
+ _el$5.style.setProperty("padding-inline-start", "0");
762
+ web.insert(_el$5, web.createComponent(solidJs.Index, {
763
+ get each() {
764
+ return allProps.tracks;
765
+ },
766
+ children: track => {
767
+ const notes = useNotes();
768
+ solidJs.createEffect(() => {
769
+ notes.onNotesChange(track().notes);
770
+ });
771
+ const [context, setContext] = store.createStore({
772
+ ...contextProps
773
+ });
774
+ solidJs.createEffect(() => {
775
+ setContext({
776
+ ...contextProps,
777
+ condensed: condensed(),
778
+ notes: notes.notes(),
779
+ onNoteChange: notes.onNoteChange,
780
+ onInsertNote: notes.onInsertNote,
781
+ onRemoveNote: notes.onRemoveNote
782
+ });
783
+ });
784
+ const verticalViewPort = useViewPortDimension("vertical");
785
+ return web.createComponent(solidJs.Show, {
786
+ get when() {
787
+ return condensed() || allProps.selectedTrack === track();
788
+ },
789
+ get children() {
790
+ return web.createComponent(PianoRollContextProvider, {
791
+ value: context,
792
+ get children() {
793
+ const _el$7 = _tmpl$3.cloneNode(true);
794
+ _el$7.style.setProperty("display", "flex");
795
+ _el$7.style.setProperty("position", "relative");
796
+ _el$7.style.setProperty("list-style", "none");
797
+ _el$7.style.setProperty("flex-direction", "row");
798
+ _el$7.style.setProperty("border-top", "1px black solid");
799
+ web.insert(_el$7, web.createComponent(PianoRollNotes, {}), null);
800
+ web.insert(_el$7, web.createComponent(PianoRollGrid, {}), null);
801
+ web.effect(() => _el$7.style.setProperty("height", condensed() ? "30px" : `${verticalViewPort.pixelSize}px`));
802
+ return _el$7;
803
+ }
804
+ });
805
+ }
806
+ });
807
+ }
808
+ }));
809
+ return _el$5;
810
+ }
811
+ }), null);
812
+ web.insert(_el$4, web.createComponent(solidJs.Show, {
813
+ get when() {
814
+ return !condensed();
815
+ },
816
+ get children() {
817
+ return web.createComponent(VerticalZoomControl, {
818
+ get value() {
819
+ return contextProps.verticalZoom;
820
+ },
821
+ onInput: event => contextProps.onVerticalZoomChange?.(event.currentTarget.valueAsNumber)
822
+ });
823
+ }
824
+ }), null);
825
+ web.insert(_el$3, web.createComponent(HorizontalZoomControl, {
826
+ style: {
827
+ width: "100%",
828
+ "margin-left": 0
829
+ },
830
+ get value() {
831
+ return contextProps.zoom;
832
+ },
833
+ onInput: event => contextProps.onZoomChange?.(event.currentTarget.valueAsNumber)
834
+ }), null);
835
+ web.effect(_p$ => {
836
+ const _v$ = styles$3.PianoRoll,
837
+ _v$2 = styles$3.PianoRollContainer;
838
+ _v$ !== _p$._v$ && web.className(_el$3, _p$._v$ = _v$);
839
+ _v$2 !== _p$._v$2 && web.className(_el$4, _p$._v$2 = _v$2);
840
+ return _p$;
841
+ }, {
842
+ _v$: undefined,
843
+ _v$2: undefined
844
+ });
845
+ return _el$;
846
+ }
847
+ });
848
+ }
849
+ });
629
850
  };
851
+ web.delegateEvents(["click"]);
630
852
 
631
853
  const _tmpl$ = /*#__PURE__*/web.template(`<div><div></div></div>`, 4);
632
854
  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"]);
855
+ const [contextProps, divProps] = splitContextProps(allProps);
634
856
  const [scrollerRef, setScrollerRef] = solidJs.createSignal();
635
857
  const clientRect = useBoundingClientRect(scrollerRef);
636
858
  const zoomFactor = 500;
@@ -701,33 +923,14 @@ const PianoRoll = allProps => {
701
923
 
702
924
  const usePianoRoll = () => {
703
925
  const [ppq, onPpqChange] = solidJs.createSignal(120);
926
+ const [condensed, onCondensedChange] = solidJs.createSignal(false);
704
927
  const [position, onPositionChange] = solidJs.createSignal(0);
705
928
  const [zoom, onZoomChange] = solidJs.createSignal(10);
706
929
  const [verticalZoom, onVerticalZoomChange] = solidJs.createSignal(5);
707
930
  const [verticalPosition, onVerticalPositionChange] = solidJs.createSignal(64);
708
- const [gridDivision, onGridDivisionChange] = solidJs.createSignal(16);
931
+ const [gridDivision, onGridDivisionChange] = solidJs.createSignal(4);
709
932
  const [snapToGrid, onSnapToGridChange] = solidJs.createSignal(true);
710
- const [notes, onNotesChange] = solidJs.createSignal([]);
711
933
  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
934
  return {
732
935
  ppq,
733
936
  onPpqChange,
@@ -743,16 +946,15 @@ const usePianoRoll = () => {
743
946
  onGridDivisionChange,
744
947
  snapToGrid,
745
948
  onSnapToGridChange,
746
- notes,
747
- onNotesChange,
748
- onNoteChange,
749
- onInsertNote,
750
- onRemoveNote,
949
+ condensed,
950
+ onCondensedChange,
751
951
  duration,
752
952
  onDurationChange
753
953
  };
754
954
  };
755
955
 
956
+ exports.MultiTrackPianoRoll = MultiTrackPianoRoll;
756
957
  exports.PianoRoll = PianoRoll;
958
+ exports.useNotes = useNotes;
757
959
  exports.usePianoRoll = usePianoRoll;
758
960
  //# sourceMappingURL=index.js.map