├── lib ├── vite-env.d.ts ├── constants.ts ├── hooks │ ├── use-subscribe.ts │ ├── use-midi-message.ts │ ├── use-midi-clock.ts │ ├── use-midi-outputs.ts │ ├── use-midi-inputs.ts │ ├── use-midi-note.ts │ ├── use-midi-controls.ts │ ├── use-midi-notes.ts │ ├── use-midi-control.ts │ └── use-midi-output.ts ├── main.ts ├── types.ts ├── midi-emitter.ts ├── reducer.ts └── midi-provider.tsx ├── src ├── vite-env.d.ts ├── .npmignore ├── main.tsx ├── App.css ├── MIDIInterfaceSelector.tsx └── App.tsx ├── tsconfig-build.json ├── .gitignore ├── tsconfig.node.json ├── index.html ├── vite.config.ts ├── tsconfig.json ├── package.json ├── README.md └── pnpm-lock.yaml /lib/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /tsconfig-build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["lib"] 4 | } 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | *ideas.txt 3 | node_modules 4 | *.local 5 | *.log 6 | /.vscode/ 7 | .DS_Store -------------------------------------------------------------------------------- /lib/constants.ts: -------------------------------------------------------------------------------- 1 | export const MIDIConstants = { 2 | noteOn: 0x90, 3 | noteOff: 0x80, 4 | cc: 0xb0, 5 | clock: 0xf0, 6 | tick: 0x08, 7 | play: 0x0a, 8 | stop: 0x0c, 9 | } 10 | -------------------------------------------------------------------------------- /src/.npmignore: -------------------------------------------------------------------------------- 1 | lib 2 | src 3 | *ideas.txt 4 | node_modules 5 | *.local 6 | *.log 7 | /.vscode/ 8 | .DS_Store 9 | tsconfig-build.json 10 | tsconfig.json 11 | tsconfig.node.json 12 | vite.config.ts 13 | index.html -------------------------------------------------------------------------------- /src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App' 4 | 5 | ReactDOM.createRoot(document.getElementById('root')!).render( 6 | 7 | 8 | 9 | ) 10 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /lib/hooks/use-subscribe.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useContext } from 'react' 2 | import { EventName } from '../types' 3 | import { MIDIContext } from '../midi-provider' 4 | 5 | export const useSubscribe = (event: EventName, cb: (args: any) => void) => { 6 | const { emitter } = useContext(MIDIContext) 7 | useEffect(() => { 8 | const id = emitter.subscribe(event, cb) 9 | return () => { 10 | emitter.unsubscribe('note', id) 11 | } 12 | }, [emitter, cb]) 13 | } 14 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import { resolve } from 'path' 3 | import react from '@vitejs/plugin-react-swc' 4 | import dts from 'vite-plugin-dts' 5 | 6 | // https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | plugins: [react(), dts({ include: ['lib'] })], 9 | build: { 10 | lib: { 11 | entry: resolve(__dirname, 'lib/main.ts'), 12 | fileName: 'main', 13 | formats: ['es'], 14 | }, 15 | rollupOptions: { 16 | external: ['react', 'react/jsx-runtime'], 17 | }, 18 | }, 19 | }) 20 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | *, 2 | body { 3 | background-color: #111111; 4 | color: white; 5 | font-family: monospace; 6 | } 7 | 8 | .section { 9 | margin-bottom: 4rem; 10 | /* background: b; */ 11 | } 12 | .section-title { 13 | font-size: 16px; 14 | } 15 | .subsection { 16 | margin-left: 1rem; 17 | margin-top: 1rem; 18 | } 19 | .subsection.tall { 20 | height: 200px; 21 | } 22 | .subsection-title { 23 | color: rgb(83, 218, 146); 24 | } 25 | .subsection-description { 26 | margin-bottom: 0.5rem; 27 | color: #5a55a0; 28 | } 29 | .value { 30 | color: rgb(222, 114, 255); 31 | } 32 | -------------------------------------------------------------------------------- /lib/main.ts: -------------------------------------------------------------------------------- 1 | export { MIDIProvider } from './midi-provider' 2 | export { useMIDIOutput } from './hooks/use-midi-output' 3 | export { useMIDIOutputs } from './hooks/use-midi-outputs' 4 | export { useMIDIInputs } from './hooks/use-midi-inputs' 5 | export { useMIDIControl } from './hooks/use-midi-control' 6 | export { useMIDIMessage } from './hooks/use-midi-message' 7 | export { useMIDIControls } from './hooks/use-midi-controls' 8 | export { useMIDINote } from './hooks/use-midi-note' 9 | export { useMIDINotes } from './hooks/use-midi-notes' 10 | // export { useMIDIClock } from './hooks/use-midi-clock'; 11 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | "jsx": "react-jsx", 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true 22 | }, 23 | "include": ["src", "lib"], 24 | "references": [{ "path": "./tsconfig.node.json" }] 25 | } 26 | -------------------------------------------------------------------------------- /lib/hooks/use-midi-message.ts: -------------------------------------------------------------------------------- 1 | import { useState } from 'react' 2 | import { MIDIMessage } from '../types' 3 | import { useSubscribe } from './use-subscribe' 4 | 5 | /** 6 | * Custom hook to subscribe to all MIDI messages. 7 | * 8 | * This hook listens for any MIDI messages and updates its state with the latest message received. 9 | * It is useful for components that need to react to or display information based on incoming MIDI messages. 10 | * 11 | * @returns {MIDIMessage | undefined} - The latest MIDI message received or `undefined` if no message has been received yet. 12 | * 13 | * @example 14 | * // To use this hook in a component to display the latest MIDI message 15 | * const midiMessage = useMIDIMessage(); 16 | * if (midiMessage) { 17 | * console.log(`MIDI message received:`, midiMessage); 18 | * } 19 | */ 20 | 21 | export const useMIDIMessage = () => { 22 | const [message, setMessage] = useState() 23 | const handleMessage = (message: MIDIMessage) => { 24 | setMessage(message) 25 | } 26 | useSubscribe('all', handleMessage) 27 | 28 | return message 29 | } 30 | -------------------------------------------------------------------------------- /src/MIDIInterfaceSelector.tsx: -------------------------------------------------------------------------------- 1 | import { useMIDIInputs, useMIDIOutputs } from '../lib/main' 2 | 3 | export const MIDIInterfaceSelector = () => { 4 | const { inputs, selectedInputId, selectInput } = useMIDIInputs() 5 | const { outputs, selectedOutputId, selectOutput } = useMIDIOutputs() 6 | return ( 7 |
8 |
MIDI Interface
9 |
10 |
Interface Selection
11 |
12 | Lists all inputs/outputs, switching when clicked. 13 |
14 |
15 | {inputs.map(({ id, name }) => ( 16 | 19 | ))} 20 |
21 |
22 | {outputs.map(({ id, name }) => ( 23 | 26 | ))} 27 |
28 |
29 |
30 | ) 31 | } 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@react-midi/hooks", 3 | "version": "2.0.1", 4 | "type": "module", 5 | "main": "dist/main.js", 6 | "types": "dist/main.d.ts", 7 | "files": [ 8 | "dist" 9 | ], 10 | "scripts": { 11 | "dev": "vite", 12 | "build": "tsc --p ./tsconfig-build.json && vite build", 13 | "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", 14 | "preview": "vite preview", 15 | "prepublishOnly": "npm run build" 16 | }, 17 | "peerDependencies": { 18 | "react": "^18.2.0" 19 | }, 20 | "devDependencies": { 21 | "@types/react": "^18.2.15", 22 | "@types/react-dom": "^18.2.7", 23 | "@types/uniqid": "^5.3.2", 24 | "@types/webmidi": "^2.0.8", 25 | "@typescript-eslint/eslint-plugin": "^6.0.0", 26 | "@typescript-eslint/parser": "^6.0.0", 27 | "@vitejs/plugin-react-swc": "^3.3.2", 28 | "eslint": "^8.45.0", 29 | "eslint-plugin-react-hooks": "^4.6.0", 30 | "eslint-plugin-react-refresh": "^0.4.3", 31 | "react": "^18.2.0", 32 | "react-dom": "^18.2.0", 33 | "typescript": "^5.0.2", 34 | "vite": "^4.4.5", 35 | "vite-plugin-dts": "^3.6.0" 36 | }, 37 | "dependencies": { 38 | "uniqid": "^5.4.0" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/hooks/use-midi-clock.ts: -------------------------------------------------------------------------------- 1 | import { useState, useCallback } from 'react' 2 | import { MIDIConstants } from '../constants' 3 | import { useSubscribe } from './use-subscribe' 4 | type Args = { 5 | division: number 6 | } 7 | 8 | // TODO: Test and complete. This is a work in progress. 9 | export const useMIDIClock = ({ division = 1 }: Args) => { 10 | const [step, setStep] = useState(0) 11 | const [isPlaying, setIsPlaying] = useState(false) 12 | const handleClockMessage = useCallback(() => { 13 | // Keep track of count through closure. Is there a better way? 14 | let steps = 0 15 | return (type: number) => { 16 | switch (type) { 17 | case MIDIConstants.tick: 18 | steps++ 19 | if (division === 1) setStep(steps) 20 | else if (steps % division === 0) setStep(Math.floor(steps / division)) 21 | break 22 | case MIDIConstants.play: 23 | setIsPlaying(true) 24 | break 25 | case MIDIConstants.stop: 26 | steps = 0 27 | setIsPlaying(false) 28 | setStep(0) 29 | break 30 | default: 31 | break 32 | } 33 | } 34 | }, [division, setStep, setIsPlaying]) 35 | useSubscribe('clock', handleClockMessage()) 36 | return { step, isPlaying } 37 | } 38 | -------------------------------------------------------------------------------- /lib/types.ts: -------------------------------------------------------------------------------- 1 | export type Connection = { 2 | id: string 3 | name: string 4 | manufacturer: string 5 | } 6 | 7 | export type Input = { 8 | onmidimessage: ((message: MIDIMessage) => void) | null 9 | } & Connection 10 | 11 | export type Output = { 12 | send: (message: number[], timestamp?: number) => void 13 | } & Connection 14 | 15 | export type InputsReturnValue = { 16 | input: Input | undefined 17 | inputs: Input[] 18 | selectInput: (inputId: string) => void 19 | selectedInputId: string | null 20 | } 21 | 22 | export type MIDINoteFilter = { 23 | note?: number // allow multiple? 24 | channel?: number 25 | // min/max velocity? 26 | } 27 | 28 | export type MIDIControlFilter = { 29 | cc?: number // allow multiple? 30 | channel?: number 31 | // min/max value? 32 | } 33 | 34 | export type MIDIMessage = { 35 | data: number[] 36 | } 37 | 38 | export type Message = { 39 | target: number // note or control 40 | value: number // velocity or control value 41 | channel: number 42 | } 43 | 44 | export type NoteMessage = Message & { 45 | on: boolean 46 | } 47 | 48 | export type MIDINote = { 49 | note: number 50 | velocity: number 51 | channel: number 52 | on: boolean 53 | } 54 | 55 | export type MIDIControl = { 56 | control: number 57 | value: number 58 | channel: number 59 | } 60 | 61 | export type EventName = 'all' | 'note' | 'clock' | 'control' 62 | -------------------------------------------------------------------------------- /lib/hooks/use-midi-outputs.ts: -------------------------------------------------------------------------------- 1 | import { useCallback, useContext } from 'react' 2 | import { MIDIContext } from '../midi-provider' 3 | import { outputSelected } from '../reducer' 4 | 5 | /** 6 | * Hook to access and manage MIDI output devices within a MIDIContext. 7 | * 8 | * This hook provides an interface to interact with available MIDI outputs and select a specific output device. 9 | * It leverages the MIDIContext to maintain and update the state related to MIDI outputs, including the current selection. 10 | * 11 | * @returns {Object} An object containing: 12 | * - output: The currently selected MIDI output device, or `undefined` if no device is selected. 13 | * - outputs: An array of all available MIDI output devices. 14 | * - selectOutput: A function to select an output device by its ID. 15 | * - selectedOutputId: The ID of the currently selected output device. 16 | * 17 | * @example 18 | * // Example of using this hook in a component to list MIDI outputs and allow selection. 19 | * const { output, outputs, selectOutput, selectedOutputId } = useMIDIOutputs(); 20 | * 21 | * // To select a MIDI output by ID, for example when a user clicks on an output device in the UI 22 | * selectOutput('desired-output-device-id'); 23 | */ 24 | 25 | export const useMIDIOutputs = () => { 26 | const { state, dispatch } = useContext(MIDIContext) 27 | const { outputs, selectedOutputId } = state 28 | const selectOutput = useCallback( 29 | (outputId: string) => { 30 | dispatch(outputSelected(outputId)) 31 | }, 32 | [dispatch] 33 | ) 34 | return { 35 | output: outputs.find(({ id }) => id === selectedOutputId), 36 | outputs, 37 | selectOutput, 38 | selectedOutputId, 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/hooks/use-midi-inputs.ts: -------------------------------------------------------------------------------- 1 | import { useCallback, useContext } from 'react' 2 | import { MIDIContext } from '../midi-provider' 3 | import { inputSelected } from '../reducer' 4 | import { InputsReturnValue } from '../types' 5 | 6 | /** 7 | * Hook to interact with MIDI input devices within a MIDIContext. 8 | * 9 | * This hook provides functionality to access the list of available MIDI input devices, 10 | * the currently selected MIDI input device, and a method to select a MIDI input device by its ID. 11 | * It leverages a MIDIContext to manage state and dispatch actions related to MIDI input selection. 12 | * 13 | * @returns {InputsReturnValue} An object containing: 14 | * - input: The currently selected MIDI input device based on the `selectedInputId`, or `undefined` if no such device is selected. 15 | * - inputs: An array of all detected MIDI input devices. 16 | * - selectInput: A function to select a MIDI input device by its ID. This updates the context state to reflect the selected device. 17 | * - selectedInputId: The ID of the currently selected MIDI input device, or `undefined` if no device is selected. 18 | * 19 | * @example 20 | * // Example of using this hook in a component to list MIDI inputs and allow selection. 21 | * const { input, inputs, selectInput, selectedInputId } = useMIDIInputs(); 22 | * 23 | * // To select a MIDI input by ID, for example when a user clicks on an input device in the UI 24 | * selectInput('desired-input-device-id'); 25 | */ 26 | 27 | export const useMIDIInputs = (): InputsReturnValue => { 28 | const { state, dispatch } = useContext(MIDIContext) 29 | const { inputs, selectedInputId } = state 30 | const selectInput = useCallback( 31 | (inputId: string) => { 32 | dispatch(inputSelected(inputId)) 33 | }, 34 | [dispatch] 35 | ) 36 | return { 37 | input: inputs.find(({ id }) => id === selectedInputId), 38 | inputs, 39 | selectInput, 40 | selectedInputId, 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/hooks/use-midi-note.ts: -------------------------------------------------------------------------------- 1 | import { useState, useCallback } from 'react' 2 | import { MIDINote, MIDINoteFilter, NoteMessage } from '../types' 3 | import { useSubscribe } from './use-subscribe' 4 | 5 | /** 6 | * Hook to subscribe to MIDI note messages that match specified filters. 7 | * 8 | * This hook allows you to listen for MIDI note messages and updates its state 9 | * with the message details if the message matches the specified note and channel filters. 10 | * If no filters are provided, it will update the state with every note message received. 11 | * 12 | * @param {MIDINoteFilter} [filters={}] - The filters to apply to incoming MIDI note messages. 13 | * @param {number} [filters.note] - The MIDI note number to filter messages by. 14 | * @param {number} [filters.channel] - The MIDI channel number to filter messages by. 15 | * 16 | * @returns {MIDINote | undefined} - The latest MIDI note message that matches the filters, 17 | * or `undefined` if no message has matched the filters yet. 18 | * 19 | * @example 20 | * // To use this hook to listen for note C3 (MIDI note number 60) on channel 1 21 | * const midiNote = useMIDINote({ note: 60, channel: 1 }); 22 | * if (midiNote) { 23 | * console.log(`Note ${midiNote.note} with velocity ${midiNote.velocity} received on channel ${midiNote.channel}`); 24 | * } 25 | */ 26 | 27 | export const useMIDINote = ({ 28 | note: noteFilter, 29 | channel: channelFilter, 30 | }: MIDINoteFilter = {}): MIDINote | undefined => { 31 | const [value, setValue] = useState() 32 | 33 | const handleNote = useCallback( 34 | (message: NoteMessage) => { 35 | const { target: note, value: velocity, on, channel } = message 36 | if ( 37 | (!noteFilter || noteFilter === note) && 38 | (!channelFilter || channelFilter === channel) 39 | ) { 40 | setValue({ note, on, velocity, channel }) 41 | } 42 | }, 43 | [noteFilter, channelFilter, setValue] 44 | ) 45 | useSubscribe('note', handleNote) 46 | 47 | return value 48 | } 49 | -------------------------------------------------------------------------------- /lib/hooks/use-midi-controls.ts: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react' 2 | import { MIDIControlFilter } from '../types' 3 | import { useMIDIControl } from './use-midi-control' 4 | 5 | /** 6 | * Hook to manage state for an array of MIDI control numbers, filtered by specific criteria. 7 | * 8 | * This hook listens for MIDI control change messages that match a provided filter, 9 | * and maintains an array of values corresponding to a predefined set of control numbers (`controls`). Each control's 10 | * value in the array is updated when a matching control change message is received. This is useful for components 11 | * that need to keep track of and react to changes in multiple MIDI control values simultaneously. 12 | * 13 | * @param {number[]} controls - An array of MIDI control numbers to monitor. 14 | * @param {Exclude} [filter={}] - An object specifying additional filters for MIDI control change messages. 15 | * Excludes the 'cc' property as that is specified by the first argument. 16 | * 17 | * @returns {number[]} An array of control values corresponding to the `controls` array. Each element in the array 18 | * represents the latest value for the control number at the same index in the `controls` input array. 19 | * 20 | * @example 21 | * // To use this hook to monitor control changes for MIDI controls 7 and 10 on channel 1 22 | * const controlValues = useMIDIControls([7, 10], { channel: 1 }); 23 | * // controlValues will be an array of two numbers, initially [0, 0], updated with the latest values for controls 7 and 10. 24 | */ 25 | 26 | export const useMIDIControls = ( 27 | controls: number[], 28 | filter: Exclude = {} 29 | ) => { 30 | const [values, setValues] = useState(controls.map(() => 0)) 31 | const cc = useMIDIControl(filter) 32 | 33 | // TODO: Get this all fixed up 34 | useEffect(() => { 35 | if (cc) { 36 | const targetIndex = controls.indexOf(cc.control) 37 | if (targetIndex > -1) 38 | setValues(values.map((v, i) => (i === targetIndex ? cc.value : v))) 39 | } 40 | }, [cc]) 41 | 42 | return values 43 | } 44 | -------------------------------------------------------------------------------- /lib/hooks/use-midi-notes.ts: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react' 2 | import { MIDINoteFilter, MIDINote } from '../types' 3 | import { useMIDINote } from './use-midi-note' 4 | 5 | /** 6 | * Hook to manage an array of MIDI note messages that match a given filter. 7 | * 8 | * This hook subscribes to MIDI note messages that satisfy specified filtering criteria (such as note number and channel). 9 | * It maintains an array of active (i.e., currently pressed) MIDI notes. When a note-on message is received, the note is 10 | * added to the array. When a note-off message for an active note is received, that note is removed from the array. 11 | * This allows for tracking of currently active MIDI notes that match the filter. 12 | * 13 | * @param {MIDINoteFilter} [filter={}] - An object specifying the filtering criteria for MIDI note messages. 14 | * This can include properties like `note` (to filter by MIDI note number) and `channel` (to filter by MIDI channel). 15 | * 16 | * @returns {MIDINote[]} An array of MIDI notes that are currently active (i.e., note-on messages have been received, 17 | * but corresponding note-off messages have not yet been received) and match the specified filter. Each 18 | * element in the array is an object representing a MIDI note message, including properties like the note number, 19 | * velocity, and channel. 20 | * 21 | * @example 22 | * // To use this hook to monitor active notes for MIDI channel 1 23 | * const activeNotes = useMIDINotes({ channel: 1 }); 24 | * // activeNotes will be an array of objects, each representing an active MIDI note on channel 1. 25 | */ 26 | 27 | export const useMIDINotes = (filter: MIDINoteFilter = {}) => { 28 | const [notes, setNotes] = useState([]) 29 | const value = useMIDINote(filter) 30 | useEffect(() => { 31 | if (value) { 32 | if (value === notes[notes.length - 1]) { 33 | return 34 | } 35 | if (value.on) { 36 | setNotes([...notes, value]) 37 | } else { 38 | setNotes(notes.filter((n) => n.note !== value.note)) 39 | } 40 | } 41 | }, [value]) 42 | return notes 43 | } 44 | -------------------------------------------------------------------------------- /lib/midi-emitter.ts: -------------------------------------------------------------------------------- 1 | import uniqid from 'uniqid' 2 | import { MIDIMessage, Message, NoteMessage, EventName } from './types' 3 | import { MIDIConstants } from './constants' 4 | 5 | type Subscriptions = { 6 | all: { [id: string]: (args: MIDIMessage) => void } 7 | note: { [id: string]: (args: NoteMessage) => void } 8 | clock: { [id: string]: (args: number) => void } 9 | control: { [id: string]: (args: Message) => void } 10 | } 11 | 12 | export class MIDIEmitter { 13 | private subscriptions: Subscriptions = { 14 | all: {}, 15 | note: {}, 16 | clock: {}, 17 | control: {}, // Consider splitting this up into things like 'control:36' 18 | } 19 | 20 | subscribe(eventName: EventName, callback: (args: any) => void) { 21 | const id = uniqid() 22 | this.subscriptions[eventName][id] = callback 23 | return id 24 | } 25 | 26 | unsubscribe(eventName: EventName, id: string) { 27 | delete this.subscriptions[eventName][id] 28 | } 29 | 30 | onMIDIMessage(message: MIDIMessage) { 31 | const action = message.data[0] & 0xf0 // Mask channel/least significant bits; 32 | const leastSig = message.data[0] & 0x0f // Mask action bits; 33 | const channel = leastSig + 1 34 | const { all, note, control, clock } = this.subscriptions 35 | for (const key in all) { 36 | all[key](message) 37 | } 38 | 39 | switch (action) { 40 | case MIDIConstants.cc: 41 | for (const key in control) { 42 | control[key]({ 43 | target: message.data[1], 44 | value: message.data[2], 45 | channel, 46 | }) // (value, control, channel) 47 | } 48 | break 49 | case MIDIConstants.noteOn: 50 | case MIDIConstants.noteOff: 51 | for (const key in note) { 52 | note[key]({ 53 | target: message.data[1], // note 54 | value: message.data[2], // velocity 55 | channel, 56 | on: action === MIDIConstants.noteOn, 57 | }) 58 | } 59 | break 60 | case MIDIConstants.clock: // Transport/Clock Message 61 | for (const key in clock) { 62 | clock[key](leastSig) // (type) 63 | } 64 | break 65 | default: 66 | break 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /lib/hooks/use-midi-control.ts: -------------------------------------------------------------------------------- 1 | import { useState, useCallback } from 'react' 2 | import { Message, MIDIControlFilter, MIDIControl } from '../types' 3 | import { useSubscribe } from './use-subscribe' 4 | 5 | // Before a control message is sent, we do not have a default value for the control. 6 | type MIDIControlState = MIDIControl & { value?: number } 7 | 8 | /** 9 | * Hook to subscribe to MIDI control change messages based on specified filters. 10 | * 11 | * This hook listens for MIDI control change (CC) messages and updates its state 12 | * with the details of the message if it matches the specified control number and channel filters. 13 | * If no filters are provided, it will update the state with every control change message received. 14 | * This can be useful for components that need to react to specific control change messages. 15 | * 16 | * @param {Object} [filters={}] - The filters to apply to incoming MIDI control change messages. 17 | * @param {number} [filters.cc] - The MIDI control change number to filter messages by. 18 | * @param {number} [filters.channel] - The MIDI channel number to filter messages by. 19 | * 20 | * @returns {MIDIControlState | undefined} - The latest MIDI control change message that matches the filters, 21 | * or `undefined` if no message has matched the filters yet. 22 | * 23 | * @example 24 | * // To use this hook to listen for control change number 7 on channel 1 25 | * const midiControl = useMIDIControl({ cc: 7, channel: 1 }); 26 | * if (midiControl) { 27 | * console.log(`Control change ${midiControl.control} with value ${midiControl.value} received on channel ${midiControl.channel}`); 28 | * } 29 | */ 30 | 31 | export const useMIDIControl = ({ 32 | cc: controlFilter, 33 | channel: channelFilter, 34 | }: MIDIControlFilter = {}) => { 35 | const [value, setValue] = useState(undefined) 36 | const handleCC = useCallback( 37 | (message: Message) => { 38 | const { target, value, channel } = message 39 | if ( 40 | (!controlFilter || controlFilter === target) && 41 | (!channelFilter || channelFilter === channel) 42 | ) { 43 | setValue({ control: target, value, channel }) 44 | } 45 | }, 46 | [controlFilter, channelFilter, setValue] 47 | ) 48 | useSubscribe('control', handleCC) 49 | return value 50 | } 51 | -------------------------------------------------------------------------------- /lib/reducer.ts: -------------------------------------------------------------------------------- 1 | import { Input, Output } from './types' 2 | 3 | export type ReducerState = { 4 | inputs: Input[] 5 | outputs: Output[] 6 | selectedInputId: string | null 7 | selectedOutputId: string | null 8 | } 9 | 10 | enum ActionTypes { 11 | accessReceived = 'AccessReceived', 12 | inputSelected = 'InputSelected', 13 | outputSelected = 'OutputSelected', 14 | } 15 | 16 | export const defaultState: ReducerState = { 17 | inputs: [], 18 | outputs: [], 19 | selectedInputId: null, 20 | selectedOutputId: null, 21 | } 22 | 23 | export const reducer = ( 24 | state: ReducerState = defaultState, 25 | action: { type: string; payload?: any } 26 | ): ReducerState => { 27 | const { type, payload } = action 28 | switch (type) { 29 | case ActionTypes.accessReceived: 30 | // If selectedInputId is defined and the id still exists in the new connections, let it remain 31 | const inputExists = payload.inputs.some( 32 | (input: Input) => input.id === state.selectedInputId 33 | ) 34 | const outputExists = payload.outputs.find( 35 | (output: Input) => output.id === state.selectedOutputId 36 | ) 37 | return { 38 | ...state, 39 | inputs: payload.inputs, 40 | outputs: payload.outputs, 41 | selectedInputId: inputExists 42 | ? state.selectedInputId 43 | : payload.inputs.length 44 | ? payload.inputs[0].id 45 | : null, 46 | selectedOutputId: outputExists 47 | ? state.selectedOutputId 48 | : payload.outputs.length 49 | ? payload.outputs[0].id 50 | : null, 51 | } 52 | case ActionTypes.inputSelected: 53 | return { 54 | ...state, 55 | selectedInputId: payload.inputId, 56 | } 57 | case ActionTypes.outputSelected: 58 | return { 59 | ...state, 60 | selectedOutputId: payload.outputId, 61 | } 62 | default: 63 | return state 64 | } 65 | } 66 | 67 | export const accessReceived = (access: WebMidi.MIDIAccess) => ({ 68 | type: ActionTypes.accessReceived, 69 | payload: { 70 | inputs: Array.from(access.inputs.values()), 71 | outputs: Array.from(access.outputs.values()), 72 | }, 73 | }) 74 | 75 | export const inputSelected = (inputId: string) => ({ 76 | type: ActionTypes.inputSelected, 77 | payload: { inputId }, 78 | }) 79 | 80 | export const outputSelected = (outputId: string) => ({ 81 | type: ActionTypes.outputSelected, 82 | payload: { outputId }, 83 | }) 84 | -------------------------------------------------------------------------------- /lib/midi-provider.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useReducer, useRef } from 'react' 2 | import { MIDIEmitter } from './midi-emitter' 3 | import { reducer, accessReceived, defaultState, ReducerState } from './reducer' 4 | 5 | // TODO Don't expose the whole midi emitter, just subscribe and unsubscribe for now. 6 | export const MIDIContext = React.createContext<{ 7 | state: ReducerState 8 | dispatch: React.Dispatch<{ 9 | type: string 10 | payload?: any 11 | }> 12 | emitter: MIDIEmitter 13 | }>({ state: defaultState, dispatch: () => null, emitter: new MIDIEmitter() }) 14 | 15 | type Props = { 16 | children?: React.ReactNode 17 | } 18 | 19 | /** 20 | * Provides a MIDI context for its child components, managing MIDI access, inputs, and state changes. 21 | * 22 | * This component encapsulates MIDI initialization and state management logic, leveraging the Web MIDI API. 23 | * It listens for MIDI access and input changes, updating the context state accordingly. This state is then 24 | * accessible to any child components through the MIDIContext. It also sets up an emitter for MIDI messages, 25 | * allowing child components to subscribe to MIDI message events. 26 | * 27 | * @param {Object} props - The component props. 28 | * @param {React.ReactNode} props.children - Child components that will have access to the MIDIContext. 29 | * 30 | * @example 31 | * // Wrap your application or component tree with MIDIProvider to provide MIDI context. 32 | * 33 | * 34 | * 35 | */ 36 | 37 | export const MIDIProvider = ({ children }: Props) => { 38 | const emitter = useRef(new MIDIEmitter()) 39 | const [state, dispatch] = useReducer(reducer, defaultState) 40 | const { inputs, selectedInputId } = state 41 | 42 | useEffect(() => { 43 | if (Boolean(navigator?.requestMIDIAccess)) { 44 | navigator.requestMIDIAccess().then((access: WebMidi.MIDIAccess) => { 45 | dispatch(accessReceived(access)) 46 | access.onstatechange = () => { 47 | dispatch(accessReceived(access)) 48 | } 49 | }) 50 | } 51 | }, [dispatch]) 52 | 53 | useEffect(() => { 54 | const selectedInput = inputs.find((i) => i.id === selectedInputId) 55 | if (selectedInput) { 56 | selectedInput.onmidimessage = emitter.current.onMIDIMessage.bind( 57 | emitter.current 58 | ) 59 | return () => (selectedInput.onmidimessage = null) 60 | } 61 | return () => {} 62 | }, [inputs, selectedInputId]) 63 | 64 | return ( 65 | 66 | {children} 67 | 68 | ) 69 | } 70 | -------------------------------------------------------------------------------- /lib/hooks/use-midi-output.ts: -------------------------------------------------------------------------------- 1 | import { MIDIConstants } from '../constants' 2 | import { useMIDIOutputs } from './use-midi-outputs' 3 | 4 | type SingleNote = number 5 | type MultipleNotes = number[] 6 | export type MultipleNotesWithOptions = { 7 | note: number 8 | velocity?: number 9 | channel?: number 10 | }[] 11 | 12 | type NoteInput = SingleNote | MultipleNotes | MultipleNotesWithOptions 13 | 14 | type NoteOptions = { 15 | velocity?: number 16 | channel?: number 17 | } 18 | 19 | /** 20 | * Hook to interact with a MIDI output device. 21 | * 22 | * This hook provides methods to send MIDI messages (note on, note off, and control change) to the selected MIDI output. 23 | * It simplifies the process of sending MIDI messages by abstracting the details of constructing MIDI message arrays. 24 | * 25 | * @returns {Object} An object containing the methods to interact with the MIDI output: 26 | * - noteOn: Function to send a 'note on' message for one or more notes. 27 | * - noteOff: Function to send a 'note off' message for one or more notes. 28 | * - cc: Function to send a control change message. 29 | * 30 | * @example 31 | * // To use this hook in a component to send a 'note on' and 'note off' message 32 | * const { noteOn, noteOff, cc } = useMIDIOutput(); 33 | * noteOn(60, { velocity: 127, channel: 1 }); // Send 'note on' for note 60 with velocity 127 on channel 1 34 | * noteOff(60, { channel: 1 }); // Send 'note off' for note 60 on channel 1 35 | * cc(64, 127, 1); // Send control change message with control number 64, value 127, on channel 1 36 | */ 37 | 38 | export const useMIDIOutput = () => { 39 | const { output } = useMIDIOutputs() 40 | if (!output) return {} 41 | 42 | const noteOn = (noteInput: NoteInput, options?: NoteOptions) => { 43 | const messages = getNoteMessages({ 44 | type: MIDIConstants.noteOn, 45 | noteInput, 46 | ...options, 47 | }) 48 | output.send(messages) 49 | } 50 | 51 | const noteOff = (noteInput: NoteInput, options?: NoteOptions) => { 52 | const messages = getNoteMessages({ 53 | type: MIDIConstants.noteOff, 54 | noteInput, 55 | ...options, 56 | }) 57 | output.send(messages) 58 | } 59 | 60 | const cc = (value: number, control = 0x14, channel = 1) => { 61 | const ccAndChannel = MIDIConstants.cc | getChannel(channel) 62 | output.send([ccAndChannel, control, value]) 63 | } 64 | 65 | return { noteOn, noteOff, cc } 66 | } 67 | 68 | type GetNoteMessagesArgs = { type: number; noteInput: NoteInput } & NoteOptions 69 | const getNoteMessages = ({ 70 | type, 71 | noteInput, 72 | velocity = 127, 73 | channel = 1, 74 | }: GetNoteMessagesArgs) => { 75 | const defaultChannelData = type | getChannel(channel) 76 | if (typeof noteInput === 'number') { 77 | return [defaultChannelData, noteInput, velocity] 78 | } else { 79 | return noteInput.reduce((messages, note) => { 80 | if (typeof note === 'number') { 81 | messages.push(defaultChannelData, note, velocity) 82 | } else { 83 | messages.push( 84 | note.channel ? type | getChannel(note.channel) : defaultChannelData, 85 | note.note, 86 | note.velocity ?? velocity 87 | ) 88 | } 89 | return messages 90 | }, [] as number[]) 91 | } 92 | } 93 | 94 | const getChannel = (channel: number) => { 95 | if (channel < 1 || channel > 16) return 0 //Channel 1 96 | return channel - 1 97 | } 98 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # @react-midi/hooks 2 | 3 | This package provides hooks for building MIDI-capable React applications and components. 4 | 5 | ``` 6 | npm install --save @react-midi/hooks 7 | ``` 8 | 9 | ## `` 10 | 11 | The `MIDIProvider` component serves as the cornerstone of our MIDI integration, enabling seamless interaction with MIDI devices directly within your React application. By leveraging the Web MIDI API, `MIDIProvider` offers a comprehensive solution for managing MIDI connections, inputs, outputs, and real-time MIDI events, all within a reactively designed context. 12 | 13 | `MIDIProvider` is a prerequisite for utilizing any of the other MIDI-related hooks within our library, as they depend on the context it establishes to function correctly. 14 | 15 | ### Getting Started: 16 | 17 | To begin working with `@react-midi/hooks`, wrap your component tree with `MIDIProvider`: 18 | 19 | ```ts 20 | import { MIDIProvider } from '@react-midi/hooks' 21 | 22 | function App() { 23 | return ( 24 | 25 | 26 | 27 | ) 28 | } 29 | ``` 30 | 31 | ## `useMIDIInputs()`: 32 | 33 | The `useMIDIInputs` hook is designed to simplify the process of accessing and managing MIDI input devices. It provides an interface for obtaining the list of available MIDI inputs, identifying the currently selected input device, and selecting an input device by its ID. 34 | 35 | ```ts 36 | const { input, inputs, selectInput, selectedInputId } = useMIDIInputs() 37 | 38 | // Example: Select a MIDI input by ID 39 | selectInput('desired-input-device-id') 40 | ``` 41 | 42 | ## `useMIDIOutputs()`: 43 | 44 | The `useMIDIOutputs` hook is almost the exact same as `useMIDIInputs`, but handles MIDI outputs instead. It provides an interface for obtaining the list of available MIDI outputs, identifying the currently selected output device, and selecting an output device by its ID. 45 | 46 | ```ts 47 | const { output, outputs, selectOutput, selectedOutputId } = useMIDIOutputs() 48 | 49 | // Example: Select a MIDI output by ID 50 | selectInput('desired-output-device-id') 51 | ``` 52 | 53 | ## `useMIDIOutput()`: 54 | 55 | The `useMIDIOutput` hook provides methods to send MIDI messages (note on, note off, and control change) to the selected MIDI output. 56 | It simplifies the process of sending MIDI messages by abstracting the details of constructing MIDI message arrays. 57 | 58 | ```ts 59 | // To use this hook in a component to send a 'note on' and 'note off' message 60 | const { noteOn, noteOff, cc } = useMIDIOutput() 61 | noteOn(60, { velocity: 127, channel: 1 }) // Send 'note on' for note 60 with velocity 127 on channel 1 62 | noteOff(60, { channel: 1 }) // Send 'note off' for note 60 on channel 1 63 | cc(64, 127, 1) // Send control change message with control number 64, value 127, on channel 1 64 | ``` 65 | 66 | ## `useMIDINote()`: 67 | 68 | The `useMIDINote` hook allows you to listen for MIDI note messages and updates its state 69 | with the message details if the message matches the specified note and channel filters. If no filters are provided, it will update the state with every note message received. 70 | 71 | ```ts 72 | // To use this hook to listen for note C3 (MIDI note number 60) on channel 1 73 | const midiNote = useMIDINote({ note: 60, channel: 1 }) 74 | if (midiNote) { 75 | console.log( 76 | `Note ${midiNote.note} with velocity ${midiNote.velocity} received on channel ${midiNote.channel}` 77 | ) 78 | } 79 | ``` 80 | 81 | ## `useMIDINotes()`: 82 | 83 | The `useMIDINotes` hook subscribes to MIDI note messages that satisfy specified filtering criteria (such as note number and channel). 84 | It maintains an array of active (i.e., currently pressed) MIDI notes. When a note-on message is received, the note is 85 | added to the array. When a note-off message for an active note is received, that note is removed from the array. 86 | This allows for tracking of currently active MIDI notes that match the filter. 87 | 88 | ```ts 89 | // To use this hook to monitor active notes for MIDI channel 1 90 | const activeNotes = useMIDINotes({ channel: 1 }) 91 | // activeNotes will be an array of objects, each representing an active MIDI note on channel 1. 92 | ``` 93 | 94 | ## `useMIDIControl()`: 95 | 96 | The `useMIDIControl` hook listens for MIDI control change (CC) messages and updates its state 97 | with the details of the message if it matches the specified control number and channel filters. 98 | If no filters are provided, it will update the state with every control change message received. 99 | This can be useful for components that need to react to specific control change messages. 100 | 101 | ```ts 102 | // To use this hook to listen for control change number 7 on channel 1 103 | const midiControl = useMIDIControl({ cc: 7, channel: 1 }) 104 | if (midiControl) { 105 | console.log( 106 | `Control change ${midiControl.control} with value ${midiControl.value} received on channel ${midiControl.channel}` 107 | ) 108 | } 109 | ``` 110 | 111 | ## `useMIDIControls()`: 112 | 113 | The `useMIDIControls` hook listens for MIDI control change messages that match a provided filter, 114 | and maintains an array of values corresponding to a predefined set of control numbers (`controls`). Each control's 115 | value in the array is updated when a matching control change message is received. This is useful for components 116 | that need to keep track of and react to changes in multiple MIDI control values simultaneously. 117 | 118 | ```ts 119 | // To use this hook to monitor control changes for MIDI controls 7 and 10 on channel 1 120 | const controlValues = useMIDIControls([7, 10], { channel: 1 }) 121 | // controlValues will be an array of two numbers, initially [0, 0], updated with the latest values for controls 7 and 10. 122 | ``` 123 | 124 | ## `useMIDIMessage()`: 125 | 126 | The `useMIDIMessage` hook listens for any MIDI messages and updates its state with the latest message received. 127 | It is useful for components that need to react to or display information based on incoming MIDI messages. 128 | 129 | ```ts 130 | // To use this hook in a component to display the latest MIDI message 131 | const midiMessage = useMIDIMessage() 132 | if (midiMessage) { 133 | console.log(`MIDI message received:`, midiMessage) 134 | } 135 | ``` 136 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { MultipleNotesWithOptions } from '../lib/hooks/use-midi-output' 3 | import { 4 | useMIDIOutput, 5 | MIDIProvider, 6 | useMIDIControl, 7 | useMIDIMessage, 8 | useMIDIControls, 9 | useMIDINote, 10 | useMIDINotes, 11 | } from '../lib/main' 12 | import './App.css' 13 | import { MIDIInterfaceSelector } from './MIDIInterfaceSelector.tsx' 14 | 15 | const MIDIBoard = () => { 16 | const { noteOn, noteOff } = useMIDIOutput() 17 | const playNotesFromNumArr = (notes: number[]) => { 18 | if (noteOn && noteOff) { 19 | noteOn(notes) 20 | window.setTimeout(() => noteOff(notes), 1000) 21 | } 22 | } 23 | const playNotesFromObjArr = (notes: MultipleNotesWithOptions) => { 24 | if (noteOn && noteOff) { 25 | noteOn(notes) 26 | window.setTimeout(() => noteOff(notes), 1000) 27 | } 28 | } 29 | return ( 30 |
31 |

