@tremolo-ui/react 0.2.1 → 0.3.0

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/index.cjs CHANGED
@@ -28,6 +28,7 @@ react = __toESM(react);
28
28
  let react_jsx_runtime = require("react/jsx-runtime");
29
29
  let _tremolo_ui_functions = require("@tremolo-ui/functions");
30
30
  let zustand = require("zustand");
31
+ let _tremolo_ui_dom = require("@tremolo-ui/dom");
31
32
  //#region src/components/AnimationCanvas/canvas.ts
32
33
  const drawingState = [
33
34
  "strokeStyle",
@@ -2295,78 +2296,72 @@ function useAnimationFrame(callback = () => {}, deps = []) {
2295
2296
  }
2296
2297
  //#endregion
2297
2298
  //#region src/hooks/useMIDIAccess.ts
2298
- /** @private */
2299
- const PERMISSION_DENIED = "PERMISSION_DENIED";
2300
- /** @private */
2301
- const NOT_SUPPORTED = "NOT_SUPPORTED";
2302
2299
  /**
2303
2300
  * Hooks for requesting MIDI access in the browser. The first argument allows you to choose whether to request access on mount.
2304
2301
  */
2305
2302
  function useMIDIAccess(requestOnMount = true) {
2306
- const [midiAccess, setMidiAccess] = (0, react.useState)(null);
2307
- const [error, setError] = (0, react.useState)(null);
2308
- const request = (0, react.useCallback)(() => {
2309
- if (navigator.requestMIDIAccess) navigator.requestMIDIAccess().then((access) => {
2310
- setMidiAccess(access);
2311
- setError(null);
2312
- }).catch(() => {
2313
- setError(PERMISSION_DENIED);
2314
- });
2315
- else setError(NOT_SUPPORTED);
2316
- }, []);
2303
+ const instance = (0, react.useMemo)(() => (0, _tremolo_ui_dom.createMIDIAccess)(), []);
2304
+ const { midiAccess, error } = (0, react.useSyncExternalStore)(instance.subscribe, instance.getState, instance.getServerState);
2305
+ (0, react.useEffect)(() => {
2306
+ if (requestOnMount) instance.request();
2307
+ }, [instance, requestOnMount]);
2317
2308
  (0, react.useEffect)(() => {
2318
- if (requestOnMount) request();
2319
- }, [requestOnMount, request]);
2309
+ return () => instance.destroy();
2310
+ }, [instance]);
2320
2311
  return {
2321
- request,
2312
+ request: instance.request,
2322
2313
  midiAccess,
2323
2314
  error
2324
2315
  };
2325
2316
  }
2326
2317
  //#endregion
2327
- //#region src/hooks/useMIDIMessage.ts
2328
- /**
2329
- * Hooks for when you want to process MIDI events in more detail than useMIDIInput.
2330
- */
2331
- function useMIDIMessage(midiAccess, onMIDIMessage) {
2332
- (0, react.useEffect)(() => {
2333
- if (!midiAccess) return;
2334
- for (const input of midiAccess.inputs.values()) input.addEventListener("midimessage", onMIDIMessage);
2335
- return () => {
2336
- for (const input of midiAccess.inputs.values()) input.removeEventListener("midimessage", onMIDIMessage);
2337
- };
2338
- }, [midiAccess, onMIDIMessage]);
2339
- }
2340
- //#endregion
2341
2318
  //#region src/hooks/useMIDIInput.ts
2342
- const MIDI_EVENT_TO_NUMBER = {
2343
- NOTE_ON: 144,
2344
- NOTE_OFF: 128,
2345
- PITCH_BEND: 224
2346
- };
2347
2319
  /**
2348
2320
  * Hooks for handling note on/off events. To be used with useMIDIAccess. Internally uses useMIDIMessage.
2349
2321
  */
2350
2322
  function useMIDIInput(midiAccess, onNoteOnEvent, onNoteOffEvent, onPitchBendEvent) {
2351
- useMIDIMessage(midiAccess, (0, react.useCallback)((event) => {
2352
- if (!event.data) return;
2353
- const kind = event.data[0] & 240;
2354
- if (kind == MIDI_EVENT_TO_NUMBER.NOTE_OFF || kind == MIDI_EVENT_TO_NUMBER.NOTE_ON && event.data[2] == 0) onNoteOffEvent?.(event.data[1]);
2355
- else if (kind == MIDI_EVENT_TO_NUMBER.NOTE_ON) onNoteOnEvent?.(event.data[1], event.data[2]);
2356
- else if (kind == MIDI_EVENT_TO_NUMBER.PITCH_BEND) onPitchBendEvent?.(event.data[1], event.data[2]);
2323
+ (0, react.useEffect)(() => {
2324
+ const instance = (0, _tremolo_ui_dom.createMIDIInput)(midiAccess, {
2325
+ onNoteOnEvent,
2326
+ onNoteOffEvent,
2327
+ onPitchBendEvent
2328
+ });
2329
+ return () => instance.destroy();
2357
2330
  }, [
2358
- onNoteOffEvent,
2331
+ midiAccess,
2359
2332
  onNoteOnEvent,
2333
+ onNoteOffEvent,
2360
2334
  onPitchBendEvent
2361
- ]));
2335
+ ]);
2336
+ }
2337
+ //#endregion
2338
+ //#region src/hooks/useMIDIMessage.ts
2339
+ /**
2340
+ * Hooks for when you want to process MIDI events in more detail than useMIDIInput.
2341
+ */
2342
+ function useMIDIMessage(midiAccess, onMIDIMessage) {
2343
+ (0, react.useEffect)(() => {
2344
+ const instance = (0, _tremolo_ui_dom.createMIDIMessage)(midiAccess, onMIDIMessage);
2345
+ return () => instance.destroy();
2346
+ }, [midiAccess, onMIDIMessage]);
2362
2347
  }
2363
2348
  //#endregion
2364
2349
  exports.AnimationCanvas = AnimationCanvas;
2365
2350
  exports.DragObserver = DragObserver;
2366
2351
  exports.Knob = Knob;
2367
- exports.NOT_SUPPORTED = NOT_SUPPORTED;
2352
+ Object.defineProperty(exports, "NOT_SUPPORTED", {
2353
+ enumerable: true,
2354
+ get: function() {
2355
+ return _tremolo_ui_dom.NOT_SUPPORTED;
2356
+ }
2357
+ });
2368
2358
  exports.NumberInput = NumberInput;
2369
- exports.PERMISSION_DENIED = PERMISSION_DENIED;
2359
+ Object.defineProperty(exports, "PERMISSION_DENIED", {
2360
+ enumerable: true,
2361
+ get: function() {
2362
+ return _tremolo_ui_dom.PERMISSION_DENIED;
2363
+ }
2364
+ });
2370
2365
  exports.Piano = Piano;
2371
2366
  exports.PointsEditor = PointsEditor;
2372
2367
  exports.SHORTCUTS = SHORTCUTS;