riffscore 1.0.0-alpha.2
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 +102 -0
- package/dist/index.d.mts +341 -0
- package/dist/index.d.ts +341 -0
- package/dist/index.js +13793 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +13761 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +83 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Joseph Kotvas
|
|
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,102 @@
|
|
|
1
|
+
# RiffScore
|
|
2
|
+
|
|
3
|
+
**RiffScore** is a self-hostable, embeddable sheet music editor for React.
|
|
4
|
+
|
|
5
|
+
Unlike commercial platforms that require users to leave your site or pay subscription fees, RiffScore allows you to embed interactive, editable scores directly into your application.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install riffscore
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { RiffScore } from 'riffscore';
|
|
17
|
+
|
|
18
|
+
function App() {
|
|
19
|
+
return <RiffScore />;
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
That's it! RiffScore renders a fully interactive grand staff editor with sensible defaults.
|
|
24
|
+
|
|
25
|
+
### With Configuration
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
<RiffScore config={{
|
|
29
|
+
score: {
|
|
30
|
+
staff: 'treble', // 'grand' | 'treble' | 'bass'
|
|
31
|
+
measureCount: 4,
|
|
32
|
+
keySignature: 'G'
|
|
33
|
+
}
|
|
34
|
+
}} />
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Read-Only Mode
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
<RiffScore config={{
|
|
41
|
+
ui: { showToolbar: false },
|
|
42
|
+
interaction: { isEnabled: false }
|
|
43
|
+
}} />
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
See the [Configuration Guide](./docs/CONFIGURATION.md) for all available options.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Documentation
|
|
51
|
+
|
|
52
|
+
| Guide | Description |
|
|
53
|
+
|-------|-------------|
|
|
54
|
+
| 📖 [Configuration](./docs/CONFIGURATION.md) | Complete API reference for config options |
|
|
55
|
+
| 📘 [Architecture](./docs/ARCHITECTURE.md) | Technical reference for developers |
|
|
56
|
+
| 🎨 [Interaction Design](./docs/INTERACTION.md) | Guide to the intuitive editing behavior |
|
|
57
|
+
| 🤝 [Contributing](./docs/CONTRIBUTING.md) | How to set up and contribute to the project |
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Features
|
|
62
|
+
|
|
63
|
+
* **Self-Hostable**: No external dependencies or platform lock-in.
|
|
64
|
+
* **Embeddable**: Drop it into any React application.
|
|
65
|
+
* **Configurable**: Full control over UI, interactions, and score content.
|
|
66
|
+
* **SMuFL Compliance**: Beautiful engraving using the [Bravura](https://github.com/steinbergmedia/bravura) font.
|
|
67
|
+
* **Interactive**: Full editing capabilities right in the browser.
|
|
68
|
+
* **Music Engine**: Powered by [Tonal.js](https://github.com/tonaljs/tonal) for music theory logic and [Tone.js](https://tonejs.github.io/) for accurate browser-based playback.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Repository Structure
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
riffscore/
|
|
76
|
+
├── src/ ← Library source
|
|
77
|
+
├── demo/ ← Next.js demo app
|
|
78
|
+
├── dist/ ← Built library (ESM/CJS/DTS)
|
|
79
|
+
└── tsup.config.ts
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Development
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# Install dependencies
|
|
86
|
+
npm install
|
|
87
|
+
cd demo && npm install
|
|
88
|
+
|
|
89
|
+
# Build library
|
|
90
|
+
npm run build
|
|
91
|
+
|
|
92
|
+
# Run demo
|
|
93
|
+
npm run demo:dev
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Coming Soon
|
|
99
|
+
|
|
100
|
+
* **Imperative API**: Programmatically control the score (e.g., `score.addNote(...)`)
|
|
101
|
+
* **Chord Symbols**: Input and playback for lead sheets
|
|
102
|
+
* **Import**: MusicXML import
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import react__default, { ReactNode } from 'react';
|
|
3
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
declare const THEMES: {
|
|
6
|
+
readonly DARK: {
|
|
7
|
+
accent: "#1DA59C";
|
|
8
|
+
background: "#1e293b";
|
|
9
|
+
panelBackground: "rgba(30, 41, 59, 0.8)";
|
|
10
|
+
text: "#e2e8f0";
|
|
11
|
+
secondaryText: "hsla(215, 20%, 65%, 1.00)";
|
|
12
|
+
border: "rgba(255, 255, 255, 0.1)";
|
|
13
|
+
buttonBackground: "rgba(30, 41, 59, 0.8)";
|
|
14
|
+
buttonHoverBackground: "hsla(218, 33%, 28%, 1.00)";
|
|
15
|
+
score: {
|
|
16
|
+
line: "hsla(215, 16%, 47%, 1.00)";
|
|
17
|
+
note: "#e2e8f0";
|
|
18
|
+
fill: "#e2e8f0";
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
readonly COOL: {
|
|
22
|
+
accent: "#22d3ee";
|
|
23
|
+
background: "#0f172a";
|
|
24
|
+
panelBackground: "rgba(15, 23, 42, 0.8)";
|
|
25
|
+
text: "#bfdbfe";
|
|
26
|
+
secondaryText: "#60a5fa";
|
|
27
|
+
border: "rgba(255, 255, 255, 0.1)";
|
|
28
|
+
buttonBackground: "rgba(15, 23, 42, 0.8)";
|
|
29
|
+
buttonHoverBackground: "#1e3a8a";
|
|
30
|
+
score: {
|
|
31
|
+
line: "#60a5fa";
|
|
32
|
+
note: "#bfdbfe";
|
|
33
|
+
fill: "#bfdbfe";
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
readonly WARM: {
|
|
37
|
+
accent: "#fb923c";
|
|
38
|
+
background: "#1c1917";
|
|
39
|
+
panelBackground: "rgba(28, 25, 23, 0.8)";
|
|
40
|
+
text: "#e7e5e4";
|
|
41
|
+
secondaryText: "#a8a29e";
|
|
42
|
+
border: "rgba(255, 255, 255, 0.1)";
|
|
43
|
+
buttonBackground: "rgba(28, 25, 23, 0.8)";
|
|
44
|
+
buttonHoverBackground: "#292524";
|
|
45
|
+
score: {
|
|
46
|
+
line: "#78716c";
|
|
47
|
+
note: "#e7e5e4";
|
|
48
|
+
fill: "#e7e5e4";
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
readonly LIGHT: {
|
|
52
|
+
accent: "#1DA59C";
|
|
53
|
+
background: string;
|
|
54
|
+
panelBackground: string;
|
|
55
|
+
text: "#1e293b";
|
|
56
|
+
secondaryText: "hsla(215, 16%, 47%, 1.00)";
|
|
57
|
+
border: string;
|
|
58
|
+
buttonBackground: string;
|
|
59
|
+
buttonHoverBackground: string;
|
|
60
|
+
score: {
|
|
61
|
+
line: "hsla(215, 20%, 65%, 1.00)";
|
|
62
|
+
note: string;
|
|
63
|
+
fill: string;
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
type ThemeName = keyof typeof THEMES;
|
|
68
|
+
interface Theme {
|
|
69
|
+
accent: string;
|
|
70
|
+
background: string;
|
|
71
|
+
panelBackground: string;
|
|
72
|
+
text: string;
|
|
73
|
+
secondaryText: string;
|
|
74
|
+
border: string;
|
|
75
|
+
buttonBackground: string;
|
|
76
|
+
buttonHoverBackground: string;
|
|
77
|
+
score: {
|
|
78
|
+
line: string;
|
|
79
|
+
note: string;
|
|
80
|
+
fill: string;
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Type definitions for the Sheet Music Editor
|
|
86
|
+
*
|
|
87
|
+
* This file defines the data model for scores, staves, measures, events, and notes.
|
|
88
|
+
* The model supports multiple staves for Grand Staff rendering.
|
|
89
|
+
*/
|
|
90
|
+
interface Note {
|
|
91
|
+
id: string | number;
|
|
92
|
+
pitch: string | null;
|
|
93
|
+
accidental?: 'sharp' | 'flat' | 'natural' | null;
|
|
94
|
+
tied?: boolean;
|
|
95
|
+
isRest?: boolean;
|
|
96
|
+
}
|
|
97
|
+
interface ScoreEvent {
|
|
98
|
+
id: string | number;
|
|
99
|
+
duration: string;
|
|
100
|
+
dotted: boolean;
|
|
101
|
+
notes: Note[];
|
|
102
|
+
isRest?: boolean;
|
|
103
|
+
tuplet?: {
|
|
104
|
+
ratio: [number, number];
|
|
105
|
+
groupSize: number;
|
|
106
|
+
position: number;
|
|
107
|
+
baseDuration?: string;
|
|
108
|
+
id?: string;
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
interface Measure {
|
|
112
|
+
id: string | number;
|
|
113
|
+
events: ScoreEvent[];
|
|
114
|
+
isPickup?: boolean;
|
|
115
|
+
}
|
|
116
|
+
interface Staff {
|
|
117
|
+
id: string | number;
|
|
118
|
+
clef: 'treble' | 'bass' | 'grand';
|
|
119
|
+
keySignature: string;
|
|
120
|
+
measures: Measure[];
|
|
121
|
+
}
|
|
122
|
+
interface Score {
|
|
123
|
+
title: string;
|
|
124
|
+
timeSignature: string;
|
|
125
|
+
keySignature: string;
|
|
126
|
+
bpm: number;
|
|
127
|
+
staves: Staff[];
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Represents the current selection state in the editor.
|
|
131
|
+
* Supports Grand Staff by tracking which staff is selected.
|
|
132
|
+
*/
|
|
133
|
+
interface Selection {
|
|
134
|
+
staffIndex: number;
|
|
135
|
+
measureIndex: number | null;
|
|
136
|
+
eventId: string | number | null;
|
|
137
|
+
noteId: string | number | null;
|
|
138
|
+
selectedNotes: Array<{
|
|
139
|
+
staffIndex: number;
|
|
140
|
+
measureIndex: number;
|
|
141
|
+
eventId: string | number;
|
|
142
|
+
noteId: string | number | null;
|
|
143
|
+
}>;
|
|
144
|
+
anchor?: {
|
|
145
|
+
staffIndex: number;
|
|
146
|
+
measureIndex: number;
|
|
147
|
+
eventId: string | number;
|
|
148
|
+
noteId: string | number | null;
|
|
149
|
+
} | null;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Utility type for allowing partial nested objects
|
|
153
|
+
*/
|
|
154
|
+
type DeepPartial<T> = {
|
|
155
|
+
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* Staff template options for score generation
|
|
159
|
+
*/
|
|
160
|
+
type StaffTemplate = 'grand' | 'treble' | 'bass';
|
|
161
|
+
/**
|
|
162
|
+
* Configuration interface for RiffScore component.
|
|
163
|
+
* Supports two modes:
|
|
164
|
+
* - Generator Mode: Pass `staff` + `measureCount` to create blank scores
|
|
165
|
+
* - Render Mode: Pass `staves` array to load existing compositions
|
|
166
|
+
*/
|
|
167
|
+
/**
|
|
168
|
+
* Configuration interface for RiffScore component.
|
|
169
|
+
* Supports two modes:
|
|
170
|
+
* - Generator Mode: Pass `staff` + `measureCount` to create blank scores
|
|
171
|
+
* - Render Mode: Pass `staves` array to load existing compositions
|
|
172
|
+
*/
|
|
173
|
+
interface RiffScoreConfig {
|
|
174
|
+
ui: {
|
|
175
|
+
showToolbar: boolean;
|
|
176
|
+
scale: number;
|
|
177
|
+
theme?: ThemeName;
|
|
178
|
+
};
|
|
179
|
+
interaction: {
|
|
180
|
+
isEnabled: boolean;
|
|
181
|
+
enableKeyboard: boolean;
|
|
182
|
+
enablePlayback: boolean;
|
|
183
|
+
};
|
|
184
|
+
score: {
|
|
185
|
+
title: string;
|
|
186
|
+
bpm: number;
|
|
187
|
+
timeSignature: string;
|
|
188
|
+
keySignature: string;
|
|
189
|
+
staff?: StaffTemplate;
|
|
190
|
+
measureCount?: number;
|
|
191
|
+
staves?: Staff[];
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* RiffScore Component
|
|
197
|
+
*
|
|
198
|
+
* Configurable React component for rendering and interacting with musical scores.
|
|
199
|
+
* Supports two modes:
|
|
200
|
+
* - Generator Mode: Create blank scores from templates (staff + measureCount)
|
|
201
|
+
* - Render Mode: Load compositions from staves array
|
|
202
|
+
*/
|
|
203
|
+
|
|
204
|
+
interface RiffScoreProps {
|
|
205
|
+
config?: DeepPartial<RiffScoreConfig>;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* RiffScore - Configurable Music Notation Editor
|
|
209
|
+
*
|
|
210
|
+
* @example
|
|
211
|
+
* // Generator Mode - Create blank grand staff with 4 measures
|
|
212
|
+
* <RiffScore config={{ score: { staff: 'grand', measureCount: 4 } }} />
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* // Render Mode - Load existing composition
|
|
216
|
+
* <RiffScore config={{ score: { staves: myStaves } }} />
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* // Disable all interaction (read-only display)
|
|
220
|
+
* <RiffScore config={{ interaction: { isEnabled: false } }} />
|
|
221
|
+
*/
|
|
222
|
+
declare const RiffScore: react__default.FC<RiffScoreProps>;
|
|
223
|
+
|
|
224
|
+
interface ScoreEditorContentProps {
|
|
225
|
+
scale?: number;
|
|
226
|
+
label?: string;
|
|
227
|
+
showToolbar?: boolean;
|
|
228
|
+
enableKeyboard?: boolean;
|
|
229
|
+
enablePlayback?: boolean;
|
|
230
|
+
}
|
|
231
|
+
declare const ScoreEditorContent: ({ scale, label, showToolbar, enableKeyboard, enablePlayback, }: ScoreEditorContentProps) => react_jsx_runtime.JSX.Element;
|
|
232
|
+
declare const ScoreEditor: ({ scale, label, initialData, }: {
|
|
233
|
+
scale?: number;
|
|
234
|
+
label?: string;
|
|
235
|
+
initialData?: any;
|
|
236
|
+
}) => react_jsx_runtime.JSX.Element;
|
|
237
|
+
|
|
238
|
+
interface ThemeContextType {
|
|
239
|
+
theme: Theme;
|
|
240
|
+
themeName: ThemeName;
|
|
241
|
+
setTheme: (name: ThemeName) => void;
|
|
242
|
+
zoom: number;
|
|
243
|
+
setZoom: (zoom: number) => void;
|
|
244
|
+
}
|
|
245
|
+
declare const ThemeProvider: react__default.FC<{
|
|
246
|
+
children: react__default.ReactNode;
|
|
247
|
+
initialTheme?: ThemeName;
|
|
248
|
+
}>;
|
|
249
|
+
declare const useTheme: () => ThemeContextType;
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Input mode for entry - determines whether canvas clicks create notes or rests.
|
|
253
|
+
*/
|
|
254
|
+
type InputMode = 'NOTE' | 'REST';
|
|
255
|
+
|
|
256
|
+
interface Command {
|
|
257
|
+
type: string;
|
|
258
|
+
execute(score: Score): Score;
|
|
259
|
+
undo(score: Score): Score;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
type EditorState = 'SELECTION_READY' | 'ENTRY_READY' | 'IDLE';
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Main score logic orchestrator hook.
|
|
266
|
+
* Composes focused hooks for measure, note, modifier, and navigation actions.
|
|
267
|
+
*/
|
|
268
|
+
declare const useScoreLogic: (initialScore: any) => {
|
|
269
|
+
score: Score;
|
|
270
|
+
selection: Selection;
|
|
271
|
+
editorState: EditorState;
|
|
272
|
+
selectedDurations: string[];
|
|
273
|
+
selectedDots: boolean[];
|
|
274
|
+
selectedTies: boolean[];
|
|
275
|
+
selectedAccidentals: string[];
|
|
276
|
+
setSelection: react.Dispatch<react.SetStateAction<Selection>>;
|
|
277
|
+
previewNote: any;
|
|
278
|
+
setPreviewNote: react.Dispatch<any>;
|
|
279
|
+
history: Command[];
|
|
280
|
+
redoStack: Command[];
|
|
281
|
+
undo: () => void;
|
|
282
|
+
redo: () => void;
|
|
283
|
+
dispatch: (command: Command) => void;
|
|
284
|
+
activeDuration: string;
|
|
285
|
+
setActiveDuration: react.Dispatch<react.SetStateAction<string>>;
|
|
286
|
+
isDotted: boolean;
|
|
287
|
+
setIsDotted: react.Dispatch<react.SetStateAction<boolean>>;
|
|
288
|
+
activeAccidental: "sharp" | "flat" | "natural" | null;
|
|
289
|
+
activeTie: boolean;
|
|
290
|
+
inputMode: InputMode;
|
|
291
|
+
setInputMode: react.Dispatch<react.SetStateAction<InputMode>>;
|
|
292
|
+
toggleInputMode: () => void;
|
|
293
|
+
handleTimeSignatureChange: (newSig: string) => void;
|
|
294
|
+
handleKeySignatureChange: (newKey: string) => void;
|
|
295
|
+
addMeasure: () => void;
|
|
296
|
+
removeMeasure: () => void;
|
|
297
|
+
togglePickup: () => void;
|
|
298
|
+
setGrandStaff: () => void;
|
|
299
|
+
handleMeasureHover: (measureIndex: number | null, hit: any, pitch: string, staffIndex?: number) => void;
|
|
300
|
+
addNoteToMeasure: (measureIndex: number, newNote: any, shouldAutoAdvance?: boolean, placementOverride?: any) => void;
|
|
301
|
+
addChordToMeasure: (measureIndex: number, notes: any[], duration: string, dotted: boolean) => void;
|
|
302
|
+
deleteSelected: () => void;
|
|
303
|
+
handleNoteSelection: (measureIndex: number, eventId: string | number, noteId: string | number | null, staffIndex?: number, isMulti?: boolean, selectAllInEvent?: boolean, isShift?: boolean) => void;
|
|
304
|
+
handleDurationChange: (newDuration: string) => void;
|
|
305
|
+
handleDotToggle: () => void;
|
|
306
|
+
handleAccidentalToggle: (type: "flat" | "natural" | "sharp" | null) => void;
|
|
307
|
+
handleTieToggle: () => void;
|
|
308
|
+
currentQuantsPerMeasure: number;
|
|
309
|
+
scoreRef: react.RefObject<Score>;
|
|
310
|
+
checkDurationValidity: (targetDuration: string) => boolean;
|
|
311
|
+
checkDotValidity: () => boolean;
|
|
312
|
+
updateNotePitch: (measureIndex: number, eventId: string | number, noteId: string | number, newPitch: string) => void;
|
|
313
|
+
applyTuplet: (ratio: [number, number], groupSize: number) => boolean;
|
|
314
|
+
removeTuplet: () => boolean;
|
|
315
|
+
canApplyTuplet: (groupSize: number) => boolean;
|
|
316
|
+
activeTupletRatio: [number, number] | null;
|
|
317
|
+
transposeSelection: (direction: string, isShift: boolean) => void;
|
|
318
|
+
moveSelection: (direction: string, isShift: boolean) => void;
|
|
319
|
+
switchStaff: (direction: "up" | "down") => void;
|
|
320
|
+
focusScore: () => void;
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
type ScoreContextType = ReturnType<typeof useScoreLogic> & {
|
|
324
|
+
pendingClefChange: {
|
|
325
|
+
targetClef: 'treble' | 'bass';
|
|
326
|
+
} | null;
|
|
327
|
+
setPendingClefChange: react__default.Dispatch<react__default.SetStateAction<{
|
|
328
|
+
targetClef: 'treble' | 'bass';
|
|
329
|
+
} | null>>;
|
|
330
|
+
handleClefChange: (val: string) => void;
|
|
331
|
+
};
|
|
332
|
+
declare const useScoreContext: () => ScoreContextType;
|
|
333
|
+
interface ScoreProviderProps {
|
|
334
|
+
children: ReactNode;
|
|
335
|
+
initialScore?: any;
|
|
336
|
+
}
|
|
337
|
+
declare const ScoreProvider: react__default.FC<ScoreProviderProps>;
|
|
338
|
+
|
|
339
|
+
declare const ConfigMenu: () => react_jsx_runtime.JSX.Element;
|
|
340
|
+
|
|
341
|
+
export { ConfigMenu, type Measure, type Note, RiffScore, type RiffScoreConfig, type Score, ScoreEditor, ScoreEditorContent, type ScoreEvent, ScoreProvider, type Selection, type Staff, ThemeProvider, useScoreContext, useTheme };
|