Output

32 |
33 |
noteOn()
34 |
35 | Triggers note on with various settings 36 |
37 | 38 | 41 | 44 | 49 |
50 | 51 |
52 |
noteOff()
53 |
54 | Triggers note off with various settings 55 |
56 | 57 | 60 | 63 | 70 |
71 | 72 |
73 |
noteOn() + noteOff()
74 |
75 | Triggers note on and schedules note off with setTimeout() 76 |
77 | 80 | 90 |
91 |
92 | ) 93 | } 94 | 95 | const MIDIMonitor = () => { 96 | const message = useMIDIMessage() 97 | return ( 98 |
99 |
All Input
100 |
101 |
useMIDIMessage()
102 |
103 | Listens to all midi messages coming from input. 104 |
105 | {message?.data.join(',') ?? 'No message'} 106 |
107 |
108 | ) 109 | } 110 | 111 | const MIDIControlTest = () => { 112 | const allCC = useMIDIControl() 113 | const cc4 = useMIDIControl({ cc: 4 }) 114 | const [cc5, cc6, cc7] = useMIDIControls([5, 6, 7]) 115 | return ( 116 |
117 |
MIDI CCs
118 |
119 |
useMIDIControl()
120 |
121 | Listens to all midi control messages coming from input. 122 |
123 | 124 |
125 | Channel: {allCC?.channel} Control:{' '} 126 | {allCC?.control} Value:{' '} 127 | {allCC?.value} 128 |
129 |
130 |
131 |
132 | {'useMIDIControl({ target: 4 })'} 133 |
134 |
135 | Listens to CC 4 messages coming from input. 136 |
137 | 138 |
139 | Channel: {cc4?.channel} Control:{' '} 140 | {cc4?.control} Value:{' '} 141 | {cc4?.value} 142 |
143 |
144 | 145 |
146 |
{'useMIDIControls([5, 6, 7])'}
147 |
148 | Listens to CC4 messages coming from input. 149 |
150 | CC5: {cc5} CC6:{' '} 151 | {cc6} CC7:{' '} 152 | {cc7} 153 |
154 |
155 | ) 156 | } 157 | 158 | const MIDINoteTest = () => { 159 | const allNote = useMIDINote() 160 | const middleC = useMIDINote({ note: 60 }) 161 | const notes = useMIDINotes() 162 | return ( 163 |
164 |
Notes
165 |
166 |
useMIDINote()
167 |
168 | Listens to all incoming MIDI notes on input. 169 |
170 |

171 | Channel: {allNote?.channel} Control:{' '} 172 | {allNote?.note} Velocity:{' '} 173 | {allNote?.velocity} On:{' '} 174 | {allNote?.on ? 'true' : 'false'} 175 |

176 |
177 |
178 |
{'useMIDINote({ target: 60 })'}
179 |
180 | Listens to middle C coming from input. 181 |
182 |

183 | Channel: {middleC?.channel} Note:{' '} 184 | {middleC?.note} Velocity:{' '} 185 | {middleC?.velocity} On:{' '} 186 | {middleC?.on ? 'true' : 'false'} 187 |

188 |
189 | 190 |
191 |
{'useMIDINotes()'}
192 |
193 | Listens to input and maintains a list of active notes. 194 |
195 | {notes.map((note, i) => ( 196 |

197 | Note: {note.note} Velocity:{' '} 198 | {note.velocity} Channel:{' '} 199 | {note.channel} 200 |

201 | ))} 202 |
203 |
204 | ) 205 | } 206 | 207 | function App() { 208 | return ( 209 | 210 |

@react-midi/hooks Test App

211 | 212 | 213 | 214 | 215 | 216 |
217 | ) 218 | } 219 | 220 | export default App 221 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '6.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | dependencies: 8 | uniqid: 9 | specifier: ^5.4.0 10 | version: 5.4.0 11 | 12 | devDependencies: 13 | '@types/react': 14 | specifier: ^18.2.15 15 | version: 18.2.28 16 | '@types/react-dom': 17 | specifier: ^18.2.7 18 | version: 18.2.13 19 | '@types/uniqid': 20 | specifier: ^5.3.2 21 | version: 5.3.2 22 | '@types/webmidi': 23 | specifier: ^2.0.8 24 | version: 2.0.8 25 | '@typescript-eslint/eslint-plugin': 26 | specifier: ^6.0.0 27 | version: 6.7.5(@typescript-eslint/parser@6.7.5)(eslint@8.51.0)(typescript@5.2.2) 28 | '@typescript-eslint/parser': 29 | specifier: ^6.0.0 30 | version: 6.7.5(eslint@8.51.0)(typescript@5.2.2) 31 | '@vitejs/plugin-react-swc': 32 | specifier: ^3.3.2 33 | version: 3.4.0(vite@4.4.11) 34 | eslint: 35 | specifier: ^8.45.0 36 | version: 8.51.0 37 | eslint-plugin-react-hooks: 38 | specifier: ^4.6.0 39 | version: 4.6.0(eslint@8.51.0) 40 | eslint-plugin-react-refresh: 41 | specifier: ^0.4.3 42 | version: 0.4.3(eslint@8.51.0) 43 | react: 44 | specifier: ^18.2.0 45 | version: 18.2.0 46 | react-dom: 47 | specifier: ^18.2.0 48 | version: 18.2.0(react@18.2.0) 49 | typescript: 50 | specifier: ^5.0.2 51 | version: 5.2.2 52 | vite: 53 | specifier: ^4.4.5 54 | version: 4.4.11 55 | vite-plugin-dts: 56 | specifier: ^3.6.0 57 | version: 3.6.0(typescript@5.2.2)(vite@4.4.11) 58 | 59 | packages: 60 | 61 | /@aashutoshrathi/word-wrap@1.2.6: 62 | resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} 63 | engines: {node: '>=0.10.0'} 64 | dev: true 65 | 66 | /@babel/helper-string-parser@7.22.5: 67 | resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} 68 | engines: {node: '>=6.9.0'} 69 | dev: true 70 | 71 | /@babel/helper-validator-identifier@7.22.20: 72 | resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} 73 | engines: {node: '>=6.9.0'} 74 | dev: true 75 | 76 | /@babel/parser@7.23.0: 77 | resolution: {integrity: sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==} 78 | engines: {node: '>=6.0.0'} 79 | hasBin: true 80 | dependencies: 81 | '@babel/types': 7.23.0 82 | dev: true 83 | 84 | /@babel/types@7.23.0: 85 | resolution: {integrity: sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==} 86 | engines: {node: '>=6.9.0'} 87 | dependencies: 88 | '@babel/helper-string-parser': 7.22.5 89 | '@babel/helper-validator-identifier': 7.22.20 90 | to-fast-properties: 2.0.0 91 | dev: true 92 | 93 | /@esbuild/android-arm64@0.18.20: 94 | resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} 95 | engines: {node: '>=12'} 96 | cpu: [arm64] 97 | os: [android] 98 | requiresBuild: true 99 | dev: true 100 | optional: true 101 | 102 | /@esbuild/android-arm@0.18.20: 103 | resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} 104 | engines: {node: '>=12'} 105 | cpu: [arm] 106 | os: [android] 107 | requiresBuild: true 108 | dev: true 109 | optional: true 110 | 111 | /@esbuild/android-x64@0.18.20: 112 | resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} 113 | engines: {node: '>=12'} 114 | cpu: [x64] 115 | os: [android] 116 | requiresBuild: true 117 | dev: true 118 | optional: true 119 | 120 | /@esbuild/darwin-arm64@0.18.20: 121 | resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} 122 | engines: {node: '>=12'} 123 | cpu: [arm64] 124 | os: [darwin] 125 | requiresBuild: true 126 | dev: true 127 | optional: true 128 | 129 | /@esbuild/darwin-x64@0.18.20: 130 | resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} 131 | engines: {node: '>=12'} 132 | cpu: [x64] 133 | os: [darwin] 134 | requiresBuild: true 135 | dev: true 136 | optional: true 137 | 138 | /@esbuild/freebsd-arm64@0.18.20: 139 | resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} 140 | engines: {node: '>=12'} 141 | cpu: [arm64] 142 | os: [freebsd] 143 | requiresBuild: true 144 | dev: true 145 | optional: true 146 | 147 | /@esbuild/freebsd-x64@0.18.20: 148 | resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} 149 | engines: {node: '>=12'} 150 | cpu: [x64] 151 | os: [freebsd] 152 | requiresBuild: true 153 | dev: true 154 | optional: true 155 | 156 | /@esbuild/linux-arm64@0.18.20: 157 | resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} 158 | engines: {node: '>=12'} 159 | cpu: [arm64] 160 | os: [linux] 161 | requiresBuild: true 162 | dev: true 163 | optional: true 164 | 165 | /@esbuild/linux-arm@0.18.20: 166 | resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} 167 | engines: {node: '>=12'} 168 | cpu: [arm] 169 | os: [linux] 170 | requiresBuild: true 171 | dev: true 172 | optional: true 173 | 174 | /@esbuild/linux-ia32@0.18.20: 175 | resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} 176 | engines: {node: '>=12'} 177 | cpu: [ia32] 178 | os: [linux] 179 | requiresBuild: true 180 | dev: true 181 | optional: true 182 | 183 | /@esbuild/linux-loong64@0.18.20: 184 | resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} 185 | engines: {node: '>=12'} 186 | cpu: [loong64] 187 | os: [linux] 188 | requiresBuild: true 189 | dev: true 190 | optional: true 191 | 192 | /@esbuild/linux-mips64el@0.18.20: 193 | resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} 194 | engines: {node: '>=12'} 195 | cpu: [mips64el] 196 | os: [linux] 197 | requiresBuild: true 198 | dev: true 199 | optional: true 200 | 201 | /@esbuild/linux-ppc64@0.18.20: 202 | resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} 203 | engines: {node: '>=12'} 204 | cpu: [ppc64] 205 | os: [linux] 206 | requiresBuild: true 207 | dev: true 208 | optional: true 209 | 210 | /@esbuild/linux-riscv64@0.18.20: 211 | resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} 212 | engines: {node: '>=12'} 213 | cpu: [riscv64] 214 | os: [linux] 215 | requiresBuild: true 216 | dev: true 217 | optional: true 218 | 219 | /@esbuild/linux-s390x@0.18.20: 220 | resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} 221 | engines: {node: '>=12'} 222 | cpu: [s390x] 223 | os: [linux] 224 | requiresBuild: true 225 | dev: true 226 | optional: true 227 | 228 | /@esbuild/linux-x64@0.18.20: 229 | resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} 230 | engines: {node: '>=12'} 231 | cpu: [x64] 232 | os: [linux] 233 | requiresBuild: true 234 | dev: true 235 | optional: true 236 | 237 | /@esbuild/netbsd-x64@0.18.20: 238 | resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} 239 | engines: {node: '>=12'} 240 | cpu: [x64] 241 | os: [netbsd] 242 | requiresBuild: true 243 | dev: true 244 | optional: true 245 | 246 | /@esbuild/openbsd-x64@0.18.20: 247 | resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} 248 | engines: {node: '>=12'} 249 | cpu: [x64] 250 | os: [openbsd] 251 | requiresBuild: true 252 | dev: true 253 | optional: true 254 | 255 | /@esbuild/sunos-x64@0.18.20: 256 | resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} 257 | engines: {node: '>=12'} 258 | cpu: [x64] 259 | os: [sunos] 260 | requiresBuild: true 261 | dev: true 262 | optional: true 263 | 264 | /@esbuild/win32-arm64@0.18.20: 265 | resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} 266 | engines: {node: '>=12'} 267 | cpu: [arm64] 268 | os: [win32] 269 | requiresBuild: true 270 | dev: true 271 | optional: true 272 | 273 | /@esbuild/win32-ia32@0.18.20: 274 | resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} 275 | engines: {node: '>=12'} 276 | cpu: [ia32] 277 | os: [win32] 278 | requiresBuild: true 279 | dev: true 280 | optional: true 281 | 282 | /@esbuild/win32-x64@0.18.20: 283 | resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} 284 | engines: {node: '>=12'} 285 | cpu: [x64] 286 | os: [win32] 287 | requiresBuild: true 288 | dev: true 289 | optional: true 290 | 291 | /@eslint-community/eslint-utils@4.4.0(eslint@8.51.0): 292 | resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} 293 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 294 | peerDependencies: 295 | eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 296 | dependencies: 297 | eslint: 8.51.0 298 | eslint-visitor-keys: 3.4.3 299 | dev: true 300 | 301 | /@eslint-community/regexpp@4.9.1: 302 | resolution: {integrity: sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==} 303 | engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} 304 | dev: true 305 | 306 | /@eslint/eslintrc@2.1.2: 307 | resolution: {integrity: sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==} 308 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 309 | dependencies: 310 | ajv: 6.12.6 311 | debug: 4.3.4 312 | espree: 9.6.1 313 | globals: 13.23.0 314 | ignore: 5.2.4 315 | import-fresh: 3.3.0 316 | js-yaml: 4.1.0 317 | minimatch: 3.1.2 318 | strip-json-comments: 3.1.1 319 | transitivePeerDependencies: 320 | - supports-color 321 | dev: true 322 | 323 | /@eslint/js@8.51.0: 324 | resolution: {integrity: sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==} 325 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 326 | dev: true 327 | 328 | /@humanwhocodes/config-array@0.11.11: 329 | resolution: {integrity: sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==} 330 | engines: {node: '>=10.10.0'} 331 | dependencies: 332 | '@humanwhocodes/object-schema': 1.2.1 333 | debug: 4.3.4 334 | minimatch: 3.1.2 335 | transitivePeerDependencies: 336 | - supports-color 337 | dev: true 338 | 339 | /@humanwhocodes/module-importer@1.0.1: 340 | resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} 341 | engines: {node: '>=12.22'} 342 | dev: true 343 | 344 | /@humanwhocodes/object-schema@1.2.1: 345 | resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} 346 | dev: true 347 | 348 | /@microsoft/api-extractor-model@7.28.2: 349 | resolution: {integrity: sha512-vkojrM2fo3q4n4oPh4uUZdjJ2DxQ2+RnDQL/xhTWSRUNPF6P4QyrvY357HBxbnltKcYu+nNNolVqc6TIGQ73Ig==} 350 | dependencies: 351 | '@microsoft/tsdoc': 0.14.2 352 | '@microsoft/tsdoc-config': 0.16.2 353 | '@rushstack/node-core-library': 3.61.0 354 | transitivePeerDependencies: 355 | - '@types/node' 356 | dev: true 357 | 358 | /@microsoft/api-extractor@7.38.0: 359 | resolution: {integrity: sha512-e1LhZYnfw+JEebuY2bzhw0imDCl1nwjSThTrQqBXl40hrVo6xm3j/1EpUr89QyzgjqmAwek2ZkIVZbrhaR+cqg==} 360 | hasBin: true 361 | dependencies: 362 | '@microsoft/api-extractor-model': 7.28.2 363 | '@microsoft/tsdoc': 0.14.2 364 | '@microsoft/tsdoc-config': 0.16.2 365 | '@rushstack/node-core-library': 3.61.0 366 | '@rushstack/rig-package': 0.5.1 367 | '@rushstack/ts-command-line': 4.16.1 368 | colors: 1.2.5 369 | lodash: 4.17.21 370 | resolve: 1.22.8 371 | semver: 7.5.4 372 | source-map: 0.6.1 373 | typescript: 5.0.4 374 | transitivePeerDependencies: 375 | - '@types/node' 376 | dev: true 377 | 378 | /@microsoft/tsdoc-config@0.16.2: 379 | resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} 380 | dependencies: 381 | '@microsoft/tsdoc': 0.14.2 382 | ajv: 6.12.6 383 | jju: 1.4.0 384 | resolve: 1.19.0 385 | dev: true 386 | 387 | /@microsoft/tsdoc@0.14.2: 388 | resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} 389 | dev: true 390 | 391 | /@nodelib/fs.scandir@2.1.5: 392 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 393 | engines: {node: '>= 8'} 394 | dependencies: 395 | '@nodelib/fs.stat': 2.0.5 396 | run-parallel: 1.2.0 397 | dev: true 398 | 399 | /@nodelib/fs.stat@2.0.5: 400 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 401 | engines: {node: '>= 8'} 402 | dev: true 403 | 404 | /@nodelib/fs.walk@1.2.8: 405 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 406 | engines: {node: '>= 8'} 407 | dependencies: 408 | '@nodelib/fs.scandir': 2.1.5 409 | fastq: 1.15.0 410 | dev: true 411 | 412 | /@rollup/pluginutils@5.0.5: 413 | resolution: {integrity: sha512-6aEYR910NyP73oHiJglti74iRyOwgFU4x3meH/H8OJx6Ry0j6cOVZ5X/wTvub7G7Ao6qaHBEaNsV3GLJkSsF+Q==} 414 | engines: {node: '>=14.0.0'} 415 | peerDependencies: 416 | rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 417 | peerDependenciesMeta: 418 | rollup: 419 | optional: true 420 | dependencies: 421 | '@types/estree': 1.0.2 422 | estree-walker: 2.0.2 423 | picomatch: 2.3.1 424 | dev: true 425 | 426 | /@rushstack/node-core-library@3.61.0: 427 | resolution: {integrity: sha512-tdOjdErme+/YOu4gPed3sFS72GhtWCgNV9oDsHDnoLY5oDfwjKUc9Z+JOZZ37uAxcm/OCahDHfuu2ugqrfWAVQ==} 428 | peerDependencies: 429 | '@types/node': '*' 430 | peerDependenciesMeta: 431 | '@types/node': 432 | optional: true 433 | dependencies: 434 | colors: 1.2.5 435 | fs-extra: 7.0.1 436 | import-lazy: 4.0.0 437 | jju: 1.4.0 438 | resolve: 1.22.8 439 | semver: 7.5.4 440 | z-schema: 5.0.5 441 | dev: true 442 | 443 | /@rushstack/rig-package@0.5.1: 444 | resolution: {integrity: sha512-pXRYSe29TjRw7rqxD4WS3HN/sRSbfr+tJs4a9uuaSIBAITbUggygdhuG0VrO0EO+QqH91GhYMN4S6KRtOEmGVA==} 445 | dependencies: 446 | resolve: 1.22.8 447 | strip-json-comments: 3.1.1 448 | dev: true 449 | 450 | /@rushstack/ts-command-line@4.16.1: 451 | resolution: {integrity: sha512-+OCsD553GYVLEmz12yiFjMOzuPeCiZ3f8wTiFHL30ZVXexTyPmgjwXEhg2K2P0a2lVf+8YBy7WtPoflB2Fp8/A==} 452 | dependencies: 453 | '@types/argparse': 1.0.38 454 | argparse: 1.0.10 455 | colors: 1.2.5 456 | string-argv: 0.3.2 457 | dev: true 458 | 459 | /@swc/core-darwin-arm64@1.3.92: 460 | resolution: {integrity: sha512-v7PqZUBtIF6Q5Cp48gqUiG8zQQnEICpnfNdoiY3xjQAglCGIQCjJIDjreZBoeZQZspB27lQN4eZ43CX18+2SnA==} 461 | engines: {node: '>=10'} 462 | cpu: [arm64] 463 | os: [darwin] 464 | requiresBuild: true 465 | dev: true 466 | optional: true 467 | 468 | /@swc/core-darwin-x64@1.3.92: 469 | resolution: {integrity: sha512-Q3XIgQfXyxxxms3bPN+xGgvwk0TtG9l89IomApu+yTKzaIIlf051mS+lGngjnh9L0aUiCp6ICyjDLtutWP54fw==} 470 | engines: {node: '>=10'} 471 | cpu: [x64] 472 | os: [darwin] 473 | requiresBuild: true 474 | dev: true 475 | optional: true 476 | 477 | /@swc/core-linux-arm-gnueabihf@1.3.92: 478 | resolution: {integrity: sha512-tnOCoCpNVXC+0FCfG84PBZJyLlz0Vfj9MQhyhCvlJz9hQmvpf8nTdKH7RHrOn8VfxtUBLdVi80dXgIFgbvl7qA==} 479 | engines: {node: '>=10'} 480 | cpu: [arm] 481 | os: [linux] 482 | requiresBuild: true 483 | dev: true 484 | optional: true 485 | 486 | /@swc/core-linux-arm64-gnu@1.3.92: 487 | resolution: {integrity: sha512-lFfGhX32w8h1j74Iyz0Wv7JByXIwX11OE9UxG+oT7lG0RyXkF4zKyxP8EoxfLrDXse4Oop434p95e3UNC3IfCw==} 488 | engines: {node: '>=10'} 489 | cpu: [arm64] 490 | os: [linux] 491 | requiresBuild: true 492 | dev: true 493 | optional: true 494 | 495 | /@swc/core-linux-arm64-musl@1.3.92: 496 | resolution: {integrity: sha512-rOZtRcLj57MSAbiecMsqjzBcZDuaCZ8F6l6JDwGkQ7u1NYR57cqF0QDyU7RKS1Jq27Z/Vg21z5cwqoH5fLN+Sg==} 497 | engines: {node: '>=10'} 498 | cpu: [arm64] 499 | os: [linux] 500 | requiresBuild: true 501 | dev: true 502 | optional: true 503 | 504 | /@swc/core-linux-x64-gnu@1.3.92: 505 | resolution: {integrity: sha512-qptoMGnBL6v89x/Qpn+l1TH1Y0ed+v0qhNfAEVzZvCvzEMTFXphhlhYbDdpxbzRmCjH6GOGq7Y+xrWt9T1/ARg==} 506 | engines: {node: '>=10'} 507 | cpu: [x64] 508 | os: [linux] 509 | requiresBuild: true 510 | dev: true 511 | optional: true 512 | 513 | /@swc/core-linux-x64-musl@1.3.92: 514 | resolution: {integrity: sha512-g2KrJ43bZkCZHH4zsIV5ErojuV1OIpUHaEyW1gf7JWKaFBpWYVyubzFPvPkjcxHGLbMsEzO7w/NVfxtGMlFH/Q==} 515 | engines: {node: '>=10'} 516 | cpu: [x64] 517 | os: [linux] 518 | requiresBuild: true 519 | dev: true 520 | optional: true 521 | 522 | /@swc/core-win32-arm64-msvc@1.3.92: 523 | resolution: {integrity: sha512-3MCRGPAYDoQ8Yyd3WsCMc8eFSyKXY5kQLyg/R5zEqA0uthomo0m0F5/fxAJMZGaSdYkU1DgF73ctOWOf+Z/EzQ==} 524 | engines: {node: '>=10'} 525 | cpu: [arm64] 526 | os: [win32] 527 | requiresBuild: true 528 | dev: true 529 | optional: true 530 | 531 | /@swc/core-win32-ia32-msvc@1.3.92: 532 | resolution: {integrity: sha512-zqTBKQhgfWm73SVGS8FKhFYDovyRl1f5dTX1IwSKynO0qHkRCqJwauFJv/yevkpJWsI2pFh03xsRs9HncTQKSA==} 533 | engines: {node: '>=10'} 534 | cpu: [ia32] 535 | os: [win32] 536 | requiresBuild: true 537 | dev: true 538 | optional: true 539 | 540 | /@swc/core-win32-x64-msvc@1.3.92: 541 | resolution: {integrity: sha512-41bE66ddr9o/Fi1FBh0sHdaKdENPTuDpv1IFHxSg0dJyM/jX8LbkjnpdInYXHBxhcLVAPraVRrNsC4SaoPw2Pg==} 542 | engines: {node: '>=10'} 543 | cpu: [x64] 544 | os: [win32] 545 | requiresBuild: true 546 | dev: true 547 | optional: true 548 | 549 | /@swc/core@1.3.92: 550 | resolution: {integrity: sha512-vx0vUrf4YTEw59njOJ46Ha5i0cZTMYdRHQ7KXU29efN1MxcmJH2RajWLPlvQarOP1ab9iv9cApD7SMchDyx2vA==} 551 | engines: {node: '>=10'} 552 | requiresBuild: true 553 | peerDependencies: 554 | '@swc/helpers': ^0.5.0 555 | peerDependenciesMeta: 556 | '@swc/helpers': 557 | optional: true 558 | dependencies: 559 | '@swc/counter': 0.1.2 560 | '@swc/types': 0.1.5 561 | optionalDependencies: 562 | '@swc/core-darwin-arm64': 1.3.92 563 | '@swc/core-darwin-x64': 1.3.92 564 | '@swc/core-linux-arm-gnueabihf': 1.3.92 565 | '@swc/core-linux-arm64-gnu': 1.3.92 566 | '@swc/core-linux-arm64-musl': 1.3.92 567 | '@swc/core-linux-x64-gnu': 1.3.92 568 | '@swc/core-linux-x64-musl': 1.3.92 569 | '@swc/core-win32-arm64-msvc': 1.3.92 570 | '@swc/core-win32-ia32-msvc': 1.3.92 571 | '@swc/core-win32-x64-msvc': 1.3.92 572 | dev: true 573 | 574 | /@swc/counter@0.1.2: 575 | resolution: {integrity: sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==} 576 | dev: true 577 | 578 | /@swc/types@0.1.5: 579 | resolution: {integrity: sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==} 580 | dev: true 581 | 582 | /@types/argparse@1.0.38: 583 | resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} 584 | dev: true 585 | 586 | /@types/estree@1.0.2: 587 | resolution: {integrity: sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==} 588 | dev: true 589 | 590 | /@types/json-schema@7.0.13: 591 | resolution: {integrity: sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==} 592 | dev: true 593 | 594 | /@types/prop-types@15.7.8: 595 | resolution: {integrity: sha512-kMpQpfZKSCBqltAJwskgePRaYRFukDkm1oItcAbC3gNELR20XIBcN9VRgg4+m8DKsTfkWeA4m4Imp4DDuWy7FQ==} 596 | dev: true 597 | 598 | /@types/react-dom@18.2.13: 599 | resolution: {integrity: sha512-eJIUv7rPP+EC45uNYp/ThhSpE16k22VJUknt5OLoH9tbXoi8bMhwLf5xRuWMywamNbWzhrSmU7IBJfPup1+3fw==} 600 | dependencies: 601 | '@types/react': 18.2.28 602 | dev: true 603 | 604 | /@types/react@18.2.28: 605 | resolution: {integrity: sha512-ad4aa/RaaJS3hyGz0BGegdnSRXQBkd1CCYDCdNjBPg90UUpLgo+WlJqb9fMYUxtehmzF3PJaTWqRZjko6BRzBg==} 606 | dependencies: 607 | '@types/prop-types': 15.7.8 608 | '@types/scheduler': 0.16.4 609 | csstype: 3.1.2 610 | dev: true 611 | 612 | /@types/scheduler@0.16.4: 613 | resolution: {integrity: sha512-2L9ifAGl7wmXwP4v3pN4p2FLhD0O1qsJpvKmNin5VA8+UvNVb447UDaAEV6UdrkA+m/Xs58U1RFps44x6TFsVQ==} 614 | dev: true 615 | 616 | /@types/semver@7.5.3: 617 | resolution: {integrity: sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==} 618 | dev: true 619 | 620 | /@types/uniqid@5.3.2: 621 | resolution: {integrity: sha512-/NYoaZpWsnAJDsGYeMNDeG3p3fuUb4AiC7MfKxi5VSu18tXd08w6Ch0fKW94T4FeLXXZwZPoFgHA1O0rDYKyMQ==} 622 | dev: true 623 | 624 | /@types/webmidi@2.0.8: 625 | resolution: {integrity: sha512-GMwIMYwLNpevZfcBeNrwavlbqY33SVfZdvQYfIAGtUFZnDZnDcMIN9s52Ksz341ylGUszOcAKlXUfz3QBOaA+w==} 626 | dev: true 627 | 628 | /@typescript-eslint/eslint-plugin@6.7.5(@typescript-eslint/parser@6.7.5)(eslint@8.51.0)(typescript@5.2.2): 629 | resolution: {integrity: sha512-JhtAwTRhOUcP96D0Y6KYnwig/MRQbOoLGXTON2+LlyB/N35SP9j1boai2zzwXb7ypKELXMx3DVk9UTaEq1vHEw==} 630 | engines: {node: ^16.0.0 || >=18.0.0} 631 | peerDependencies: 632 | '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha 633 | eslint: ^7.0.0 || ^8.0.0 634 | typescript: '*' 635 | peerDependenciesMeta: 636 | typescript: 637 | optional: true 638 | dependencies: 639 | '@eslint-community/regexpp': 4.9.1 640 | '@typescript-eslint/parser': 6.7.5(eslint@8.51.0)(typescript@5.2.2) 641 | '@typescript-eslint/scope-manager': 6.7.5 642 | '@typescript-eslint/type-utils': 6.7.5(eslint@8.51.0)(typescript@5.2.2) 643 | '@typescript-eslint/utils': 6.7.5(eslint@8.51.0)(typescript@5.2.2) 644 | '@typescript-eslint/visitor-keys': 6.7.5 645 | debug: 4.3.4 646 | eslint: 8.51.0 647 | graphemer: 1.4.0 648 | ignore: 5.2.4 649 | natural-compare: 1.4.0 650 | semver: 7.5.4 651 | ts-api-utils: 1.0.3(typescript@5.2.2) 652 | typescript: 5.2.2 653 | transitivePeerDependencies: 654 | - supports-color 655 | dev: true 656 | 657 | /@typescript-eslint/parser@6.7.5(eslint@8.51.0)(typescript@5.2.2): 658 | resolution: {integrity: sha512-bIZVSGx2UME/lmhLcjdVc7ePBwn7CLqKarUBL4me1C5feOd663liTGjMBGVcGr+BhnSLeP4SgwdvNnnkbIdkCw==} 659 | engines: {node: ^16.0.0 || >=18.0.0} 660 | peerDependencies: 661 | eslint: ^7.0.0 || ^8.0.0 662 | typescript: '*' 663 | peerDependenciesMeta: 664 | typescript: 665 | optional: true 666 | dependencies: 667 | '@typescript-eslint/scope-manager': 6.7.5 668 | '@typescript-eslint/types': 6.7.5 669 | '@typescript-eslint/typescript-estree': 6.7.5(typescript@5.2.2) 670 | '@typescript-eslint/visitor-keys': 6.7.5 671 | debug: 4.3.4 672 | eslint: 8.51.0 673 | typescript: 5.2.2 674 | transitivePeerDependencies: 675 | - supports-color 676 | dev: true 677 | 678 | /@typescript-eslint/scope-manager@6.7.5: 679 | resolution: {integrity: sha512-GAlk3eQIwWOJeb9F7MKQ6Jbah/vx1zETSDw8likab/eFcqkjSD7BI75SDAeC5N2L0MmConMoPvTsmkrg71+B1A==} 680 | engines: {node: ^16.0.0 || >=18.0.0} 681 | dependencies: 682 | '@typescript-eslint/types': 6.7.5 683 | '@typescript-eslint/visitor-keys': 6.7.5 684 | dev: true 685 | 686 | /@typescript-eslint/type-utils@6.7.5(eslint@8.51.0)(typescript@5.2.2): 687 | resolution: {integrity: sha512-Gs0qos5wqxnQrvpYv+pf3XfcRXW6jiAn9zE/K+DlmYf6FcpxeNYN0AIETaPR7rHO4K2UY+D0CIbDP9Ut0U4m1g==} 688 | engines: {node: ^16.0.0 || >=18.0.0} 689 | peerDependencies: 690 | eslint: ^7.0.0 || ^8.0.0 691 | typescript: '*' 692 | peerDependenciesMeta: 693 | typescript: 694 | optional: true 695 | dependencies: 696 | '@typescript-eslint/typescript-estree': 6.7.5(typescript@5.2.2) 697 | '@typescript-eslint/utils': 6.7.5(eslint@8.51.0)(typescript@5.2.2) 698 | debug: 4.3.4 699 | eslint: 8.51.0 700 | ts-api-utils: 1.0.3(typescript@5.2.2) 701 | typescript: 5.2.2 702 | transitivePeerDependencies: 703 | - supports-color 704 | dev: true 705 | 706 | /@typescript-eslint/types@6.7.5: 707 | resolution: {integrity: sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==} 708 | engines: {node: ^16.0.0 || >=18.0.0} 709 | dev: true 710 | 711 | /@typescript-eslint/typescript-estree@6.7.5(typescript@5.2.2): 712 | resolution: {integrity: sha512-NhJiJ4KdtwBIxrKl0BqG1Ur+uw7FiOnOThcYx9DpOGJ/Abc9z2xNzLeirCG02Ig3vkvrc2qFLmYSSsaITbKjlg==} 713 | engines: {node: ^16.0.0 || >=18.0.0} 714 | peerDependencies: 715 | typescript: '*' 716 | peerDependenciesMeta: 717 | typescript: 718 | optional: true 719 | dependencies: 720 | '@typescript-eslint/types': 6.7.5 721 | '@typescript-eslint/visitor-keys': 6.7.5 722 | debug: 4.3.4 723 | globby: 11.1.0 724 | is-glob: 4.0.3 725 | semver: 7.5.4 726 | ts-api-utils: 1.0.3(typescript@5.2.2) 727 | typescript: 5.2.2 728 | transitivePeerDependencies: 729 | - supports-color 730 | dev: true 731 | 732 | /@typescript-eslint/utils@6.7.5(eslint@8.51.0)(typescript@5.2.2): 733 | resolution: {integrity: sha512-pfRRrH20thJbzPPlPc4j0UNGvH1PjPlhlCMq4Yx7EGjV7lvEeGX0U6MJYe8+SyFutWgSHsdbJ3BXzZccYggezA==} 734 | engines: {node: ^16.0.0 || >=18.0.0} 735 | peerDependencies: 736 | eslint: ^7.0.0 || ^8.0.0 737 | dependencies: 738 | '@eslint-community/eslint-utils': 4.4.0(eslint@8.51.0) 739 | '@types/json-schema': 7.0.13 740 | '@types/semver': 7.5.3 741 | '@typescript-eslint/scope-manager': 6.7.5 742 | '@typescript-eslint/types': 6.7.5 743 | '@typescript-eslint/typescript-estree': 6.7.5(typescript@5.2.2) 744 | eslint: 8.51.0 745 | semver: 7.5.4 746 | transitivePeerDependencies: 747 | - supports-color 748 | - typescript 749 | dev: true 750 | 751 | /@typescript-eslint/visitor-keys@6.7.5: 752 | resolution: {integrity: sha512-3MaWdDZtLlsexZzDSdQWsFQ9l9nL8B80Z4fImSpyllFC/KLqWQRdEcB+gGGO+N3Q2uL40EsG66wZLsohPxNXvg==} 753 | engines: {node: ^16.0.0 || >=18.0.0} 754 | dependencies: 755 | '@typescript-eslint/types': 6.7.5 756 | eslint-visitor-keys: 3.4.3 757 | dev: true 758 | 759 | /@vitejs/plugin-react-swc@3.4.0(vite@4.4.11): 760 | resolution: {integrity: sha512-m7UaA4Uvz82N/0EOVpZL4XsFIakRqrFKeSNxa1FBLSXGvWrWRBwmZb4qxk+ZIVAZcW3c3dn5YosomDgx62XWcQ==} 761 | peerDependencies: 762 | vite: ^4 763 | dependencies: 764 | '@swc/core': 1.3.92 765 | vite: 4.4.11 766 | transitivePeerDependencies: 767 | - '@swc/helpers' 768 | dev: true 769 | 770 | /@volar/language-core@1.10.4: 771 | resolution: {integrity: sha512-Na69qA6uwVIdA0rHuOc2W3pHtVQQO8hCNim7FOaKNpRJh0oAFnu5r9i7Oopo5C4cnELZkPNjTrbmpcCTiW+CMQ==} 772 | dependencies: 773 | '@volar/source-map': 1.10.4 774 | dev: true 775 | 776 | /@volar/source-map@1.10.4: 777 | resolution: {integrity: sha512-RxZdUEL+pV8p+SMqnhVjzy5zpb1QRZTlcwSk4bdcBO7yOu4rtEWqDGahVCEj4CcXour+0yJUMrMczfSCpP9Uxg==} 778 | dependencies: 779 | muggle-string: 0.3.1 780 | dev: true 781 | 782 | /@volar/typescript@1.10.4: 783 | resolution: {integrity: sha512-BCCUEBASBEMCrz7qmNSi2hBEWYsXD0doaktRKpmmhvb6XntM2sAWYu6gbyK/MluLDgluGLFiFRpWgobgzUqolg==} 784 | dependencies: 785 | '@volar/language-core': 1.10.4 786 | dev: true 787 | 788 | /@vue/compiler-core@3.3.4: 789 | resolution: {integrity: sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==} 790 | dependencies: 791 | '@babel/parser': 7.23.0 792 | '@vue/shared': 3.3.4 793 | estree-walker: 2.0.2 794 | source-map-js: 1.0.2 795 | dev: true 796 | 797 | /@vue/compiler-dom@3.3.4: 798 | resolution: {integrity: sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==} 799 | dependencies: 800 | '@vue/compiler-core': 3.3.4 801 | '@vue/shared': 3.3.4 802 | dev: true 803 | 804 | /@vue/language-core@1.8.19(typescript@5.2.2): 805 | resolution: {integrity: sha512-nt3dodGs97UM6fnxeQBazO50yYCKBK53waFWB3qMbLmR6eL3aUryZgQtZoBe1pye17Wl8fs9HysV3si6xMgndQ==} 806 | peerDependencies: 807 | typescript: '*' 808 | peerDependenciesMeta: 809 | typescript: 810 | optional: true 811 | dependencies: 812 | '@volar/language-core': 1.10.4 813 | '@volar/source-map': 1.10.4 814 | '@vue/compiler-dom': 3.3.4 815 | '@vue/reactivity': 3.3.4 816 | '@vue/shared': 3.3.4 817 | minimatch: 9.0.3 818 | muggle-string: 0.3.1 819 | typescript: 5.2.2 820 | vue-template-compiler: 2.7.14 821 | dev: true 822 | 823 | /@vue/reactivity@3.3.4: 824 | resolution: {integrity: sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==} 825 | dependencies: 826 | '@vue/shared': 3.3.4 827 | dev: true 828 | 829 | /@vue/shared@3.3.4: 830 | resolution: {integrity: sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==} 831 | dev: true 832 | 833 | /@vue/typescript@1.8.19(typescript@5.2.2): 834 | resolution: {integrity: sha512-k/SHeeQROUgqsxyHQ8Cs3Zz5TnX57p7BcBDVYR2E0c61QL2DJ2G8CsaBremmNGuGE6o1R5D50IHIxFmroMz8iw==} 835 | dependencies: 836 | '@volar/typescript': 1.10.4 837 | '@vue/language-core': 1.8.19(typescript@5.2.2) 838 | transitivePeerDependencies: 839 | - typescript 840 | dev: true 841 | 842 | /acorn-jsx@5.3.2(acorn@8.10.0): 843 | resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} 844 | peerDependencies: 845 | acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 846 | dependencies: 847 | acorn: 8.10.0 848 | dev: true 849 | 850 | /acorn@8.10.0: 851 | resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} 852 | engines: {node: '>=0.4.0'} 853 | hasBin: true 854 | dev: true 855 | 856 | /ajv@6.12.6: 857 | resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} 858 | dependencies: 859 | fast-deep-equal: 3.1.3 860 | fast-json-stable-stringify: 2.1.0 861 | json-schema-traverse: 0.4.1 862 | uri-js: 4.4.1 863 | dev: true 864 | 865 | /ansi-regex@5.0.1: 866 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 867 | engines: {node: '>=8'} 868 | dev: true 869 | 870 | /ansi-styles@4.3.0: 871 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 872 | engines: {node: '>=8'} 873 | dependencies: 874 | color-convert: 2.0.1 875 | dev: true 876 | 877 | /argparse@1.0.10: 878 | resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} 879 | dependencies: 880 | sprintf-js: 1.0.3 881 | dev: true 882 | 883 | /argparse@2.0.1: 884 | resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 885 | dev: true 886 | 887 | /array-union@2.1.0: 888 | resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} 889 | engines: {node: '>=8'} 890 | dev: true 891 | 892 | /balanced-match@1.0.2: 893 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 894 | dev: true 895 | 896 | /brace-expansion@1.1.11: 897 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} 898 | dependencies: 899 | balanced-match: 1.0.2 900 | concat-map: 0.0.1 901 | dev: true 902 | 903 | /brace-expansion@2.0.1: 904 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 905 | dependencies: 906 | balanced-match: 1.0.2 907 | dev: true 908 | 909 | /braces@3.0.2: 910 | resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} 911 | engines: {node: '>=8'} 912 | dependencies: 913 | fill-range: 7.0.1 914 | dev: true 915 | 916 | /callsites@3.1.0: 917 | resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} 918 | engines: {node: '>=6'} 919 | dev: true 920 | 921 | /chalk@4.1.2: 922 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 923 | engines: {node: '>=10'} 924 | dependencies: 925 | ansi-styles: 4.3.0 926 | supports-color: 7.2.0 927 | dev: true 928 | 929 | /color-convert@2.0.1: 930 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 931 | engines: {node: '>=7.0.0'} 932 | dependencies: 933 | color-name: 1.1.4 934 | dev: true 935 | 936 | /color-name@1.1.4: 937 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 938 | dev: true 939 | 940 | /colors@1.2.5: 941 | resolution: {integrity: sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==} 942 | engines: {node: '>=0.1.90'} 943 | dev: true 944 | 945 | /commander@9.5.0: 946 | resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} 947 | engines: {node: ^12.20.0 || >=14} 948 | requiresBuild: true 949 | dev: true 950 | optional: true 951 | 952 | /concat-map@0.0.1: 953 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 954 | dev: true 955 | 956 | /cross-spawn@7.0.3: 957 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} 958 | engines: {node: '>= 8'} 959 | dependencies: 960 | path-key: 3.1.1 961 | shebang-command: 2.0.0 962 | which: 2.0.2 963 | dev: true 964 | 965 | /csstype@3.1.2: 966 | resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} 967 | dev: true 968 | 969 | /de-indent@1.0.2: 970 | resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} 971 | dev: true 972 | 973 | /debug@4.3.4: 974 | resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} 975 | engines: {node: '>=6.0'} 976 | peerDependencies: 977 | supports-color: '*' 978 | peerDependenciesMeta: 979 | supports-color: 980 | optional: true 981 | dependencies: 982 | ms: 2.1.2 983 | dev: true 984 | 985 | /deep-is@0.1.4: 986 | resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} 987 | dev: true 988 | 989 | /dir-glob@3.0.1: 990 | resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} 991 | engines: {node: '>=8'} 992 | dependencies: 993 | path-type: 4.0.0 994 | dev: true 995 | 996 | /doctrine@3.0.0: 997 | resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} 998 | engines: {node: '>=6.0.0'} 999 | dependencies: 1000 | esutils: 2.0.3 1001 | dev: true 1002 | 1003 | /esbuild@0.18.20: 1004 | resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} 1005 | engines: {node: '>=12'} 1006 | hasBin: true 1007 | requiresBuild: true 1008 | optionalDependencies: 1009 | '@esbuild/android-arm': 0.18.20 1010 | '@esbuild/android-arm64': 0.18.20 1011 | '@esbuild/android-x64': 0.18.20 1012 | '@esbuild/darwin-arm64': 0.18.20 1013 | '@esbuild/darwin-x64': 0.18.20 1014 | '@esbuild/freebsd-arm64': 0.18.20 1015 | '@esbuild/freebsd-x64': 0.18.20 1016 | '@esbuild/linux-arm': 0.18.20 1017 | '@esbuild/linux-arm64': 0.18.20 1018 | '@esbuild/linux-ia32': 0.18.20 1019 | '@esbuild/linux-loong64': 0.18.20 1020 | '@esbuild/linux-mips64el': 0.18.20 1021 | '@esbuild/linux-ppc64': 0.18.20 1022 | '@esbuild/linux-riscv64': 0.18.20 1023 | '@esbuild/linux-s390x': 0.18.20 1024 | '@esbuild/linux-x64': 0.18.20 1025 | '@esbuild/netbsd-x64': 0.18.20 1026 | '@esbuild/openbsd-x64': 0.18.20 1027 | '@esbuild/sunos-x64': 0.18.20 1028 | '@esbuild/win32-arm64': 0.18.20 1029 | '@esbuild/win32-ia32': 0.18.20 1030 | '@esbuild/win32-x64': 0.18.20 1031 | dev: true 1032 | 1033 | /escape-string-regexp@4.0.0: 1034 | resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} 1035 | engines: {node: '>=10'} 1036 | dev: true 1037 | 1038 | /eslint-plugin-react-hooks@4.6.0(eslint@8.51.0): 1039 | resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} 1040 | engines: {node: '>=10'} 1041 | peerDependencies: 1042 | eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 1043 | dependencies: 1044 | eslint: 8.51.0 1045 | dev: true 1046 | 1047 | /eslint-plugin-react-refresh@0.4.3(eslint@8.51.0): 1048 | resolution: {integrity: sha512-Hh0wv8bUNY877+sI0BlCUlsS0TYYQqvzEwJsJJPM2WF4RnTStSnSR3zdJYa2nPOJgg3UghXi54lVyMSmpCalzA==} 1049 | peerDependencies: 1050 | eslint: '>=7' 1051 | dependencies: 1052 | eslint: 8.51.0 1053 | dev: true 1054 | 1055 | /eslint-scope@7.2.2: 1056 | resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} 1057 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1058 | dependencies: 1059 | esrecurse: 4.3.0 1060 | estraverse: 5.3.0 1061 | dev: true 1062 | 1063 | /eslint-visitor-keys@3.4.3: 1064 | resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} 1065 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1066 | dev: true 1067 | 1068 | /eslint@8.51.0: 1069 | resolution: {integrity: sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==} 1070 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1071 | hasBin: true 1072 | dependencies: 1073 | '@eslint-community/eslint-utils': 4.4.0(eslint@8.51.0) 1074 | '@eslint-community/regexpp': 4.9.1 1075 | '@eslint/eslintrc': 2.1.2 1076 | '@eslint/js': 8.51.0 1077 | '@humanwhocodes/config-array': 0.11.11 1078 | '@humanwhocodes/module-importer': 1.0.1 1079 | '@nodelib/fs.walk': 1.2.8 1080 | ajv: 6.12.6 1081 | chalk: 4.1.2 1082 | cross-spawn: 7.0.3 1083 | debug: 4.3.4 1084 | doctrine: 3.0.0 1085 | escape-string-regexp: 4.0.0 1086 | eslint-scope: 7.2.2 1087 | eslint-visitor-keys: 3.4.3 1088 | espree: 9.6.1 1089 | esquery: 1.5.0 1090 | esutils: 2.0.3 1091 | fast-deep-equal: 3.1.3 1092 | file-entry-cache: 6.0.1 1093 | find-up: 5.0.0 1094 | glob-parent: 6.0.2 1095 | globals: 13.23.0 1096 | graphemer: 1.4.0 1097 | ignore: 5.2.4 1098 | imurmurhash: 0.1.4 1099 | is-glob: 4.0.3 1100 | is-path-inside: 3.0.3 1101 | js-yaml: 4.1.0 1102 | json-stable-stringify-without-jsonify: 1.0.1 1103 | levn: 0.4.1 1104 | lodash.merge: 4.6.2 1105 | minimatch: 3.1.2 1106 | natural-compare: 1.4.0 1107 | optionator: 0.9.3 1108 | strip-ansi: 6.0.1 1109 | text-table: 0.2.0 1110 | transitivePeerDependencies: 1111 | - supports-color 1112 | dev: true 1113 | 1114 | /espree@9.6.1: 1115 | resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} 1116 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 1117 | dependencies: 1118 | acorn: 8.10.0 1119 | acorn-jsx: 5.3.2(acorn@8.10.0) 1120 | eslint-visitor-keys: 3.4.3 1121 | dev: true 1122 | 1123 | /esquery@1.5.0: 1124 | resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} 1125 | engines: {node: '>=0.10'} 1126 | dependencies: 1127 | estraverse: 5.3.0 1128 | dev: true 1129 | 1130 | /esrecurse@4.3.0: 1131 | resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} 1132 | engines: {node: '>=4.0'} 1133 | dependencies: 1134 | estraverse: 5.3.0 1135 | dev: true 1136 | 1137 | /estraverse@5.3.0: 1138 | resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} 1139 | engines: {node: '>=4.0'} 1140 | dev: true 1141 | 1142 | /estree-walker@2.0.2: 1143 | resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} 1144 | dev: true 1145 | 1146 | /esutils@2.0.3: 1147 | resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} 1148 | engines: {node: '>=0.10.0'} 1149 | dev: true 1150 | 1151 | /fast-deep-equal@3.1.3: 1152 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 1153 | dev: true 1154 | 1155 | /fast-glob@3.3.1: 1156 | resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} 1157 | engines: {node: '>=8.6.0'} 1158 | dependencies: 1159 | '@nodelib/fs.stat': 2.0.5 1160 | '@nodelib/fs.walk': 1.2.8 1161 | glob-parent: 5.1.2 1162 | merge2: 1.4.1 1163 | micromatch: 4.0.5 1164 | dev: true 1165 | 1166 | /fast-json-stable-stringify@2.1.0: 1167 | resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} 1168 | dev: true 1169 | 1170 | /fast-levenshtein@2.0.6: 1171 | resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} 1172 | dev: true 1173 | 1174 | /fastq@1.15.0: 1175 | resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} 1176 | dependencies: 1177 | reusify: 1.0.4 1178 | dev: true 1179 | 1180 | /file-entry-cache@6.0.1: 1181 | resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} 1182 | engines: {node: ^10.12.0 || >=12.0.0} 1183 | dependencies: 1184 | flat-cache: 3.1.1 1185 | dev: true 1186 | 1187 | /fill-range@7.0.1: 1188 | resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} 1189 | engines: {node: '>=8'} 1190 | dependencies: 1191 | to-regex-range: 5.0.1 1192 | dev: true 1193 | 1194 | /find-up@5.0.0: 1195 | resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} 1196 | engines: {node: '>=10'} 1197 | dependencies: 1198 | locate-path: 6.0.0 1199 | path-exists: 4.0.0 1200 | dev: true 1201 | 1202 | /flat-cache@3.1.1: 1203 | resolution: {integrity: sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==} 1204 | engines: {node: '>=12.0.0'} 1205 | dependencies: 1206 | flatted: 3.2.9 1207 | keyv: 4.5.4 1208 | rimraf: 3.0.2 1209 | dev: true 1210 | 1211 | /flatted@3.2.9: 1212 | resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} 1213 | dev: true 1214 | 1215 | /fs-extra@7.0.1: 1216 | resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} 1217 | engines: {node: '>=6 <7 || >=8'} 1218 | dependencies: 1219 | graceful-fs: 4.2.11 1220 | jsonfile: 4.0.0 1221 | universalify: 0.1.2 1222 | dev: true 1223 | 1224 | /fs.realpath@1.0.0: 1225 | resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} 1226 | dev: true 1227 | 1228 | /fsevents@2.3.3: 1229 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 1230 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 1231 | os: [darwin] 1232 | requiresBuild: true 1233 | dev: true 1234 | optional: true 1235 | 1236 | /glob-parent@5.1.2: 1237 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 1238 | engines: {node: '>= 6'} 1239 | dependencies: 1240 | is-glob: 4.0.3 1241 | dev: true 1242 | 1243 | /glob-parent@6.0.2: 1244 | resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} 1245 | engines: {node: '>=10.13.0'} 1246 | dependencies: 1247 | is-glob: 4.0.3 1248 | dev: true 1249 | 1250 | /glob@7.2.3: 1251 | resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} 1252 | dependencies: 1253 | fs.realpath: 1.0.0 1254 | inflight: 1.0.6 1255 | inherits: 2.0.4 1256 | minimatch: 3.1.2 1257 | once: 1.4.0 1258 | path-is-absolute: 1.0.1 1259 | dev: true 1260 | 1261 | /globals@13.23.0: 1262 | resolution: {integrity: sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==} 1263 | engines: {node: '>=8'} 1264 | dependencies: 1265 | type-fest: 0.20.2 1266 | dev: true 1267 | 1268 | /globby@11.1.0: 1269 | resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} 1270 | engines: {node: '>=10'} 1271 | dependencies: 1272 | array-union: 2.1.0 1273 | dir-glob: 3.0.1 1274 | fast-glob: 3.3.1 1275 | ignore: 5.2.4 1276 | merge2: 1.4.1 1277 | slash: 3.0.0 1278 | dev: true 1279 | 1280 | /graceful-fs@4.2.11: 1281 | resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} 1282 | dev: true 1283 | 1284 | /graphemer@1.4.0: 1285 | resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} 1286 | dev: true 1287 | 1288 | /has-flag@4.0.0: 1289 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 1290 | engines: {node: '>=8'} 1291 | dev: true 1292 | 1293 | /has@1.0.4: 1294 | resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==} 1295 | engines: {node: '>= 0.4.0'} 1296 | dev: true 1297 | 1298 | /he@1.2.0: 1299 | resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} 1300 | hasBin: true 1301 | dev: true 1302 | 1303 | /ignore@5.2.4: 1304 | resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} 1305 | engines: {node: '>= 4'} 1306 | dev: true 1307 | 1308 | /import-fresh@3.3.0: 1309 | resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} 1310 | engines: {node: '>=6'} 1311 | dependencies: 1312 | parent-module: 1.0.1 1313 | resolve-from: 4.0.0 1314 | dev: true 1315 | 1316 | /import-lazy@4.0.0: 1317 | resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} 1318 | engines: {node: '>=8'} 1319 | dev: true 1320 | 1321 | /imurmurhash@0.1.4: 1322 | resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} 1323 | engines: {node: '>=0.8.19'} 1324 | dev: true 1325 | 1326 | /inflight@1.0.6: 1327 | resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} 1328 | dependencies: 1329 | once: 1.4.0 1330 | wrappy: 1.0.2 1331 | dev: true 1332 | 1333 | /inherits@2.0.4: 1334 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 1335 | dev: true 1336 | 1337 | /is-core-module@2.13.0: 1338 | resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} 1339 | dependencies: 1340 | has: 1.0.4 1341 | dev: true 1342 | 1343 | /is-extglob@2.1.1: 1344 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 1345 | engines: {node: '>=0.10.0'} 1346 | dev: true 1347 | 1348 | /is-glob@4.0.3: 1349 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 1350 | engines: {node: '>=0.10.0'} 1351 | dependencies: 1352 | is-extglob: 2.1.1 1353 | dev: true 1354 | 1355 | /is-number@7.0.0: 1356 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 1357 | engines: {node: '>=0.12.0'} 1358 | dev: true 1359 | 1360 | /is-path-inside@3.0.3: 1361 | resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} 1362 | engines: {node: '>=8'} 1363 | dev: true 1364 | 1365 | /isexe@2.0.0: 1366 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 1367 | dev: true 1368 | 1369 | /jju@1.4.0: 1370 | resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} 1371 | dev: true 1372 | 1373 | /js-tokens@4.0.0: 1374 | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} 1375 | dev: true 1376 | 1377 | /js-yaml@4.1.0: 1378 | resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} 1379 | hasBin: true 1380 | dependencies: 1381 | argparse: 2.0.1 1382 | dev: true 1383 | 1384 | /json-buffer@3.0.1: 1385 | resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} 1386 | dev: true 1387 | 1388 | /json-schema-traverse@0.4.1: 1389 | resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} 1390 | dev: true 1391 | 1392 | /json-stable-stringify-without-jsonify@1.0.1: 1393 | resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} 1394 | dev: true 1395 | 1396 | /jsonfile@4.0.0: 1397 | resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} 1398 | optionalDependencies: 1399 | graceful-fs: 4.2.11 1400 | dev: true 1401 | 1402 | /keyv@4.5.4: 1403 | resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} 1404 | dependencies: 1405 | json-buffer: 3.0.1 1406 | dev: true 1407 | 1408 | /kolorist@1.8.0: 1409 | resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} 1410 | dev: true 1411 | 1412 | /levn@0.4.1: 1413 | resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} 1414 | engines: {node: '>= 0.8.0'} 1415 | dependencies: 1416 | prelude-ls: 1.2.1 1417 | type-check: 0.4.0 1418 | dev: true 1419 | 1420 | /locate-path@6.0.0: 1421 | resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} 1422 | engines: {node: '>=10'} 1423 | dependencies: 1424 | p-locate: 5.0.0 1425 | dev: true 1426 | 1427 | /lodash.get@4.4.2: 1428 | resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} 1429 | dev: true 1430 | 1431 | /lodash.isequal@4.5.0: 1432 | resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} 1433 | dev: true 1434 | 1435 | /lodash.merge@4.6.2: 1436 | resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} 1437 | dev: true 1438 | 1439 | /lodash@4.17.21: 1440 | resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} 1441 | dev: true 1442 | 1443 | /loose-envify@1.4.0: 1444 | resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} 1445 | hasBin: true 1446 | dependencies: 1447 | js-tokens: 4.0.0 1448 | dev: true 1449 | 1450 | /lru-cache@6.0.0: 1451 | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} 1452 | engines: {node: '>=10'} 1453 | dependencies: 1454 | yallist: 4.0.0 1455 | dev: true 1456 | 1457 | /merge2@1.4.1: 1458 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 1459 | engines: {node: '>= 8'} 1460 | dev: true 1461 | 1462 | /micromatch@4.0.5: 1463 | resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} 1464 | engines: {node: '>=8.6'} 1465 | dependencies: 1466 | braces: 3.0.2 1467 | picomatch: 2.3.1 1468 | dev: true 1469 | 1470 | /minimatch@3.1.2: 1471 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 1472 | dependencies: 1473 | brace-expansion: 1.1.11 1474 | dev: true 1475 | 1476 | /minimatch@9.0.3: 1477 | resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} 1478 | engines: {node: '>=16 || 14 >=14.17'} 1479 | dependencies: 1480 | brace-expansion: 2.0.1 1481 | dev: true 1482 | 1483 | /ms@2.1.2: 1484 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} 1485 | dev: true 1486 | 1487 | /muggle-string@0.3.1: 1488 | resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==} 1489 | dev: true 1490 | 1491 | /nanoid@3.3.6: 1492 | resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} 1493 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 1494 | hasBin: true 1495 | dev: true 1496 | 1497 | /natural-compare@1.4.0: 1498 | resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} 1499 | dev: true 1500 | 1501 | /once@1.4.0: 1502 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} 1503 | dependencies: 1504 | wrappy: 1.0.2 1505 | dev: true 1506 | 1507 | /optionator@0.9.3: 1508 | resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} 1509 | engines: {node: '>= 0.8.0'} 1510 | dependencies: 1511 | '@aashutoshrathi/word-wrap': 1.2.6 1512 | deep-is: 0.1.4 1513 | fast-levenshtein: 2.0.6 1514 | levn: 0.4.1 1515 | prelude-ls: 1.2.1 1516 | type-check: 0.4.0 1517 | dev: true 1518 | 1519 | /p-limit@3.1.0: 1520 | resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} 1521 | engines: {node: '>=10'} 1522 | dependencies: 1523 | yocto-queue: 0.1.0 1524 | dev: true 1525 | 1526 | /p-locate@5.0.0: 1527 | resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} 1528 | engines: {node: '>=10'} 1529 | dependencies: 1530 | p-limit: 3.1.0 1531 | dev: true 1532 | 1533 | /parent-module@1.0.1: 1534 | resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} 1535 | engines: {node: '>=6'} 1536 | dependencies: 1537 | callsites: 3.1.0 1538 | dev: true 1539 | 1540 | /path-exists@4.0.0: 1541 | resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} 1542 | engines: {node: '>=8'} 1543 | dev: true 1544 | 1545 | /path-is-absolute@1.0.1: 1546 | resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} 1547 | engines: {node: '>=0.10.0'} 1548 | dev: true 1549 | 1550 | /path-key@3.1.1: 1551 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1552 | engines: {node: '>=8'} 1553 | dev: true 1554 | 1555 | /path-parse@1.0.7: 1556 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 1557 | dev: true 1558 | 1559 | /path-type@4.0.0: 1560 | resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} 1561 | engines: {node: '>=8'} 1562 | dev: true 1563 | 1564 | /picocolors@1.0.0: 1565 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} 1566 | dev: true 1567 | 1568 | /picomatch@2.3.1: 1569 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1570 | engines: {node: '>=8.6'} 1571 | dev: true 1572 | 1573 | /postcss@8.4.31: 1574 | resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} 1575 | engines: {node: ^10 || ^12 || >=14} 1576 | dependencies: 1577 | nanoid: 3.3.6 1578 | picocolors: 1.0.0 1579 | source-map-js: 1.0.2 1580 | dev: true 1581 | 1582 | /prelude-ls@1.2.1: 1583 | resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} 1584 | engines: {node: '>= 0.8.0'} 1585 | dev: true 1586 | 1587 | /punycode@2.3.0: 1588 | resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} 1589 | engines: {node: '>=6'} 1590 | dev: true 1591 | 1592 | /queue-microtask@1.2.3: 1593 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1594 | dev: true 1595 | 1596 | /react-dom@18.2.0(react@18.2.0): 1597 | resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} 1598 | peerDependencies: 1599 | react: ^18.2.0 1600 | dependencies: 1601 | loose-envify: 1.4.0 1602 | react: 18.2.0 1603 | scheduler: 0.23.0 1604 | dev: true 1605 | 1606 | /react@18.2.0: 1607 | resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} 1608 | engines: {node: '>=0.10.0'} 1609 | dependencies: 1610 | loose-envify: 1.4.0 1611 | dev: true 1612 | 1613 | /resolve-from@4.0.0: 1614 | resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} 1615 | engines: {node: '>=4'} 1616 | dev: true 1617 | 1618 | /resolve@1.19.0: 1619 | resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} 1620 | dependencies: 1621 | is-core-module: 2.13.0 1622 | path-parse: 1.0.7 1623 | dev: true 1624 | 1625 | /resolve@1.22.8: 1626 | resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} 1627 | hasBin: true 1628 | dependencies: 1629 | is-core-module: 2.13.0 1630 | path-parse: 1.0.7 1631 | supports-preserve-symlinks-flag: 1.0.0 1632 | dev: true 1633 | 1634 | /reusify@1.0.4: 1635 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 1636 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 1637 | dev: true 1638 | 1639 | /rimraf@3.0.2: 1640 | resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} 1641 | hasBin: true 1642 | dependencies: 1643 | glob: 7.2.3 1644 | dev: true 1645 | 1646 | /rollup@3.29.4: 1647 | resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==} 1648 | engines: {node: '>=14.18.0', npm: '>=8.0.0'} 1649 | hasBin: true 1650 | optionalDependencies: 1651 | fsevents: 2.3.3 1652 | dev: true 1653 | 1654 | /run-parallel@1.2.0: 1655 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1656 | dependencies: 1657 | queue-microtask: 1.2.3 1658 | dev: true 1659 | 1660 | /scheduler@0.23.0: 1661 | resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} 1662 | dependencies: 1663 | loose-envify: 1.4.0 1664 | dev: true 1665 | 1666 | /semver@7.5.4: 1667 | resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} 1668 | engines: {node: '>=10'} 1669 | hasBin: true 1670 | dependencies: 1671 | lru-cache: 6.0.0 1672 | dev: true 1673 | 1674 | /shebang-command@2.0.0: 1675 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1676 | engines: {node: '>=8'} 1677 | dependencies: 1678 | shebang-regex: 3.0.0 1679 | dev: true 1680 | 1681 | /shebang-regex@3.0.0: 1682 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1683 | engines: {node: '>=8'} 1684 | dev: true 1685 | 1686 | /slash@3.0.0: 1687 | resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} 1688 | engines: {node: '>=8'} 1689 | dev: true 1690 | 1691 | /source-map-js@1.0.2: 1692 | resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} 1693 | engines: {node: '>=0.10.0'} 1694 | dev: true 1695 | 1696 | /source-map@0.6.1: 1697 | resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} 1698 | engines: {node: '>=0.10.0'} 1699 | dev: true 1700 | 1701 | /sprintf-js@1.0.3: 1702 | resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} 1703 | dev: true 1704 | 1705 | /string-argv@0.3.2: 1706 | resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} 1707 | engines: {node: '>=0.6.19'} 1708 | dev: true 1709 | 1710 | /strip-ansi@6.0.1: 1711 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 1712 | engines: {node: '>=8'} 1713 | dependencies: 1714 | ansi-regex: 5.0.1 1715 | dev: true 1716 | 1717 | /strip-json-comments@3.1.1: 1718 | resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} 1719 | engines: {node: '>=8'} 1720 | dev: true 1721 | 1722 | /supports-color@7.2.0: 1723 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 1724 | engines: {node: '>=8'} 1725 | dependencies: 1726 | has-flag: 4.0.0 1727 | dev: true 1728 | 1729 | /supports-preserve-symlinks-flag@1.0.0: 1730 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 1731 | engines: {node: '>= 0.4'} 1732 | dev: true 1733 | 1734 | /text-table@0.2.0: 1735 | resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} 1736 | dev: true 1737 | 1738 | /to-fast-properties@2.0.0: 1739 | resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} 1740 | engines: {node: '>=4'} 1741 | dev: true 1742 | 1743 | /to-regex-range@5.0.1: 1744 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1745 | engines: {node: '>=8.0'} 1746 | dependencies: 1747 | is-number: 7.0.0 1748 | dev: true 1749 | 1750 | /ts-api-utils@1.0.3(typescript@5.2.2): 1751 | resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} 1752 | engines: {node: '>=16.13.0'} 1753 | peerDependencies: 1754 | typescript: '>=4.2.0' 1755 | dependencies: 1756 | typescript: 5.2.2 1757 | dev: true 1758 | 1759 | /type-check@0.4.0: 1760 | resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} 1761 | engines: {node: '>= 0.8.0'} 1762 | dependencies: 1763 | prelude-ls: 1.2.1 1764 | dev: true 1765 | 1766 | /type-fest@0.20.2: 1767 | resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} 1768 | engines: {node: '>=10'} 1769 | dev: true 1770 | 1771 | /typescript@5.0.4: 1772 | resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} 1773 | engines: {node: '>=12.20'} 1774 | hasBin: true 1775 | dev: true 1776 | 1777 | /typescript@5.2.2: 1778 | resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} 1779 | engines: {node: '>=14.17'} 1780 | hasBin: true 1781 | dev: true 1782 | 1783 | /uniqid@5.4.0: 1784 | resolution: {integrity: sha512-38JRbJ4Fj94VmnC7G/J/5n5SC7Ab46OM5iNtSstB/ko3l1b5g7ALt4qzHFgGciFkyiRNtDXtLNb+VsxtMSE77A==} 1785 | dev: false 1786 | 1787 | /universalify@0.1.2: 1788 | resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} 1789 | engines: {node: '>= 4.0.0'} 1790 | dev: true 1791 | 1792 | /uri-js@4.4.1: 1793 | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 1794 | dependencies: 1795 | punycode: 2.3.0 1796 | dev: true 1797 | 1798 | /validator@13.11.0: 1799 | resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==} 1800 | engines: {node: '>= 0.10'} 1801 | dev: true 1802 | 1803 | /vite-plugin-dts@3.6.0(typescript@5.2.2)(vite@4.4.11): 1804 | resolution: {integrity: sha512-doxhDRFJCZD2sGjIp4V800nm8Y19GvmwckjG5vYPuiqJ7OBjc9NlW1Vp9Gkyh2aXlUs1jTDRH/lxWfcsPLOQHg==} 1805 | engines: {node: ^14.18.0 || >=16.0.0} 1806 | peerDependencies: 1807 | typescript: '*' 1808 | vite: '*' 1809 | peerDependenciesMeta: 1810 | vite: 1811 | optional: true 1812 | dependencies: 1813 | '@microsoft/api-extractor': 7.38.0 1814 | '@rollup/pluginutils': 5.0.5 1815 | '@vue/language-core': 1.8.19(typescript@5.2.2) 1816 | debug: 4.3.4 1817 | kolorist: 1.8.0 1818 | typescript: 5.2.2 1819 | vite: 4.4.11 1820 | vue-tsc: 1.8.19(typescript@5.2.2) 1821 | transitivePeerDependencies: 1822 | - '@types/node' 1823 | - rollup 1824 | - supports-color 1825 | dev: true 1826 | 1827 | /vite@4.4.11: 1828 | resolution: {integrity: sha512-ksNZJlkcU9b0lBwAGZGGaZHCMqHsc8OpgtoYhsQ4/I2v5cnpmmmqe5pM4nv/4Hn6G/2GhTdj0DhZh2e+Er1q5A==} 1829 | engines: {node: ^14.18.0 || >=16.0.0} 1830 | hasBin: true 1831 | peerDependencies: 1832 | '@types/node': '>= 14' 1833 | less: '*' 1834 | lightningcss: ^1.21.0 1835 | sass: '*' 1836 | stylus: '*' 1837 | sugarss: '*' 1838 | terser: ^5.4.0 1839 | peerDependenciesMeta: 1840 | '@types/node': 1841 | optional: true 1842 | less: 1843 | optional: true 1844 | lightningcss: 1845 | optional: true 1846 | sass: 1847 | optional: true 1848 | stylus: 1849 | optional: true 1850 | sugarss: 1851 | optional: true 1852 | terser: 1853 | optional: true 1854 | dependencies: 1855 | esbuild: 0.18.20 1856 | postcss: 8.4.31 1857 | rollup: 3.29.4 1858 | optionalDependencies: 1859 | fsevents: 2.3.3 1860 | dev: true 1861 | 1862 | /vue-template-compiler@2.7.14: 1863 | resolution: {integrity: sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==} 1864 | dependencies: 1865 | de-indent: 1.0.2 1866 | he: 1.2.0 1867 | dev: true 1868 | 1869 | /vue-tsc@1.8.19(typescript@5.2.2): 1870 | resolution: {integrity: sha512-tacMQLQ0CXAfbhRycCL5sWIy1qujXaIEtP1hIQpzHWOUuICbtTj9gJyFf91PvzG5KCNIkA5Eg7k2Fmgt28l5DQ==} 1871 | hasBin: true 1872 | peerDependencies: 1873 | typescript: '*' 1874 | dependencies: 1875 | '@vue/language-core': 1.8.19(typescript@5.2.2) 1876 | '@vue/typescript': 1.8.19(typescript@5.2.2) 1877 | semver: 7.5.4 1878 | typescript: 5.2.2 1879 | dev: true 1880 | 1881 | /which@2.0.2: 1882 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 1883 | engines: {node: '>= 8'} 1884 | hasBin: true 1885 | dependencies: 1886 | isexe: 2.0.0 1887 | dev: true 1888 | 1889 | /wrappy@1.0.2: 1890 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 1891 | dev: true 1892 | 1893 | /yallist@4.0.0: 1894 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} 1895 | dev: true 1896 | 1897 | /yocto-queue@0.1.0: 1898 | resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} 1899 | engines: {node: '>=10'} 1900 | dev: true 1901 | 1902 | /z-schema@5.0.5: 1903 | resolution: {integrity: sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==} 1904 | engines: {node: '>=8.0.0'} 1905 | hasBin: true 1906 | dependencies: 1907 | lodash.get: 4.4.2 1908 | lodash.isequal: 4.5.0 1909 | validator: 13.11.0 1910 | optionalDependencies: 1911 | commander: 9.5.0 1912 | dev: true 1913 | --------------------------------------------------------------------------------