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.
Files changed (144) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +561 -0
  3. package/dist/assets/icons/index.d.ts +19 -0
  4. package/dist/assets/icons/index.d.ts.map +1 -0
  5. package/dist/components/Accordion/Accordion.css.d.ts +23 -0
  6. package/dist/components/Accordion/Accordion.css.d.ts.map +1 -0
  7. package/dist/components/Accordion/Accordion.d.ts +20 -0
  8. package/dist/components/Accordion/Accordion.d.ts.map +1 -0
  9. package/dist/components/Accordion/index.d.ts +3 -0
  10. package/dist/components/Accordion/index.d.ts.map +1 -0
  11. package/dist/components/AppHeader/AppHeader.css.d.ts +10 -0
  12. package/dist/components/AppHeader/AppHeader.css.d.ts.map +1 -0
  13. package/dist/components/AppHeader/AppHeader.d.ts +20 -0
  14. package/dist/components/AppHeader/AppHeader.d.ts.map +1 -0
  15. package/dist/components/AppHeader/index.d.ts +3 -0
  16. package/dist/components/AppHeader/index.d.ts.map +1 -0
  17. package/dist/components/AppLayout/AppLayout.css.d.ts +7 -0
  18. package/dist/components/AppLayout/AppLayout.css.d.ts.map +1 -0
  19. package/dist/components/AppLayout/AppLayout.d.ts +18 -0
  20. package/dist/components/AppLayout/AppLayout.d.ts.map +1 -0
  21. package/dist/components/AppLayout/index.d.ts +3 -0
  22. package/dist/components/AppLayout/index.d.ts.map +1 -0
  23. package/dist/components/Button/Button.css.d.ts +7 -0
  24. package/dist/components/Button/Button.css.d.ts.map +1 -0
  25. package/dist/components/Button/Button.d.ts +17 -0
  26. package/dist/components/Button/Button.d.ts.map +1 -0
  27. package/dist/components/Button/index.d.ts +3 -0
  28. package/dist/components/Button/index.d.ts.map +1 -0
  29. package/dist/components/Card/Card.css.d.ts +9 -0
  30. package/dist/components/Card/Card.css.d.ts.map +1 -0
  31. package/dist/components/Card/Card.d.ts +22 -0
  32. package/dist/components/Card/Card.d.ts.map +1 -0
  33. package/dist/components/Card/index.d.ts +3 -0
  34. package/dist/components/Card/index.d.ts.map +1 -0
  35. package/dist/components/EmptyState/EmptyState.css.d.ts +12 -0
  36. package/dist/components/EmptyState/EmptyState.css.d.ts.map +1 -0
  37. package/dist/components/EmptyState/EmptyState.d.ts +24 -0
  38. package/dist/components/EmptyState/EmptyState.d.ts.map +1 -0
  39. package/dist/components/EmptyState/index.d.ts +3 -0
  40. package/dist/components/EmptyState/index.d.ts.map +1 -0
  41. package/dist/components/ErrorDisplay/ErrorDisplay.css.d.ts +14 -0
  42. package/dist/components/ErrorDisplay/ErrorDisplay.css.d.ts.map +1 -0
  43. package/dist/components/ErrorDisplay/ErrorDisplay.d.ts +28 -0
  44. package/dist/components/ErrorDisplay/ErrorDisplay.d.ts.map +1 -0
  45. package/dist/components/ErrorDisplay/index.d.ts +3 -0
  46. package/dist/components/ErrorDisplay/index.d.ts.map +1 -0
  47. package/dist/components/Modal/Modal.css.d.ts +14 -0
  48. package/dist/components/Modal/Modal.css.d.ts.map +1 -0
  49. package/dist/components/Modal/Modal.d.ts +17 -0
  50. package/dist/components/Modal/Modal.d.ts.map +1 -0
  51. package/dist/components/Modal/index.d.ts +3 -0
  52. package/dist/components/Modal/index.d.ts.map +1 -0
  53. package/dist/components/ModalContent/ModalContent.css.d.ts +23 -0
  54. package/dist/components/ModalContent/ModalContent.css.d.ts.map +1 -0
  55. package/dist/components/ModalContent/ModalContent.d.ts +58 -0
  56. package/dist/components/ModalContent/ModalContent.d.ts.map +1 -0
  57. package/dist/components/ModalContent/index.d.ts +3 -0
  58. package/dist/components/ModalContent/index.d.ts.map +1 -0
  59. package/dist/components/ParameterDisplay/ParameterDisplay.css.d.ts +17 -0
  60. package/dist/components/ParameterDisplay/ParameterDisplay.css.d.ts.map +1 -0
  61. package/dist/components/ParameterDisplay/ParameterDisplay.d.ts +29 -0
  62. package/dist/components/ParameterDisplay/ParameterDisplay.d.ts.map +1 -0
  63. package/dist/components/ParameterDisplay/index.d.ts +3 -0
  64. package/dist/components/ParameterDisplay/index.d.ts.map +1 -0
  65. package/dist/components/PartEditorLayout/PartEditorLayout.css.d.ts +19 -0
  66. package/dist/components/PartEditorLayout/PartEditorLayout.css.d.ts.map +1 -0
  67. package/dist/components/PartEditorLayout/PartEditorLayout.d.ts +53 -0
  68. package/dist/components/PartEditorLayout/PartEditorLayout.d.ts.map +1 -0
  69. package/dist/components/PartEditorLayout/index.d.ts +3 -0
  70. package/dist/components/PartEditorLayout/index.d.ts.map +1 -0
  71. package/dist/components/PartTitle/PartTitle.css.d.ts +11 -0
  72. package/dist/components/PartTitle/PartTitle.css.d.ts.map +1 -0
  73. package/dist/components/PartTitle/PartTitle.d.ts +30 -0
  74. package/dist/components/PartTitle/PartTitle.d.ts.map +1 -0
  75. package/dist/components/PartTitle/index.d.ts +3 -0
  76. package/dist/components/PartTitle/index.d.ts.map +1 -0
  77. package/dist/components/Parts/Parts.css.d.ts +8 -0
  78. package/dist/components/Parts/Parts.css.d.ts.map +1 -0
  79. package/dist/components/Parts/Parts.d.ts +16 -0
  80. package/dist/components/Parts/Parts.d.ts.map +1 -0
  81. package/dist/components/Parts/index.d.ts +3 -0
  82. package/dist/components/Parts/index.d.ts.map +1 -0
  83. package/dist/components/Processing/Processing.css.d.ts +8 -0
  84. package/dist/components/Processing/Processing.css.d.ts.map +1 -0
  85. package/dist/components/Processing/Processing.d.ts +20 -0
  86. package/dist/components/Processing/Processing.d.ts.map +1 -0
  87. package/dist/components/Processing/index.d.ts +3 -0
  88. package/dist/components/Processing/index.d.ts.map +1 -0
  89. package/dist/components/RadioButton/RadioButton.css.d.ts +13 -0
  90. package/dist/components/RadioButton/RadioButton.css.d.ts.map +1 -0
  91. package/dist/components/RadioButton/RadioButton.d.ts +25 -0
  92. package/dist/components/RadioButton/RadioButton.d.ts.map +1 -0
  93. package/dist/components/RadioButton/index.d.ts +3 -0
  94. package/dist/components/RadioButton/index.d.ts.map +1 -0
  95. package/dist/components/RadioGroup/RadioGroup.css.d.ts +8 -0
  96. package/dist/components/RadioGroup/RadioGroup.css.d.ts.map +1 -0
  97. package/dist/components/RadioGroup/RadioGroup.d.ts +21 -0
  98. package/dist/components/RadioGroup/RadioGroup.d.ts.map +1 -0
  99. package/dist/components/RadioGroup/index.d.ts +3 -0
  100. package/dist/components/RadioGroup/index.d.ts.map +1 -0
  101. package/dist/components/Slider/Slider.css.d.ts +15 -0
  102. package/dist/components/Slider/Slider.css.d.ts.map +1 -0
  103. package/dist/components/Slider/Slider.d.ts +20 -0
  104. package/dist/components/Slider/Slider.d.ts.map +1 -0
  105. package/dist/components/Slider/index.d.ts +3 -0
  106. package/dist/components/Slider/index.d.ts.map +1 -0
  107. package/dist/components/Stack/Stack.css.d.ts +10 -0
  108. package/dist/components/Stack/Stack.css.d.ts.map +1 -0
  109. package/dist/components/Stack/Stack.d.ts +24 -0
  110. package/dist/components/Stack/Stack.d.ts.map +1 -0
  111. package/dist/components/Stack/index.d.ts +3 -0
  112. package/dist/components/Stack/index.d.ts.map +1 -0
  113. package/dist/components/Status/Status.css.d.ts +49 -0
  114. package/dist/components/Status/Status.css.d.ts.map +1 -0
  115. package/dist/components/Status/Status.d.ts +28 -0
  116. package/dist/components/Status/Status.d.ts.map +1 -0
  117. package/dist/components/Status/index.d.ts +3 -0
  118. package/dist/components/Status/index.d.ts.map +1 -0
  119. package/dist/components/StepList/StepList.css.d.ts +12 -0
  120. package/dist/components/StepList/StepList.css.d.ts.map +1 -0
  121. package/dist/components/StepList/StepList.d.ts +19 -0
  122. package/dist/components/StepList/StepList.d.ts.map +1 -0
  123. package/dist/components/StepList/index.d.ts +3 -0
  124. package/dist/components/StepList/index.d.ts.map +1 -0
  125. package/dist/components/Switch/Switch.css.d.ts +9 -0
  126. package/dist/components/Switch/Switch.css.d.ts.map +1 -0
  127. package/dist/components/Switch/Switch.d.ts +17 -0
  128. package/dist/components/Switch/Switch.d.ts.map +1 -0
  129. package/dist/components/Switch/index.d.ts +3 -0
  130. package/dist/components/Switch/index.d.ts.map +1 -0
  131. package/dist/components/Toast/Toast.css.d.ts +6 -0
  132. package/dist/components/Toast/Toast.css.d.ts.map +1 -0
  133. package/dist/components/Toast/Toast.d.ts +10 -0
  134. package/dist/components/Toast/Toast.d.ts.map +1 -0
  135. package/dist/components/Toast/index.d.ts +2 -0
  136. package/dist/components/Toast/index.d.ts.map +1 -0
  137. package/dist/index.d.ts +51 -0
  138. package/dist/index.d.ts.map +1 -0
  139. package/dist/index.js +852 -0
  140. package/dist/index.js.map +1 -0
  141. package/dist/style.css +1 -0
  142. package/dist/utils/toast.d.ts +15 -0
  143. package/dist/utils/toast.d.ts.map +1 -0
  144. 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
+ [![npm version](https://img.shields.io/npm/v/@midi-volca-drum/ui-components.svg)](https://www.npmjs.com/package/@midi-volca-drum/ui-components)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](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,3 @@
1
+ export { Accordion } from './Accordion';
2
+ export type { AccordionProps } from './Accordion';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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"}