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/dist/index.d.ts
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 };
|