@moises.ai/design-system 3.11.2 → 3.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +3540 -3390
- package/package.json +1 -1
- package/src/components/InputLevelMeter/InputLevelMeter.jsx +205 -0
- package/src/components/InputLevelMeter/InputLevelMeter.module.css +111 -0
- package/src/components/InputLevelMeter/InputLevelMeter.stories.jsx +27 -0
- package/src/components/InputLevelMeter/useSimulatedInputLevel.js +33 -0
- package/src/components/TrackHeader/RecordSettingsPopover.jsx +10 -11
- package/src/components/TrackHeader/TrackHeader.jsx +5 -5
- package/src/components/TrackHeader/TrackHeader.stories.jsx +28 -1
- package/src/index.jsx +7 -4
package/package.json
CHANGED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { memo, useCallback, useRef, useState } from 'react'
|
|
2
|
+
import styles from './InputLevelMeter.module.css'
|
|
3
|
+
|
|
4
|
+
const SEGMENT_MIN = 5
|
|
5
|
+
const SEGMENT_RANGE = 25
|
|
6
|
+
const UNITY_GAIN_POS = 0.667
|
|
7
|
+
const MAX_BOOST_DB = 6
|
|
8
|
+
|
|
9
|
+
function linearToMeterLevel(linear) {
|
|
10
|
+
const peakDb = 20 * Math.log10(Math.max(linear, 1e-6))
|
|
11
|
+
return Math.max(0, Math.min(30, (peakDb + 60) / 2))
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function clampLevel(level) {
|
|
15
|
+
if (!Number.isFinite(level)) return 0
|
|
16
|
+
return Math.max(0, Math.min(30, level))
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function clampPeakDb(peakDb) {
|
|
20
|
+
if (!Number.isFinite(peakDb)) return Number.NEGATIVE_INFINITY
|
|
21
|
+
return Math.max(-96, peakDb)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function getNormalizedLevel(level) {
|
|
25
|
+
return Math.max(
|
|
26
|
+
0,
|
|
27
|
+
Math.min(100, ((clampLevel(level) - SEGMENT_MIN) / SEGMENT_RANGE) * 100),
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function getPeakHoldColor(peakPct) {
|
|
32
|
+
if (peakPct >= 88) return 'rgba(254, 78, 84, 0.89)'
|
|
33
|
+
if (peakPct >= 69) return 'rgb(255, 197, 61)'
|
|
34
|
+
return '#00dae8'
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function gainToFaderPosition(gain) {
|
|
38
|
+
if (gain <= 0) return 0
|
|
39
|
+
const db = 20 * Math.log10(gain)
|
|
40
|
+
if (db <= -96) return 0
|
|
41
|
+
if (db <= 0) return ((db + 96) / 96) * UNITY_GAIN_POS
|
|
42
|
+
return (
|
|
43
|
+
UNITY_GAIN_POS +
|
|
44
|
+
(Math.min(db, MAX_BOOST_DB) / MAX_BOOST_DB) * (1 - UNITY_GAIN_POS)
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function faderPositionToGain(pos) {
|
|
49
|
+
if (pos <= 0) return 0
|
|
50
|
+
let db
|
|
51
|
+
if (pos <= UNITY_GAIN_POS) {
|
|
52
|
+
db = (pos / UNITY_GAIN_POS) * 96 - 96
|
|
53
|
+
} else {
|
|
54
|
+
db = ((pos - UNITY_GAIN_POS) / (1 - UNITY_GAIN_POS)) * MAX_BOOST_DB
|
|
55
|
+
}
|
|
56
|
+
return 10 ** (db / 20)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function MeterRow({ level }) {
|
|
60
|
+
const pct = getNormalizedLevel(level)
|
|
61
|
+
return (
|
|
62
|
+
<div className={styles.barRow}>
|
|
63
|
+
<div className={styles.barTrack} />
|
|
64
|
+
<div
|
|
65
|
+
className={styles.barFill}
|
|
66
|
+
style={{
|
|
67
|
+
width: `${pct}%`,
|
|
68
|
+
backgroundSize: pct > 0 ? `${10000 / pct}% 100%` : '100% 100%',
|
|
69
|
+
}}
|
|
70
|
+
/>
|
|
71
|
+
</div>
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export const InputLevelMeter = memo(function InputLevelMeter({
|
|
76
|
+
linear = [0, 0],
|
|
77
|
+
volume = 1,
|
|
78
|
+
onVolumeChange,
|
|
79
|
+
showHandler = true,
|
|
80
|
+
showMeter = true,
|
|
81
|
+
}) {
|
|
82
|
+
const [linearL, linearR] = linear
|
|
83
|
+
const leftLevel = clampLevel(linearToMeterLevel(linearL ?? 0))
|
|
84
|
+
const rightLevel = clampLevel(linearToMeterLevel(linearR ?? 0))
|
|
85
|
+
|
|
86
|
+
const [isPressed, setIsPressed] = useState(false)
|
|
87
|
+
const isPressedRef = useRef(false)
|
|
88
|
+
const meterRef = useRef(null)
|
|
89
|
+
const peakHoldRef = useRef(0)
|
|
90
|
+
|
|
91
|
+
const faderPercent = Math.max(
|
|
92
|
+
0,
|
|
93
|
+
Math.min(100, gainToFaderPosition(volume) * 100),
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
const leftNormalized = getNormalizedLevel(leftLevel)
|
|
97
|
+
const rightNormalized = getNormalizedLevel(rightLevel)
|
|
98
|
+
const currentPeakPct = Math.max(leftNormalized, rightNormalized)
|
|
99
|
+
|
|
100
|
+
if (currentPeakPct > peakHoldRef.current) {
|
|
101
|
+
peakHoldRef.current = currentPeakPct
|
|
102
|
+
}
|
|
103
|
+
if (currentPeakPct <= 0) {
|
|
104
|
+
peakHoldRef.current = 0
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const peakHoldPct = peakHoldRef.current
|
|
108
|
+
const peakHoldColor = getPeakHoldColor(peakHoldPct)
|
|
109
|
+
const showPeakHold = peakHoldPct > 0
|
|
110
|
+
|
|
111
|
+
const handlePointerDown = useCallback(
|
|
112
|
+
(e) => {
|
|
113
|
+
if (!onVolumeChange) return
|
|
114
|
+
e.currentTarget.setPointerCapture(e.pointerId)
|
|
115
|
+
isPressedRef.current = true
|
|
116
|
+
setIsPressed(true)
|
|
117
|
+
const rect = meterRef.current?.getBoundingClientRect()
|
|
118
|
+
if (rect) {
|
|
119
|
+
const pos = Math.max(
|
|
120
|
+
0,
|
|
121
|
+
Math.min(1, (e.clientX - rect.left) / rect.width),
|
|
122
|
+
)
|
|
123
|
+
onVolumeChange([faderPositionToGain(pos)])
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
[onVolumeChange],
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
const handlePointerMove = useCallback(
|
|
130
|
+
(e) => {
|
|
131
|
+
if (!isPressedRef.current || !onVolumeChange) return
|
|
132
|
+
const rect = meterRef.current?.getBoundingClientRect()
|
|
133
|
+
if (rect) {
|
|
134
|
+
const pos = Math.max(
|
|
135
|
+
0,
|
|
136
|
+
Math.min(1, (e.clientX - rect.left) / rect.width),
|
|
137
|
+
)
|
|
138
|
+
onVolumeChange([faderPositionToGain(pos)])
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
[onVolumeChange],
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
const handlePointerUp = useCallback(() => {
|
|
145
|
+
isPressedRef.current = false
|
|
146
|
+
setIsPressed(false)
|
|
147
|
+
}, [])
|
|
148
|
+
|
|
149
|
+
const meterClassName = [styles.bars, isPressed ? styles.pressed : '']
|
|
150
|
+
.filter(Boolean)
|
|
151
|
+
.join(' ')
|
|
152
|
+
|
|
153
|
+
const hasHandler = onVolumeChange && showHandler
|
|
154
|
+
|
|
155
|
+
return (
|
|
156
|
+
<div
|
|
157
|
+
className={styles.container}
|
|
158
|
+
onMouseLeave={() => {
|
|
159
|
+
if (!isPressed) setIsPressed(false)
|
|
160
|
+
}}
|
|
161
|
+
onPointerDown={handlePointerDown}
|
|
162
|
+
onPointerMove={handlePointerMove}
|
|
163
|
+
onPointerUp={handlePointerUp}
|
|
164
|
+
>
|
|
165
|
+
<div ref={meterRef} className={meterClassName}>
|
|
166
|
+
<MeterRow level={leftLevel} />
|
|
167
|
+
<MeterRow level={rightLevel} />
|
|
168
|
+
|
|
169
|
+
{hasHandler && (
|
|
170
|
+
<div
|
|
171
|
+
className={`${styles.thumb} ${isPressed ? styles.pressed : ''}`}
|
|
172
|
+
style={{ left: `${faderPercent}%` }}
|
|
173
|
+
/>
|
|
174
|
+
)}
|
|
175
|
+
|
|
176
|
+
{showPeakHold && (
|
|
177
|
+
<>
|
|
178
|
+
<div
|
|
179
|
+
className={styles.peakDotTop}
|
|
180
|
+
style={{
|
|
181
|
+
left: `min(calc(${peakHoldPct}% + 3px), calc(100% - 3px))`,
|
|
182
|
+
background: peakHoldColor,
|
|
183
|
+
}}
|
|
184
|
+
/>
|
|
185
|
+
<div
|
|
186
|
+
className={styles.peakDotBottom}
|
|
187
|
+
style={{
|
|
188
|
+
left: `min(calc(${peakHoldPct}% + 3px), calc(100% - 3px))`,
|
|
189
|
+
background: peakHoldColor,
|
|
190
|
+
}}
|
|
191
|
+
/>
|
|
192
|
+
</>
|
|
193
|
+
)}
|
|
194
|
+
</div>
|
|
195
|
+
|
|
196
|
+
{showMeter && (
|
|
197
|
+
<div
|
|
198
|
+
className={`${styles.zeroDbDot} ${isPressed ? styles.pressed : ''}`}
|
|
199
|
+
/>
|
|
200
|
+
)}
|
|
201
|
+
</div>
|
|
202
|
+
)
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
InputLevelMeter.displayName = 'InputLevelMeter'
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
.container {
|
|
2
|
+
position: relative;
|
|
3
|
+
display: flex;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
gap: 4px;
|
|
6
|
+
align-items: flex-start;
|
|
7
|
+
width: 100%;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.bars {
|
|
11
|
+
position: relative;
|
|
12
|
+
display: flex;
|
|
13
|
+
flex-direction: column;
|
|
14
|
+
gap: 1px;
|
|
15
|
+
padding: 2px;
|
|
16
|
+
border-radius: 3px;
|
|
17
|
+
width: 100%;
|
|
18
|
+
background: rgba(216, 244, 246, 0.04);
|
|
19
|
+
transition: background-color 0.1s ease;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.bars.pressed {
|
|
23
|
+
background: rgba(221, 234, 248, 0.08);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.barRow {
|
|
27
|
+
display: inline-grid;
|
|
28
|
+
grid-template-rows: max-content;
|
|
29
|
+
place-items: start;
|
|
30
|
+
width: 100%;
|
|
31
|
+
position: relative;
|
|
32
|
+
line-height: 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.barTrack {
|
|
36
|
+
grid-column: 1;
|
|
37
|
+
grid-row: 1;
|
|
38
|
+
height: 3px;
|
|
39
|
+
width: 100%;
|
|
40
|
+
border-radius: 9999px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.barFill {
|
|
44
|
+
grid-column: 1;
|
|
45
|
+
grid-row: 1;
|
|
46
|
+
height: 3px;
|
|
47
|
+
border-radius: 9999px;
|
|
48
|
+
background: linear-gradient(
|
|
49
|
+
270deg,
|
|
50
|
+
rgba(254, 78, 84, 0.894) 12%,
|
|
51
|
+
rgb(255, 197, 61) 12%,
|
|
52
|
+
rgb(255, 197, 61) 31%,
|
|
53
|
+
rgb(0, 218, 232) 31%
|
|
54
|
+
);
|
|
55
|
+
will-change: width;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.thumb {
|
|
59
|
+
position: absolute;
|
|
60
|
+
top: 50%;
|
|
61
|
+
transform: translate(-50%, -50%);
|
|
62
|
+
width: 8px;
|
|
63
|
+
height: 19px;
|
|
64
|
+
border-radius: 9999px;
|
|
65
|
+
background: #edeef0;
|
|
66
|
+
cursor: ew-resize;
|
|
67
|
+
z-index: 2;
|
|
68
|
+
touch-action: none;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.thumb.pressed {
|
|
72
|
+
background: white;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.peakDot {
|
|
76
|
+
position: absolute;
|
|
77
|
+
width: 1px;
|
|
78
|
+
height: 3px;
|
|
79
|
+
border-radius: 9999px;
|
|
80
|
+
z-index: 1;
|
|
81
|
+
pointer-events: none;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.peakDotTop {
|
|
85
|
+
composes: peakDot;
|
|
86
|
+
top: calc(50% - 2px);
|
|
87
|
+
transform: translate(-50%, -50%);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.peakDotBottom {
|
|
91
|
+
composes: peakDot;
|
|
92
|
+
top: calc(50% + 2px);
|
|
93
|
+
transform: translate(-50%, -50%);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.zeroDbDot {
|
|
97
|
+
position: absolute;
|
|
98
|
+
left: 66.7%;
|
|
99
|
+
top: 12px;
|
|
100
|
+
width: 2px;
|
|
101
|
+
height: 2px;
|
|
102
|
+
border-radius: 50%;
|
|
103
|
+
background: rgba(255, 255, 255, 0.12);
|
|
104
|
+
pointer-events: none;
|
|
105
|
+
transform: translateX(-50%);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.zeroDbDot.pressed {
|
|
109
|
+
width: 3px;
|
|
110
|
+
height: 3px;
|
|
111
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { InputLevelMeter } from './InputLevelMeter'
|
|
2
|
+
import { useSimulatedInputLevel } from './useSimulatedInputLevel'
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Components/InputLevelMeter',
|
|
6
|
+
component: InputLevelMeter,
|
|
7
|
+
tags: ['autodocs'],
|
|
8
|
+
parameters: {
|
|
9
|
+
layout: 'centered',
|
|
10
|
+
},
|
|
11
|
+
decorators: [
|
|
12
|
+
(Story) => (
|
|
13
|
+
<div style={{ padding: '16px', background: '#1d1d1d', width: '200px' }}>
|
|
14
|
+
<Story />
|
|
15
|
+
</div>
|
|
16
|
+
),
|
|
17
|
+
],
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function AnimatedMeter() {
|
|
21
|
+
const linear = useSimulatedInputLevel()
|
|
22
|
+
return <InputLevelMeter linear={linear} />
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const Default = {
|
|
26
|
+
render: () => <AnimatedMeter />,
|
|
27
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from 'react'
|
|
2
|
+
|
|
3
|
+
export function useSimulatedInputLevel() {
|
|
4
|
+
const [linear, setLinear] = useState([0.5, 0.5])
|
|
5
|
+
const targetRef = useRef([0.5, 0.5])
|
|
6
|
+
const currentRef = useRef([0.5, 0.5])
|
|
7
|
+
const frameRef = useRef(null)
|
|
8
|
+
const tickRef = useRef(0)
|
|
9
|
+
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
function animate() {
|
|
12
|
+
tickRef.current++
|
|
13
|
+
|
|
14
|
+
if (tickRef.current % 20 === 0) {
|
|
15
|
+
targetRef.current = [Math.random(), Math.random()]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
currentRef.current = currentRef.current.map((cur, i) => {
|
|
19
|
+
const target = targetRef.current[i]
|
|
20
|
+
const speed = cur > target ? 0.15 : 0.08
|
|
21
|
+
return cur + (target - cur) * speed
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
setLinear([...currentRef.current])
|
|
25
|
+
frameRef.current = requestAnimationFrame(animate)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
frameRef.current = requestAnimationFrame(animate)
|
|
29
|
+
return () => cancelAnimationFrame(frameRef.current)
|
|
30
|
+
}, [])
|
|
31
|
+
|
|
32
|
+
return linear
|
|
33
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Flex, Text } from '@radix-ui/themes'
|
|
2
2
|
import { Popover } from 'radix-ui'
|
|
3
3
|
import { useCallback, useState } from 'react'
|
|
4
|
+
import { InputLevelMeter } from '../InputLevelMeter/InputLevelMeter'
|
|
4
5
|
import { Select } from '../Select/Select'
|
|
5
|
-
import { Slider } from '../Slider/Slider'
|
|
6
6
|
import styles from './RecordSettingsPopover.module.css'
|
|
7
7
|
|
|
8
8
|
export function RecordSettingsPopover({
|
|
@@ -18,11 +18,14 @@ export function RecordSettingsPopover({
|
|
|
18
18
|
}) {
|
|
19
19
|
const [opened, setOpened] = useState(false)
|
|
20
20
|
|
|
21
|
-
const handleOpenChange = useCallback(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
const handleOpenChange = useCallback(
|
|
22
|
+
(open) => {
|
|
23
|
+
if (!open || !isRecord) {
|
|
24
|
+
setOpened(open)
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
[open, isRecord],
|
|
28
|
+
)
|
|
26
29
|
|
|
27
30
|
const handleContextMenu = useCallback(() => {
|
|
28
31
|
e.preventDefault()
|
|
@@ -69,11 +72,7 @@ export function RecordSettingsPopover({
|
|
|
69
72
|
</Text>
|
|
70
73
|
|
|
71
74
|
{opened && (
|
|
72
|
-
<
|
|
73
|
-
value={inputLevel}
|
|
74
|
-
max={30}
|
|
75
|
-
style={{ paddingTop: '8px', paddingBottom: '8px' }}
|
|
76
|
-
/>
|
|
75
|
+
<InputLevelMeter linear={inputLevel} showHandler={false} />
|
|
77
76
|
)}
|
|
78
77
|
</Flex>
|
|
79
78
|
</Flex>
|
|
@@ -9,8 +9,8 @@ import {
|
|
|
9
9
|
Box,
|
|
10
10
|
DropdownMenu,
|
|
11
11
|
Flex,
|
|
12
|
-
HorizontalVolume,
|
|
13
12
|
IconButton,
|
|
13
|
+
InputLevelMeter,
|
|
14
14
|
PanControl,
|
|
15
15
|
Text,
|
|
16
16
|
Tooltip,
|
|
@@ -32,14 +32,13 @@ export const TrackHeader = memo(
|
|
|
32
32
|
menuOptions,
|
|
33
33
|
showPan = true,
|
|
34
34
|
showVolumeControls = true,
|
|
35
|
-
isGrouped = false,
|
|
36
35
|
height = 81,
|
|
37
36
|
compact = false,
|
|
38
37
|
isActive = false,
|
|
39
38
|
instrumentOptions,
|
|
40
39
|
deviceOptions,
|
|
41
40
|
channelOptions,
|
|
42
|
-
inputLevel,
|
|
41
|
+
inputLevel: inputLevel,
|
|
43
42
|
|
|
44
43
|
// State
|
|
45
44
|
volume,
|
|
@@ -213,9 +212,10 @@ export const TrackHeader = memo(
|
|
|
213
212
|
<div {...DND_PROTECTION} className={styles.trackControls}>
|
|
214
213
|
{!compact && showVolumeControls && (
|
|
215
214
|
<>
|
|
216
|
-
<
|
|
215
|
+
<InputLevelMeter
|
|
216
|
+
linear={inputLevel}
|
|
217
217
|
volume={volume}
|
|
218
|
-
|
|
218
|
+
onVolumeChange={onVolumeChange}
|
|
219
219
|
/>
|
|
220
220
|
{showPan && (
|
|
221
221
|
<PanControl
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useState } from 'react'
|
|
2
2
|
import { BassIcon, DrumsIcon, ElectricGuitarIcon, KeysIcon } from '../../icons'
|
|
3
|
+
import { useSimulatedInputLevel } from '../InputLevelMeter/useSimulatedInputLevel'
|
|
3
4
|
import { TrackHeader } from './TrackHeader'
|
|
4
5
|
export default {
|
|
5
6
|
title: 'Components/TrackHeader',
|
|
@@ -130,7 +131,33 @@ export const Default = {
|
|
|
130
131
|
instrumentOptions,
|
|
131
132
|
instrumentSelected: instrumentOptions[0],
|
|
132
133
|
},
|
|
133
|
-
render: (args) =>
|
|
134
|
+
render: (args) => {
|
|
135
|
+
const inputLevel = useSimulatedInputLevel()
|
|
136
|
+
const [isRecord, setIsRecord] = useState(false)
|
|
137
|
+
const [isMuted, setIsMuted] = useState(args.isMuted)
|
|
138
|
+
const [isSolo, setIsSolo] = useState(args.isSolo)
|
|
139
|
+
|
|
140
|
+
return (
|
|
141
|
+
<TrackHeader
|
|
142
|
+
{...args}
|
|
143
|
+
deviceOptions={[
|
|
144
|
+
{ value: 'mic', label: 'Built-in Microphone' },
|
|
145
|
+
{ value: 'interface', label: 'Audio Interface' },
|
|
146
|
+
]}
|
|
147
|
+
channelOptions={[
|
|
148
|
+
{ value: '1', label: 'Channel 1' },
|
|
149
|
+
{ value: '2', label: 'Channel 2' },
|
|
150
|
+
]}
|
|
151
|
+
isRecord={isRecord}
|
|
152
|
+
onRecordChange={() => setIsRecord((v) => !v)}
|
|
153
|
+
isMuted={isMuted}
|
|
154
|
+
onMutedChange={() => setIsMuted((v) => !v)}
|
|
155
|
+
isSolo={isSolo}
|
|
156
|
+
onSoloChange={() => setIsSolo((v) => !v)}
|
|
157
|
+
inputLevel={inputLevel}
|
|
158
|
+
/>
|
|
159
|
+
)
|
|
160
|
+
},
|
|
134
161
|
}
|
|
135
162
|
|
|
136
163
|
export const Group = {
|
package/src/index.jsx
CHANGED
|
@@ -87,6 +87,7 @@ export { Countdown } from './components/Countdown/Countdown'
|
|
|
87
87
|
export { DataTable } from './components/DataTable/DataTable'
|
|
88
88
|
export { DropdownButton } from './components/DropdownButton/DropdownButton'
|
|
89
89
|
export { DropdownMenu } from './components/DropdownMenu/DropdownMenu'
|
|
90
|
+
export { EmptyState } from './components/EmptyState/EmptyState'
|
|
90
91
|
export {
|
|
91
92
|
Extension,
|
|
92
93
|
useExtension,
|
|
@@ -100,6 +101,7 @@ export { GroupButtons } from './components/GroupButtons/GroupButtons'
|
|
|
100
101
|
export { HeaderPanel } from './components/HeaderPanel/HeaderPanel'
|
|
101
102
|
export { HorizontalVolume } from './components/HorizontalVolume/HorizontalVolume'
|
|
102
103
|
export { IconButton } from './components/IconButton/IconButton'
|
|
104
|
+
export { InputLevelMeter } from './components/InputLevelMeter/InputLevelMeter'
|
|
103
105
|
export { InstrumentSelector } from './components/InstrumentSelector/InstrumentSelector'
|
|
104
106
|
export { Knob } from './components/Knob/Knob'
|
|
105
107
|
export { ListCards } from './components/ListCards/ListCards'
|
|
@@ -132,15 +134,16 @@ export { Text } from './components/Text/Text'
|
|
|
132
134
|
export { TextArea } from './components/TextArea/TextArea'
|
|
133
135
|
export { TextField } from './components/TextField/TextField'
|
|
134
136
|
export { Theme } from './components/theme/Theme'
|
|
135
|
-
export { ToastProvider, useToast } from './components/ToastProvider/ToastProvider'
|
|
136
137
|
export { ThumbnailPicker } from './components/ThumbnailPicker/ThumbnailPicker'
|
|
138
|
+
export {
|
|
139
|
+
ToastProvider,
|
|
140
|
+
useToast,
|
|
141
|
+
} from './components/ToastProvider/ToastProvider'
|
|
137
142
|
export { Tooltip } from './components/Tooltip/Tooltip'
|
|
138
143
|
export { TooltipWithInfoIcon } from './components/TooltipWithInfoIcon/TooltipWithInfoIcon'
|
|
139
144
|
export { TrackControlButton } from './components/TrackControlButton'
|
|
145
|
+
export { TrackControlsToggle } from './components/TrackControlsToggle/TrackControlsToggle'
|
|
140
146
|
export { TrackHeader } from './components/TrackHeader/TrackHeader'
|
|
141
147
|
export { useForm } from './components/useForm/useForm'
|
|
142
148
|
export { VoiceConversionForm } from './components/VoiceConversionForm/VoiceConversionForm'
|
|
143
149
|
export { Waveform } from './components/VoiceConversionForm/Waveform/Waveform'
|
|
144
|
-
|
|
145
|
-
export { EmptyState } from './components/EmptyState/EmptyState'
|
|
146
|
-
export { TrackControlsToggle } from './components/TrackControlsToggle/TrackControlsToggle'
|