volca-drum-ui 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +561 -0
- package/dist/assets/icons/index.d.ts +19 -0
- package/dist/assets/icons/index.d.ts.map +1 -0
- package/dist/components/Accordion/Accordion.css.d.ts +23 -0
- package/dist/components/Accordion/Accordion.css.d.ts.map +1 -0
- package/dist/components/Accordion/Accordion.d.ts +20 -0
- package/dist/components/Accordion/Accordion.d.ts.map +1 -0
- package/dist/components/Accordion/index.d.ts +3 -0
- package/dist/components/Accordion/index.d.ts.map +1 -0
- package/dist/components/AppHeader/AppHeader.css.d.ts +10 -0
- package/dist/components/AppHeader/AppHeader.css.d.ts.map +1 -0
- package/dist/components/AppHeader/AppHeader.d.ts +20 -0
- package/dist/components/AppHeader/AppHeader.d.ts.map +1 -0
- package/dist/components/AppHeader/index.d.ts +3 -0
- package/dist/components/AppHeader/index.d.ts.map +1 -0
- package/dist/components/AppLayout/AppLayout.css.d.ts +7 -0
- package/dist/components/AppLayout/AppLayout.css.d.ts.map +1 -0
- package/dist/components/AppLayout/AppLayout.d.ts +18 -0
- package/dist/components/AppLayout/AppLayout.d.ts.map +1 -0
- package/dist/components/AppLayout/index.d.ts +3 -0
- package/dist/components/AppLayout/index.d.ts.map +1 -0
- package/dist/components/Button/Button.css.d.ts +7 -0
- package/dist/components/Button/Button.css.d.ts.map +1 -0
- package/dist/components/Button/Button.d.ts +17 -0
- package/dist/components/Button/Button.d.ts.map +1 -0
- package/dist/components/Button/index.d.ts +3 -0
- package/dist/components/Button/index.d.ts.map +1 -0
- package/dist/components/Card/Card.css.d.ts +9 -0
- package/dist/components/Card/Card.css.d.ts.map +1 -0
- package/dist/components/Card/Card.d.ts +22 -0
- package/dist/components/Card/Card.d.ts.map +1 -0
- package/dist/components/Card/index.d.ts +3 -0
- package/dist/components/Card/index.d.ts.map +1 -0
- package/dist/components/EmptyState/EmptyState.css.d.ts +12 -0
- package/dist/components/EmptyState/EmptyState.css.d.ts.map +1 -0
- package/dist/components/EmptyState/EmptyState.d.ts +24 -0
- package/dist/components/EmptyState/EmptyState.d.ts.map +1 -0
- package/dist/components/EmptyState/index.d.ts +3 -0
- package/dist/components/EmptyState/index.d.ts.map +1 -0
- package/dist/components/ErrorDisplay/ErrorDisplay.css.d.ts +14 -0
- package/dist/components/ErrorDisplay/ErrorDisplay.css.d.ts.map +1 -0
- package/dist/components/ErrorDisplay/ErrorDisplay.d.ts +28 -0
- package/dist/components/ErrorDisplay/ErrorDisplay.d.ts.map +1 -0
- package/dist/components/ErrorDisplay/index.d.ts +3 -0
- package/dist/components/ErrorDisplay/index.d.ts.map +1 -0
- package/dist/components/Modal/Modal.css.d.ts +14 -0
- package/dist/components/Modal/Modal.css.d.ts.map +1 -0
- package/dist/components/Modal/Modal.d.ts +17 -0
- package/dist/components/Modal/Modal.d.ts.map +1 -0
- package/dist/components/Modal/index.d.ts +3 -0
- package/dist/components/Modal/index.d.ts.map +1 -0
- package/dist/components/ModalContent/ModalContent.css.d.ts +23 -0
- package/dist/components/ModalContent/ModalContent.css.d.ts.map +1 -0
- package/dist/components/ModalContent/ModalContent.d.ts +58 -0
- package/dist/components/ModalContent/ModalContent.d.ts.map +1 -0
- package/dist/components/ModalContent/index.d.ts +3 -0
- package/dist/components/ModalContent/index.d.ts.map +1 -0
- package/dist/components/ParameterDisplay/ParameterDisplay.css.d.ts +17 -0
- package/dist/components/ParameterDisplay/ParameterDisplay.css.d.ts.map +1 -0
- package/dist/components/ParameterDisplay/ParameterDisplay.d.ts +29 -0
- package/dist/components/ParameterDisplay/ParameterDisplay.d.ts.map +1 -0
- package/dist/components/ParameterDisplay/index.d.ts +3 -0
- package/dist/components/ParameterDisplay/index.d.ts.map +1 -0
- package/dist/components/PartEditorLayout/PartEditorLayout.css.d.ts +19 -0
- package/dist/components/PartEditorLayout/PartEditorLayout.css.d.ts.map +1 -0
- package/dist/components/PartEditorLayout/PartEditorLayout.d.ts +53 -0
- package/dist/components/PartEditorLayout/PartEditorLayout.d.ts.map +1 -0
- package/dist/components/PartEditorLayout/index.d.ts +3 -0
- package/dist/components/PartEditorLayout/index.d.ts.map +1 -0
- package/dist/components/PartTitle/PartTitle.css.d.ts +11 -0
- package/dist/components/PartTitle/PartTitle.css.d.ts.map +1 -0
- package/dist/components/PartTitle/PartTitle.d.ts +30 -0
- package/dist/components/PartTitle/PartTitle.d.ts.map +1 -0
- package/dist/components/PartTitle/index.d.ts +3 -0
- package/dist/components/PartTitle/index.d.ts.map +1 -0
- package/dist/components/Parts/Parts.css.d.ts +8 -0
- package/dist/components/Parts/Parts.css.d.ts.map +1 -0
- package/dist/components/Parts/Parts.d.ts +16 -0
- package/dist/components/Parts/Parts.d.ts.map +1 -0
- package/dist/components/Parts/index.d.ts +3 -0
- package/dist/components/Parts/index.d.ts.map +1 -0
- package/dist/components/Processing/Processing.css.d.ts +8 -0
- package/dist/components/Processing/Processing.css.d.ts.map +1 -0
- package/dist/components/Processing/Processing.d.ts +20 -0
- package/dist/components/Processing/Processing.d.ts.map +1 -0
- package/dist/components/Processing/index.d.ts +3 -0
- package/dist/components/Processing/index.d.ts.map +1 -0
- package/dist/components/RadioButton/RadioButton.css.d.ts +13 -0
- package/dist/components/RadioButton/RadioButton.css.d.ts.map +1 -0
- package/dist/components/RadioButton/RadioButton.d.ts +25 -0
- package/dist/components/RadioButton/RadioButton.d.ts.map +1 -0
- package/dist/components/RadioButton/index.d.ts +3 -0
- package/dist/components/RadioButton/index.d.ts.map +1 -0
- package/dist/components/RadioGroup/RadioGroup.css.d.ts +8 -0
- package/dist/components/RadioGroup/RadioGroup.css.d.ts.map +1 -0
- package/dist/components/RadioGroup/RadioGroup.d.ts +21 -0
- package/dist/components/RadioGroup/RadioGroup.d.ts.map +1 -0
- package/dist/components/RadioGroup/index.d.ts +3 -0
- package/dist/components/RadioGroup/index.d.ts.map +1 -0
- package/dist/components/Slider/Slider.css.d.ts +15 -0
- package/dist/components/Slider/Slider.css.d.ts.map +1 -0
- package/dist/components/Slider/Slider.d.ts +20 -0
- package/dist/components/Slider/Slider.d.ts.map +1 -0
- package/dist/components/Slider/index.d.ts +3 -0
- package/dist/components/Slider/index.d.ts.map +1 -0
- package/dist/components/Stack/Stack.css.d.ts +10 -0
- package/dist/components/Stack/Stack.css.d.ts.map +1 -0
- package/dist/components/Stack/Stack.d.ts +24 -0
- package/dist/components/Stack/Stack.d.ts.map +1 -0
- package/dist/components/Stack/index.d.ts +3 -0
- package/dist/components/Stack/index.d.ts.map +1 -0
- package/dist/components/Status/Status.css.d.ts +49 -0
- package/dist/components/Status/Status.css.d.ts.map +1 -0
- package/dist/components/Status/Status.d.ts +28 -0
- package/dist/components/Status/Status.d.ts.map +1 -0
- package/dist/components/Status/index.d.ts +3 -0
- package/dist/components/Status/index.d.ts.map +1 -0
- package/dist/components/StepList/StepList.css.d.ts +12 -0
- package/dist/components/StepList/StepList.css.d.ts.map +1 -0
- package/dist/components/StepList/StepList.d.ts +19 -0
- package/dist/components/StepList/StepList.d.ts.map +1 -0
- package/dist/components/StepList/index.d.ts +3 -0
- package/dist/components/StepList/index.d.ts.map +1 -0
- package/dist/components/Switch/Switch.css.d.ts +9 -0
- package/dist/components/Switch/Switch.css.d.ts.map +1 -0
- package/dist/components/Switch/Switch.d.ts +17 -0
- package/dist/components/Switch/Switch.d.ts.map +1 -0
- package/dist/components/Switch/index.d.ts +3 -0
- package/dist/components/Switch/index.d.ts.map +1 -0
- package/dist/components/Toast/Toast.css.d.ts +6 -0
- package/dist/components/Toast/Toast.css.d.ts.map +1 -0
- package/dist/components/Toast/Toast.d.ts +10 -0
- package/dist/components/Toast/Toast.d.ts.map +1 -0
- package/dist/components/Toast/index.d.ts +2 -0
- package/dist/components/Toast/index.d.ts.map +1 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +852 -0
- package/dist/index.js.map +1 -0
- package/dist/style.css +1 -0
- package/dist/utils/toast.d.ts +15 -0
- package/dist/utils/toast.d.ts.map +1 -0
- package/package.json +100 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hans Desmedt
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
# @midi-volca-drum/ui-components
|
|
2
|
+
|
|
3
|
+
> A lightweight, accessible React component library designed for Figma Make integration
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@midi-volca-drum/ui-components)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
A collection of production-ready React components extracted from the MIDI Volca Drum Editor project. Designed with Figma Make in mind, these components bridge the gap between design and code, making it easy to use production components in your Figma prototypes.
|
|
11
|
+
|
|
12
|
+
### Key Features
|
|
13
|
+
|
|
14
|
+
- 🎨 **Figma Make Ready** - Designed to work seamlessly with Figma Make
|
|
15
|
+
- ♿ **Accessible** - WCAG 2.1 compliant with proper ARIA labels
|
|
16
|
+
- 🎹 **Keyboard Navigation** - Full keyboard support for all interactive components
|
|
17
|
+
- 🌗 **Theme Support** - CSS custom properties for easy theming
|
|
18
|
+
- 📦 **Lightweight** - ~8KB JS + ~13KB CSS (gzipped)
|
|
19
|
+
- ⚡ **Tree-shakeable** - Import only what you need
|
|
20
|
+
- 🔒 **TypeScript** - Full type definitions included
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install @midi-volca-drum/ui-components
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Peer Dependencies
|
|
29
|
+
|
|
30
|
+
This library requires React 18 or higher:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install react@^18.0.0 react-dom@^18.0.0
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Quick Start
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
import { Button, Slider, Modal } from '@midi-volca-drum/ui-components';
|
|
40
|
+
import '@midi-volca-drum/ui-components/styles';
|
|
41
|
+
|
|
42
|
+
function App() {
|
|
43
|
+
const [value, setValue] = useState(64);
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<>
|
|
47
|
+
<Button variant="primary" onClick={() => console.log('Clicked!')}>
|
|
48
|
+
Click Me
|
|
49
|
+
</Button>
|
|
50
|
+
|
|
51
|
+
<Slider
|
|
52
|
+
id="volume"
|
|
53
|
+
label="Volume"
|
|
54
|
+
value={value}
|
|
55
|
+
onChange={setValue}
|
|
56
|
+
min={0}
|
|
57
|
+
max={127}
|
|
58
|
+
/>
|
|
59
|
+
</>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Components
|
|
65
|
+
|
|
66
|
+
### Accordion
|
|
67
|
+
|
|
68
|
+
Collapsible content sections with smooth animations.
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
import { Accordion } from '@midi-volca-drum/ui-components';
|
|
72
|
+
|
|
73
|
+
<Accordion
|
|
74
|
+
id="my-accordion"
|
|
75
|
+
title="Settings"
|
|
76
|
+
defaultExpanded={true}
|
|
77
|
+
direction="vertical"
|
|
78
|
+
>
|
|
79
|
+
<p>Your content here</p>
|
|
80
|
+
</Accordion>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Props:**
|
|
84
|
+
- `id` (string, required) - Unique identifier
|
|
85
|
+
- `title` (string, required) - Header text
|
|
86
|
+
- `defaultExpanded` (boolean) - Initial state (default: true)
|
|
87
|
+
- `direction` ('vertical' | 'horizontal') - Collapse direction (default: 'vertical')
|
|
88
|
+
- `className` (string) - Additional CSS classes
|
|
89
|
+
- `children` (ReactNode) - Content to collapse/expand
|
|
90
|
+
|
|
91
|
+
### Button
|
|
92
|
+
|
|
93
|
+
Versatile button component with multiple variants.
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
import { Button } from '@midi-volca-drum/ui-components';
|
|
97
|
+
|
|
98
|
+
<Button variant="primary" size="medium" onClick={handleClick}>
|
|
99
|
+
Click Me
|
|
100
|
+
</Button>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Props:**
|
|
104
|
+
- `variant` ('primary' | 'secondary' | 'text') - Visual style (default: 'primary')
|
|
105
|
+
- `size` ('small' | 'medium' | 'large') - Button size (default: 'medium')
|
|
106
|
+
- `disabled` (boolean) - Disabled state
|
|
107
|
+
- `type` ('button' | 'submit' | 'reset') - HTML button type
|
|
108
|
+
- `children` (ReactNode, required) - Button content
|
|
109
|
+
- All standard HTML button attributes
|
|
110
|
+
|
|
111
|
+
### Modal
|
|
112
|
+
|
|
113
|
+
Accessible modal dialog with backdrop.
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
import { Modal } from '@midi-volca-drum/ui-components';
|
|
117
|
+
|
|
118
|
+
<Modal isOpen={isOpen} onClose={() => setIsOpen(false)} title="Settings">
|
|
119
|
+
<p>Modal content goes here</p>
|
|
120
|
+
</Modal>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Props:**
|
|
124
|
+
- `isOpen` (boolean, required) - Visibility state
|
|
125
|
+
- `onClose` (function, required) - Close handler
|
|
126
|
+
- `title` (string, required) - Modal title
|
|
127
|
+
- `children` (ReactNode, required) - Modal content
|
|
128
|
+
|
|
129
|
+
### RadioButton & RadioGroup
|
|
130
|
+
|
|
131
|
+
Radio button inputs with icon or text variants.
|
|
132
|
+
|
|
133
|
+
```tsx
|
|
134
|
+
import { RadioGroup } from '@midi-volca-drum/ui-components';
|
|
135
|
+
|
|
136
|
+
const options = [
|
|
137
|
+
{ id: 'option1', value: '1', label: 'Option 1' },
|
|
138
|
+
{ id: 'option2', value: '2', label: 'Option 2' },
|
|
139
|
+
{ id: 'option3', value: '3', label: 'Option 3' },
|
|
140
|
+
];
|
|
141
|
+
|
|
142
|
+
<RadioGroup
|
|
143
|
+
name="my-radio-group"
|
|
144
|
+
options={options}
|
|
145
|
+
value={selectedValue}
|
|
146
|
+
onChange={setSelectedValue}
|
|
147
|
+
/>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**RadioGroup Props:**
|
|
151
|
+
- `name` (string, required) - Radio group name
|
|
152
|
+
- `options` (RadioOption[], required) - Array of radio options
|
|
153
|
+
- `value` (string | number, required) - Selected value
|
|
154
|
+
- `onChange` (function, required) - Change handler
|
|
155
|
+
- `className` (string) - Additional CSS classes
|
|
156
|
+
- `disabled` (boolean) - Disabled state
|
|
157
|
+
|
|
158
|
+
**RadioOption:**
|
|
159
|
+
- `id` (string, required) - Unique identifier
|
|
160
|
+
- `value` (string | number, required) - Option value
|
|
161
|
+
- `label` (string, required) - Display label
|
|
162
|
+
- `imageSrc` (string) - Icon image URL (for icon variant)
|
|
163
|
+
- `imageAlt` (string) - Icon alt text
|
|
164
|
+
- `variant` ('icon' | 'text') - Display style (default: 'text')
|
|
165
|
+
- `disabled` (boolean) - Disabled state
|
|
166
|
+
|
|
167
|
+
### Slider
|
|
168
|
+
|
|
169
|
+
Range input with visual feedback and custom formatting.
|
|
170
|
+
|
|
171
|
+
```tsx
|
|
172
|
+
import { Slider } from '@midi-volca-drum/ui-components';
|
|
173
|
+
|
|
174
|
+
<Slider
|
|
175
|
+
id="volume"
|
|
176
|
+
label="Volume"
|
|
177
|
+
value={volume}
|
|
178
|
+
onChange={setVolume}
|
|
179
|
+
min={0}
|
|
180
|
+
max={127}
|
|
181
|
+
step={1}
|
|
182
|
+
formatValue={(v) => `${v}%`}
|
|
183
|
+
/>
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**Props:**
|
|
187
|
+
- `id` (string, required) - Unique identifier
|
|
188
|
+
- `label` (string, required) - Slider label
|
|
189
|
+
- `value` (number, required) - Current value
|
|
190
|
+
- `onChange` (function, required) - Change handler: `(value: number) => void`
|
|
191
|
+
- `min` (number) - Minimum value (default: 0)
|
|
192
|
+
- `max` (number) - Maximum value (default: 127)
|
|
193
|
+
- `step` (number) - Step increment (default: 1)
|
|
194
|
+
- `formatValue` (function) - Custom value formatter: `(value: number) => string`
|
|
195
|
+
- `className` (string) - Additional CSS classes
|
|
196
|
+
- `disabled` (boolean) - Disabled state
|
|
197
|
+
|
|
198
|
+
### Switch
|
|
199
|
+
|
|
200
|
+
Toggle switch for boolean settings.
|
|
201
|
+
|
|
202
|
+
```tsx
|
|
203
|
+
import { Switch } from '@midi-volca-drum/ui-components';
|
|
204
|
+
|
|
205
|
+
<Switch
|
|
206
|
+
id="dark-mode"
|
|
207
|
+
label="Dark Mode"
|
|
208
|
+
checked={isDarkMode}
|
|
209
|
+
onChange={() => setIsDarkMode(!isDarkMode)}
|
|
210
|
+
/>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
**Props:**
|
|
214
|
+
- `id` (string, required) - Unique identifier
|
|
215
|
+
- `label` (string, required) - Switch label
|
|
216
|
+
- `checked` (boolean, required) - Current state
|
|
217
|
+
- `onChange` (function, required) - Toggle handler: `() => void`
|
|
218
|
+
- `disabled` (boolean) - Disabled state
|
|
219
|
+
|
|
220
|
+
### Toast
|
|
221
|
+
|
|
222
|
+
Toast notifications for user feedback. This component wraps `react-hot-toast` with styled defaults.
|
|
223
|
+
|
|
224
|
+
```tsx
|
|
225
|
+
import { toast } from '@midi-volca-drum/ui-components';
|
|
226
|
+
|
|
227
|
+
// Success toast
|
|
228
|
+
toast.success('Settings saved successfully!');
|
|
229
|
+
|
|
230
|
+
// Error toast
|
|
231
|
+
toast.error('Failed to connect to device');
|
|
232
|
+
|
|
233
|
+
// Info toast
|
|
234
|
+
toast('Processing your request...');
|
|
235
|
+
|
|
236
|
+
// Custom duration
|
|
237
|
+
toast.success('File uploaded', { duration: 5000 });
|
|
238
|
+
|
|
239
|
+
// With custom ID (prevents duplicates)
|
|
240
|
+
toast.success('Connection established', { id: 'midi-connect' });
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**Toast API:**
|
|
244
|
+
- `toast(message, options?)` - Default toast
|
|
245
|
+
- `toast.success(message, options?)` - Success toast with green indicator
|
|
246
|
+
- `toast.error(message, options?)` - Error toast with red indicator
|
|
247
|
+
- `toast.loading(message, options?)` - Loading toast with spinner
|
|
248
|
+
- `toast.custom(component, options?)` - Custom toast component
|
|
249
|
+
- `toast.dismiss(toastId?)` - Dismiss specific or all toasts
|
|
250
|
+
|
|
251
|
+
**Common Options:**
|
|
252
|
+
- `duration` (number) - Display duration in ms (default: 4000)
|
|
253
|
+
- `position` ('top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right') - Toast position
|
|
254
|
+
- `id` (string) - Unique ID to prevent duplicate toasts
|
|
255
|
+
- `icon` (ReactNode) - Custom icon
|
|
256
|
+
- `style` (CSSProperties) - Custom inline styles
|
|
257
|
+
|
|
258
|
+
**Note:** The Toast component uses `react-hot-toast` under the hood. You can import `Toaster` to customize the toast container:
|
|
259
|
+
|
|
260
|
+
```tsx
|
|
261
|
+
import { Toaster } from 'react-hot-toast';
|
|
262
|
+
|
|
263
|
+
function App() {
|
|
264
|
+
return (
|
|
265
|
+
<>
|
|
266
|
+
<Toaster position="top-right" />
|
|
267
|
+
{/* Your app content */}
|
|
268
|
+
</>
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## Theming & Customization
|
|
274
|
+
|
|
275
|
+
All components use CSS custom properties (CSS variables) for styling, making them fully themeable without modifying component code.
|
|
276
|
+
|
|
277
|
+
### Theme Switching
|
|
278
|
+
|
|
279
|
+
The library supports multiple themes using the `data-theme` attribute approach. By default, components use dark theme colors. Override with light theme by setting `data-theme="light"` on the root element:
|
|
280
|
+
|
|
281
|
+
```tsx
|
|
282
|
+
// Example theme switcher component
|
|
283
|
+
function ThemeToggle() {
|
|
284
|
+
const [isDark, setIsDark] = useState(true);
|
|
285
|
+
|
|
286
|
+
const toggleTheme = () => {
|
|
287
|
+
if (isDark) {
|
|
288
|
+
document.documentElement.dataset.theme = 'light';
|
|
289
|
+
} else {
|
|
290
|
+
delete document.documentElement.dataset.theme;
|
|
291
|
+
}
|
|
292
|
+
setIsDark(!isDark);
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
return (
|
|
296
|
+
<button onClick={toggleTheme}>
|
|
297
|
+
{isDark ? 'Switch to Light' : 'Switch to Dark'}
|
|
298
|
+
</button>
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Custom Theme Example
|
|
304
|
+
|
|
305
|
+
Create your own theme by defining CSS variables:
|
|
306
|
+
|
|
307
|
+
```css
|
|
308
|
+
/* Dark theme (default) */
|
|
309
|
+
:root, :root:not([data-theme="light"]) {
|
|
310
|
+
--color-background-app: #141a24;
|
|
311
|
+
--color-background-elevated: #0f141f;
|
|
312
|
+
--color-text-title: #b2bfcc;
|
|
313
|
+
--color-text-subtitle: #99a6b2;
|
|
314
|
+
--color-stroke-cyan: #00b2f2;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/* Light theme */
|
|
318
|
+
:root[data-theme="light"] {
|
|
319
|
+
--color-background-app: #ffffff;
|
|
320
|
+
--color-background-elevated: #f8f9fa;
|
|
321
|
+
--color-text-title: #212529;
|
|
322
|
+
--color-text-subtitle: #495057;
|
|
323
|
+
--color-stroke-cyan: #00b2f2;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/* Custom brand theme */
|
|
327
|
+
:root[data-theme="brand"] {
|
|
328
|
+
--color-stroke-cyan: #ff6b35; /* Custom accent color */
|
|
329
|
+
--color-stroke-green: #4ecdc4;
|
|
330
|
+
--color-stroke-orange: #f7931e;
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Complete CSS Custom Properties Reference
|
|
335
|
+
|
|
336
|
+
#### Colors - Background
|
|
337
|
+
```css
|
|
338
|
+
--color-background-app /* Main app background */
|
|
339
|
+
--color-background-elevated /* Elevated surfaces (cards, modals) */
|
|
340
|
+
--color-background-container /* Container backgrounds */
|
|
341
|
+
--color-background-card /* Card backgrounds */
|
|
342
|
+
--color-background-object /* UI object backgrounds */
|
|
343
|
+
--color-background-hover /* Hover state background */
|
|
344
|
+
--color-bg-surface /* Surface backgrounds */
|
|
345
|
+
--color-bg-base /* Base layer background */
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
#### Colors - Text
|
|
349
|
+
```css
|
|
350
|
+
--color-text-active /* Active/selected text */
|
|
351
|
+
--color-text-title /* Title text */
|
|
352
|
+
--color-text-body /* Body text */
|
|
353
|
+
--color-text-subtitle /* Subtitle text */
|
|
354
|
+
--color-text-muted /* Muted/secondary text */
|
|
355
|
+
--color-text-disabled /* Disabled text */
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
#### Colors - Stroke/Accent
|
|
359
|
+
```css
|
|
360
|
+
--color-stroke-green /* Success/green accent */
|
|
361
|
+
--color-stroke-green-overlay /* Green overlay/background */
|
|
362
|
+
--color-stroke-cyan /* Primary/cyan accent */
|
|
363
|
+
--color-stroke-cyan-overlay /* Cyan overlay/background */
|
|
364
|
+
--color-stroke-orange /* Warning/orange accent */
|
|
365
|
+
--color-stroke-orange-overlay /* Orange overlay/background */
|
|
366
|
+
--color-stroke-neutral /* Neutral borders/strokes */
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
#### Colors - Buttons
|
|
370
|
+
```css
|
|
371
|
+
--color-button-status-default /* Status button default */
|
|
372
|
+
--color-button-primary-default /* Primary button default */
|
|
373
|
+
--color-button-primary-hover /* Primary button hover */
|
|
374
|
+
--color-button-secondary-default /* Secondary button default */
|
|
375
|
+
--color-button-secondary-hover /* Secondary button hover */
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
#### Colors - Other
|
|
379
|
+
```css
|
|
380
|
+
--color-input-background /* Input field backgrounds */
|
|
381
|
+
--color-error-default /* Error state color */
|
|
382
|
+
--color-error-background /* Error background */
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
#### Spacing
|
|
386
|
+
```css
|
|
387
|
+
--spacing-xxs: 8px
|
|
388
|
+
--spacing-xs: 10px
|
|
389
|
+
--spacing-s: 12px
|
|
390
|
+
--spacing-m: 16px
|
|
391
|
+
--spacing-l: 20px
|
|
392
|
+
--spacing-xl: 24px
|
|
393
|
+
--spacing-xxl: 32px
|
|
394
|
+
--spacing-xxxl: 48px
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
#### Border Radius
|
|
398
|
+
```css
|
|
399
|
+
--border-radius-s: 6px
|
|
400
|
+
--border-radius-m: 8px
|
|
401
|
+
--border-radius-l: 12px
|
|
402
|
+
--border-radius-xl: 20px
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
#### Typography
|
|
406
|
+
```css
|
|
407
|
+
/* Display */
|
|
408
|
+
--font-display-lg-size: 20px
|
|
409
|
+
--font-display-lg-weight: 700
|
|
410
|
+
--font-display-lg-line-height: 1.4
|
|
411
|
+
--font-display-lg-letter-spacing: -0.01em
|
|
412
|
+
|
|
413
|
+
/* Headings */
|
|
414
|
+
--font-heading-lg-size: 16px
|
|
415
|
+
--font-heading-lg-weight: 700
|
|
416
|
+
--font-heading-md-size: 14px
|
|
417
|
+
--font-heading-md-weight: 700
|
|
418
|
+
--font-heading-sm-size: 12px
|
|
419
|
+
--font-heading-sm-weight: 700
|
|
420
|
+
|
|
421
|
+
/* Body */
|
|
422
|
+
--font-body-lg-size: 16px
|
|
423
|
+
--font-body-lg-weight: 600
|
|
424
|
+
--font-body-md-size: 13px
|
|
425
|
+
--font-body-md-weight: 600
|
|
426
|
+
--font-body-sm-size: 12px
|
|
427
|
+
--font-body-sm-weight: 600
|
|
428
|
+
|
|
429
|
+
/* Labels */
|
|
430
|
+
--font-label-md-size: 12px
|
|
431
|
+
--font-label-md-weight: 700
|
|
432
|
+
--font-label-md-line-height: 1.4
|
|
433
|
+
--font-label-md-letter-spacing: 0.02em
|
|
434
|
+
|
|
435
|
+
/* Caption */
|
|
436
|
+
--font-caption-size: 10px
|
|
437
|
+
--font-caption-weight: 600
|
|
438
|
+
--font-caption-line-height: 1.4
|
|
439
|
+
--font-caption-letter-spacing: 0.02em
|
|
440
|
+
|
|
441
|
+
/* Font Family */
|
|
442
|
+
--font-family-base: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### Persistence
|
|
446
|
+
|
|
447
|
+
Theme preference can be persisted using localStorage:
|
|
448
|
+
|
|
449
|
+
```tsx
|
|
450
|
+
function useTheme() {
|
|
451
|
+
const [theme, setTheme] = useState(() => {
|
|
452
|
+
return localStorage.getItem('theme') || 'dark';
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
useEffect(() => {
|
|
456
|
+
if (theme === 'light') {
|
|
457
|
+
document.documentElement.dataset.theme = 'light';
|
|
458
|
+
} else {
|
|
459
|
+
delete document.documentElement.dataset.theme;
|
|
460
|
+
}
|
|
461
|
+
localStorage.setItem('theme', theme);
|
|
462
|
+
}, [theme]);
|
|
463
|
+
|
|
464
|
+
return { theme, setTheme };
|
|
465
|
+
}
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
## Figma Make Integration
|
|
469
|
+
|
|
470
|
+
This library is specifically designed to work with Figma Make. Follow these steps to integrate:
|
|
471
|
+
|
|
472
|
+
1. **Install the library** in your project
|
|
473
|
+
2. **Import components** in your Figma Make setup
|
|
474
|
+
3. **Use production components** in your Figma prototypes instead of mockups
|
|
475
|
+
|
|
476
|
+
See [/docs/figma-make-setup.md](../../docs/figma-make-setup.md) for detailed integration guide.
|
|
477
|
+
|
|
478
|
+
## Development
|
|
479
|
+
|
|
480
|
+
### Setup
|
|
481
|
+
|
|
482
|
+
```bash
|
|
483
|
+
# Install dependencies
|
|
484
|
+
npm install
|
|
485
|
+
|
|
486
|
+
# Build library
|
|
487
|
+
npm run build
|
|
488
|
+
|
|
489
|
+
# Watch mode for development
|
|
490
|
+
npm run dev
|
|
491
|
+
|
|
492
|
+
# Type checking
|
|
493
|
+
npm run type-check
|
|
494
|
+
|
|
495
|
+
# Linting
|
|
496
|
+
npm run lint
|
|
497
|
+
npm run lint:fix
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
### Project Structure
|
|
501
|
+
|
|
502
|
+
```
|
|
503
|
+
src/
|
|
504
|
+
├── components/
|
|
505
|
+
│ ├── Accordion/
|
|
506
|
+
│ │ ├── Accordion.tsx
|
|
507
|
+
│ │ ├── Accordion.css
|
|
508
|
+
│ │ └── index.ts
|
|
509
|
+
│ ├── Button/
|
|
510
|
+
│ ├── Modal/
|
|
511
|
+
│ └── ...
|
|
512
|
+
├── styles/
|
|
513
|
+
│ └── index.css
|
|
514
|
+
└── index.ts
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### Building
|
|
518
|
+
|
|
519
|
+
The library is built using Vite in library mode:
|
|
520
|
+
|
|
521
|
+
```bash
|
|
522
|
+
npm run build
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
Output:
|
|
526
|
+
- `dist/index.js` - ES module bundle
|
|
527
|
+
- `dist/index.d.ts` - TypeScript declarations
|
|
528
|
+
- `dist/style.css` - Component styles
|
|
529
|
+
|
|
530
|
+
## Browser Support
|
|
531
|
+
|
|
532
|
+
- Chrome/Edge 90+
|
|
533
|
+
- Firefox 88+
|
|
534
|
+
- Safari 14+
|
|
535
|
+
|
|
536
|
+
## Contributing
|
|
537
|
+
|
|
538
|
+
Contributions are welcome! This library was extracted from the MIDI Volca Drum Editor project.
|
|
539
|
+
|
|
540
|
+
### Guidelines
|
|
541
|
+
|
|
542
|
+
1. Follow existing code style
|
|
543
|
+
2. Add TypeScript types for all props
|
|
544
|
+
3. Include CSS with each component
|
|
545
|
+
4. Test accessibility (keyboard navigation, ARIA labels)
|
|
546
|
+
5. Keep components generic (no app-specific logic)
|
|
547
|
+
|
|
548
|
+
## License
|
|
549
|
+
|
|
550
|
+
MIT © Hans Desmedt
|
|
551
|
+
|
|
552
|
+
## Related Projects
|
|
553
|
+
|
|
554
|
+
- [MIDI Volca Drum Editor](https://github.com/username/midi-volca-drum) - The parent project
|
|
555
|
+
- [Figma Make](https://www.figma.com/make) - Use production code in Figma prototypes
|
|
556
|
+
|
|
557
|
+
## Support
|
|
558
|
+
|
|
559
|
+
For issues and questions:
|
|
560
|
+
- [GitHub Issues](https://github.com/username/midi-volca-drum/issues)
|
|
561
|
+
- [Documentation](../../docs/)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Icon Registry
|
|
3
|
+
* Bundled icons with name-based selection
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Icon type - all available icon names
|
|
7
|
+
*/
|
|
8
|
+
export type IconName = 'sine' | 'saw' | 'noise-hp' | 'noise-lp' | 'noise-bp' | 'envelope' | 'lfo' | 'random' | 'ad' | 'exp' | 'multi';
|
|
9
|
+
/**
|
|
10
|
+
* Icon registry mapping names to SVG URLs
|
|
11
|
+
*/
|
|
12
|
+
export declare const ICONS: Record<IconName, string>;
|
|
13
|
+
/**
|
|
14
|
+
* Get icon URL by name
|
|
15
|
+
* @param name Icon name
|
|
16
|
+
* @returns SVG URL or undefined if not found
|
|
17
|
+
*/
|
|
18
|
+
export declare function getIcon(name: IconName): string | undefined;
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/assets/icons/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAcH;;GAEG;AACH,MAAM,MAAM,QAAQ,GAChB,MAAM,GACN,KAAK,GACL,UAAU,GACV,UAAU,GACV,UAAU,GACV,UAAU,GACV,KAAK,GACL,QAAQ,GACR,IAAI,GACJ,KAAK,GACL,OAAO,CAAC;AAEZ;;GAEG;AACH,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAiB1C,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAE1D"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accordion Component Styles
|
|
3
|
+
*/
|
|
4
|
+
export declare const collapsibleSection: string;
|
|
5
|
+
export declare const collapsibleHeader: string;
|
|
6
|
+
export declare const accordionTitle: string;
|
|
7
|
+
export declare const collapseToggle: string;
|
|
8
|
+
export declare const collapseIcon: string;
|
|
9
|
+
export declare const collapsibleContent: string;
|
|
10
|
+
export declare const collapsibleContentInner: string;
|
|
11
|
+
export declare const vertical: string;
|
|
12
|
+
export declare const horizontal: string;
|
|
13
|
+
export declare const collapsed: string;
|
|
14
|
+
export declare const expanded: string;
|
|
15
|
+
export declare const directionVariants: {
|
|
16
|
+
vertical: string;
|
|
17
|
+
horizontal: string;
|
|
18
|
+
};
|
|
19
|
+
export declare const stateVariants: {
|
|
20
|
+
collapsed: string;
|
|
21
|
+
expanded: string;
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=Accordion.css.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Accordion.css.d.ts","sourceRoot":"","sources":["../../../src/components/Accordion/Accordion.css.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,eAAO,MAAM,kBAAkB,QAG7B,CAAC;AAEH,eAAO,MAAM,iBAAiB,QAsB5B,CAAC;AAEH,eAAO,MAAM,cAAc,QAKzB,CAAC;AAEH,eAAO,MAAM,cAAc,QASzB,CAAC;AAEH,eAAO,MAAM,YAAY,QAGvB,CAAC;AAEH,eAAO,MAAM,kBAAkB,QAAY,CAAC;AAC5C,eAAO,MAAM,uBAAuB,QAAY,CAAC;AAGjD,eAAO,MAAM,QAAQ,QAAY,CAAC;AAgBlC,eAAO,MAAM,UAAU,QAAY,CAAC;AA8BpC,eAAO,MAAM,SAAS,QAAY,CAAC;AACnC,eAAO,MAAM,QAAQ,QAAY,CAAC;AAmClC,eAAO,MAAM,iBAAiB;;;CAG7B,CAAC;AAEF,eAAO,MAAM,aAAa;;;CAGzB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accordion Component
|
|
3
|
+
* Collapsible section with optional persistence
|
|
4
|
+
* Keyboard accessible with smooth animations
|
|
5
|
+
*/
|
|
6
|
+
import { ReactNode } from 'react';
|
|
7
|
+
export interface AccordionProps {
|
|
8
|
+
id: string;
|
|
9
|
+
title: string;
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
defaultExpanded?: boolean;
|
|
12
|
+
expanded?: boolean;
|
|
13
|
+
onToggle?: (expanded: boolean) => void;
|
|
14
|
+
className?: string;
|
|
15
|
+
direction?: 'vertical' | 'horizontal';
|
|
16
|
+
persistState?: boolean;
|
|
17
|
+
storageKey?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const Accordion: import("react").MemoExoticComponent<({ id, title, children, defaultExpanded, expanded: controlledExpanded, onToggle, className, direction, persistState, storageKey, }: AccordionProps) => import("react/jsx-runtime").JSX.Element>;
|
|
20
|
+
//# sourceMappingURL=Accordion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Accordion.d.ts","sourceRoot":"","sources":["../../../src/components/Accordion/Accordion.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAA0C,MAAM,OAAO,CAAC;AAG1E,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;IACtC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,SAAS,0KAYjB,cAAc,6CAyElB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Accordion/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AppHeader Component Styles
|
|
3
|
+
*/
|
|
4
|
+
export declare const header: string;
|
|
5
|
+
export declare const title: string;
|
|
6
|
+
export declare const actions: string;
|
|
7
|
+
export declare const iconButton: string;
|
|
8
|
+
export declare const infoIcon: string;
|
|
9
|
+
export declare const infoIconText: string;
|
|
10
|
+
//# sourceMappingURL=AppHeader.css.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AppHeader.css.d.ts","sourceRoot":"","sources":["../../../src/components/AppHeader/AppHeader.css.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,eAAO,MAAM,MAAM,QAMjB,CAAC;AAEH,eAAO,MAAM,KAAK,QAOhB,CAAC;AAEH,eAAO,MAAM,OAAO,QAIlB,CAAC;AAEH,eAAO,MAAM,UAAU,QAerB,CAAC;AAEH,eAAO,MAAM,QAAQ,QAQnB,CAAC;AAEH,eAAO,MAAM,YAAY,QAKvB,CAAC"}
|