@dawcore/components 0.0.18 → 0.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +171 -114
- package/dist/index.d.ts +171 -114
- package/dist/index.js +201 -42
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +181 -19
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -5
package/dist/index.d.mts
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import * as lit from 'lit';
|
|
2
2
|
import { LitElement, PropertyValues, ReactiveController, ReactiveControllerHost } from 'lit';
|
|
3
|
-
import { MidiNoteData,
|
|
3
|
+
import { MidiNoteData, RenderMode, SpectrogramConfig, Peaks, Bits, FadeType, PeakData, MeterEntry, SnapTo, ColorMapValue, ClipTrack, KeyboardShortcut } from '@waveform-playlist/core';
|
|
4
4
|
import WaveformData from 'waveform-data';
|
|
5
5
|
import { PlayoutAdapter, PlaylistEngine } from '@waveform-playlist/engine';
|
|
6
|
+
import { MidiLoadOptions, MidiLoadResult } from '@dawcore/midi';
|
|
6
7
|
import { ClipRegistration, CanvasRegistration, ViewportState } from '@dawcore/spectrogram';
|
|
7
8
|
|
|
8
9
|
declare class DawClipElement extends LitElement {
|
|
9
10
|
src: string;
|
|
10
11
|
peaksSrc: string;
|
|
12
|
+
/**
|
|
13
|
+
* Timeline position in seconds. JS property only — NOT reflected to the
|
|
14
|
+
* `start` attribute (Lit's `reflect` defaults to false). Tests that need
|
|
15
|
+
* to assert clip position must read this property directly; reading
|
|
16
|
+
* `el.getAttribute('start')` returns `null` regardless of correctness.
|
|
17
|
+
*/
|
|
11
18
|
start: number;
|
|
12
19
|
duration: number;
|
|
13
20
|
offset: number;
|
|
@@ -39,113 +46,6 @@ declare global {
|
|
|
39
46
|
}
|
|
40
47
|
}
|
|
41
48
|
|
|
42
|
-
type TrackRenderMode = 'waveform' | 'piano-roll' | 'spectrogram';
|
|
43
|
-
interface TrackDescriptor {
|
|
44
|
-
name: string;
|
|
45
|
-
src: string;
|
|
46
|
-
volume: number;
|
|
47
|
-
pan: number;
|
|
48
|
-
muted: boolean;
|
|
49
|
-
soloed: boolean;
|
|
50
|
-
renderMode: TrackRenderMode;
|
|
51
|
-
spectrogramConfig?: SpectrogramConfig | null;
|
|
52
|
-
clips: ClipDescriptor[];
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Common fields shared by all clip descriptors regardless of source.
|
|
56
|
-
*/
|
|
57
|
-
interface BaseClipDescriptor {
|
|
58
|
-
src: string;
|
|
59
|
-
peaksSrc: string;
|
|
60
|
-
start: number;
|
|
61
|
-
duration: number;
|
|
62
|
-
offset: number;
|
|
63
|
-
gain: number;
|
|
64
|
-
name: string;
|
|
65
|
-
fadeIn: number;
|
|
66
|
-
fadeOut: number;
|
|
67
|
-
fadeType: FadeType;
|
|
68
|
-
midiNotes: MidiNoteData[] | null;
|
|
69
|
-
midiChannel: number | null;
|
|
70
|
-
midiProgram: number | null;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* A clip descriptor sourced from a `<daw-clip>` DOM element. `clipId` is
|
|
74
|
-
* always set — `<daw-clip>.clipId` is a `crypto.randomUUID()` generated at
|
|
75
|
-
* construction. Engine `clip.id` is aligned with this id in `_loadTrack`
|
|
76
|
-
* and `_loadAndAppendClip` so DOM and engine reference the same clip.
|
|
77
|
-
*/
|
|
78
|
-
interface DomClipDescriptor extends BaseClipDescriptor {
|
|
79
|
-
kind: 'dom';
|
|
80
|
-
clipId: string;
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* A clip descriptor synthesized from a non-DOM source — file drops, the
|
|
84
|
-
* `<daw-track src>` shorthand fallback, or recording-clip insertion. No
|
|
85
|
-
* `clipId` because there's no DOM element to align with; the engine
|
|
86
|
-
* generates its own id at clip-creation time.
|
|
87
|
-
*/
|
|
88
|
-
interface DropClipDescriptor extends BaseClipDescriptor {
|
|
89
|
-
kind: 'drop';
|
|
90
|
-
}
|
|
91
|
-
type ClipDescriptor = DomClipDescriptor | DropClipDescriptor;
|
|
92
|
-
/**
|
|
93
|
-
* Type predicate for the `'dom'` discriminator. Use to narrow a
|
|
94
|
-
* `ClipDescriptor` to `DomClipDescriptor` (which has `clipId`) without
|
|
95
|
-
* inline `c.kind === 'dom'` repetition.
|
|
96
|
-
*/
|
|
97
|
-
declare function isDomClip(desc: ClipDescriptor): desc is DomClipDescriptor;
|
|
98
|
-
/**
|
|
99
|
-
* Public input shape for `editor.addTrack(config)`. All fields optional —
|
|
100
|
-
* defaults match the declarative `<daw-track>` defaults.
|
|
101
|
-
*/
|
|
102
|
-
interface TrackConfig {
|
|
103
|
-
name?: string;
|
|
104
|
-
volume?: number;
|
|
105
|
-
pan?: number;
|
|
106
|
-
muted?: boolean;
|
|
107
|
-
soloed?: boolean;
|
|
108
|
-
renderMode?: TrackRenderMode;
|
|
109
|
-
spectrogramConfig?: SpectrogramConfig | null;
|
|
110
|
-
clips?: ClipConfig[];
|
|
111
|
-
/**
|
|
112
|
-
* Convenience: creates a single piano-roll `<daw-clip>` child with these
|
|
113
|
-
* notes and sets `render-mode="piano-roll"` on the track. Equivalent to
|
|
114
|
-
* passing `{ renderMode: 'piano-roll', clips: [{ midiNotes, midiChannel, midiProgram }] }`.
|
|
115
|
-
* An explicit `renderMode` takes precedence over the inferred `'piano-roll'`.
|
|
116
|
-
*
|
|
117
|
-
* Creation-only — ignored by `updateTrack`. To modify notes after the
|
|
118
|
-
* track is built, use `editor.updateClip(trackId, clipId, { midiNotes })` or
|
|
119
|
-
* mutate the `<daw-clip>` element's `midiNotes` property directly.
|
|
120
|
-
*/
|
|
121
|
-
midi?: {
|
|
122
|
-
notes: MidiNoteData[];
|
|
123
|
-
channel?: number;
|
|
124
|
-
program?: number;
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Public input shape for clips passed via `TrackConfig.clips` or
|
|
129
|
-
* `editor.addClip(trackId, config)`. `src` is optional to support MIDI clips
|
|
130
|
-
* with no audio source. Other fields default to the matching `<daw-clip>`
|
|
131
|
-
* attribute defaults.
|
|
132
|
-
*/
|
|
133
|
-
interface ClipConfig {
|
|
134
|
-
src?: string;
|
|
135
|
-
peaksSrc?: string;
|
|
136
|
-
start?: number;
|
|
137
|
-
duration?: number;
|
|
138
|
-
offset?: number;
|
|
139
|
-
gain?: number;
|
|
140
|
-
name?: string;
|
|
141
|
-
fadeIn?: number;
|
|
142
|
-
fadeOut?: number;
|
|
143
|
-
fadeType?: FadeType;
|
|
144
|
-
midiNotes?: MidiNoteData[];
|
|
145
|
-
midiChannel?: number;
|
|
146
|
-
midiProgram?: number;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
49
|
declare class DawTrackElement extends LitElement {
|
|
150
50
|
src: string;
|
|
151
51
|
name: string;
|
|
@@ -153,7 +53,9 @@ declare class DawTrackElement extends LitElement {
|
|
|
153
53
|
pan: number;
|
|
154
54
|
muted: boolean;
|
|
155
55
|
soloed: boolean;
|
|
156
|
-
renderMode:
|
|
56
|
+
get renderMode(): RenderMode;
|
|
57
|
+
set renderMode(value: RenderMode);
|
|
58
|
+
private _renderMode;
|
|
157
59
|
spectrogramConfig: SpectrogramConfig | null;
|
|
158
60
|
readonly trackId: `${string}-${string}-${string}-${string}-${string}`;
|
|
159
61
|
createRenderRoot(): this;
|
|
@@ -353,6 +255,113 @@ declare global {
|
|
|
353
255
|
}
|
|
354
256
|
}
|
|
355
257
|
|
|
258
|
+
type TrackRenderMode = RenderMode;
|
|
259
|
+
interface TrackDescriptor {
|
|
260
|
+
name: string;
|
|
261
|
+
src: string;
|
|
262
|
+
volume: number;
|
|
263
|
+
pan: number;
|
|
264
|
+
muted: boolean;
|
|
265
|
+
soloed: boolean;
|
|
266
|
+
renderMode: TrackRenderMode;
|
|
267
|
+
spectrogramConfig?: SpectrogramConfig | null;
|
|
268
|
+
clips: ClipDescriptor[];
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Common fields shared by all clip descriptors regardless of source.
|
|
272
|
+
*/
|
|
273
|
+
interface BaseClipDescriptor {
|
|
274
|
+
src: string;
|
|
275
|
+
peaksSrc: string;
|
|
276
|
+
start: number;
|
|
277
|
+
duration: number;
|
|
278
|
+
offset: number;
|
|
279
|
+
gain: number;
|
|
280
|
+
name: string;
|
|
281
|
+
fadeIn: number;
|
|
282
|
+
fadeOut: number;
|
|
283
|
+
fadeType: FadeType;
|
|
284
|
+
midiNotes: MidiNoteData[] | null;
|
|
285
|
+
midiChannel: number | null;
|
|
286
|
+
midiProgram: number | null;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* A clip descriptor sourced from a `<daw-clip>` DOM element. `clipId` is
|
|
290
|
+
* always set — `<daw-clip>.clipId` is a `crypto.randomUUID()` generated at
|
|
291
|
+
* construction. Engine `clip.id` is aligned with this id in `_loadTrack`
|
|
292
|
+
* and `_loadAndAppendClip` so DOM and engine reference the same clip.
|
|
293
|
+
*/
|
|
294
|
+
interface DomClipDescriptor extends BaseClipDescriptor {
|
|
295
|
+
kind: 'dom';
|
|
296
|
+
clipId: string;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* A clip descriptor synthesized from a non-DOM source — file drops, the
|
|
300
|
+
* `<daw-track src>` shorthand fallback, or recording-clip insertion. No
|
|
301
|
+
* `clipId` because there's no DOM element to align with; the engine
|
|
302
|
+
* generates its own id at clip-creation time.
|
|
303
|
+
*/
|
|
304
|
+
interface DropClipDescriptor extends BaseClipDescriptor {
|
|
305
|
+
kind: 'drop';
|
|
306
|
+
}
|
|
307
|
+
type ClipDescriptor = DomClipDescriptor | DropClipDescriptor;
|
|
308
|
+
/**
|
|
309
|
+
* Type predicate for the `'dom'` discriminator. Use to narrow a
|
|
310
|
+
* `ClipDescriptor` to `DomClipDescriptor` (which has `clipId`) without
|
|
311
|
+
* inline `c.kind === 'dom'` repetition.
|
|
312
|
+
*/
|
|
313
|
+
declare function isDomClip(desc: ClipDescriptor): desc is DomClipDescriptor;
|
|
314
|
+
/**
|
|
315
|
+
* Public input shape for `editor.addTrack(config)`. All fields optional —
|
|
316
|
+
* defaults match the declarative `<daw-track>` defaults.
|
|
317
|
+
*/
|
|
318
|
+
interface TrackConfig {
|
|
319
|
+
name?: string;
|
|
320
|
+
volume?: number;
|
|
321
|
+
pan?: number;
|
|
322
|
+
muted?: boolean;
|
|
323
|
+
soloed?: boolean;
|
|
324
|
+
renderMode?: TrackRenderMode;
|
|
325
|
+
spectrogramConfig?: SpectrogramConfig | null;
|
|
326
|
+
clips?: ClipConfig[];
|
|
327
|
+
/**
|
|
328
|
+
* Convenience: creates a single piano-roll `<daw-clip>` child with these
|
|
329
|
+
* notes and sets `render-mode="piano-roll"` on the track. Equivalent to
|
|
330
|
+
* passing `{ renderMode: 'piano-roll', clips: [{ midiNotes, midiChannel, midiProgram }] }`.
|
|
331
|
+
* An explicit `renderMode` takes precedence over the inferred `'piano-roll'`.
|
|
332
|
+
*
|
|
333
|
+
* Creation-only — ignored by `updateTrack`. To modify notes after the
|
|
334
|
+
* track is built, use `editor.updateClip(trackId, clipId, { midiNotes })` or
|
|
335
|
+
* mutate the `<daw-clip>` element's `midiNotes` property directly.
|
|
336
|
+
*/
|
|
337
|
+
midi?: {
|
|
338
|
+
notes: MidiNoteData[];
|
|
339
|
+
channel?: number;
|
|
340
|
+
program?: number;
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Public input shape for clips passed via `TrackConfig.clips` or
|
|
345
|
+
* `editor.addClip(trackId, config)`. `src` is optional to support MIDI clips
|
|
346
|
+
* with no audio source. Other fields default to the matching `<daw-clip>`
|
|
347
|
+
* attribute defaults.
|
|
348
|
+
*/
|
|
349
|
+
interface ClipConfig {
|
|
350
|
+
src?: string;
|
|
351
|
+
peaksSrc?: string;
|
|
352
|
+
start?: number;
|
|
353
|
+
duration?: number;
|
|
354
|
+
offset?: number;
|
|
355
|
+
gain?: number;
|
|
356
|
+
name?: string;
|
|
357
|
+
fadeIn?: number;
|
|
358
|
+
fadeOut?: number;
|
|
359
|
+
fadeType?: FadeType;
|
|
360
|
+
midiNotes?: MidiNoteData[];
|
|
361
|
+
midiChannel?: number;
|
|
362
|
+
midiProgram?: number;
|
|
363
|
+
}
|
|
364
|
+
|
|
356
365
|
/**
|
|
357
366
|
* Peak generation pipeline: AudioBuffer → web worker → WaveformData → PeakData.
|
|
358
367
|
*
|
|
@@ -785,6 +794,12 @@ interface DawClipSplitDetail {
|
|
|
785
794
|
}
|
|
786
795
|
interface DawSpectrogramReadyDetail {
|
|
787
796
|
trackId: string;
|
|
797
|
+
generation: number;
|
|
798
|
+
}
|
|
799
|
+
interface DawSpectrogramErrorDetail {
|
|
800
|
+
trackId: string;
|
|
801
|
+
generation: number;
|
|
802
|
+
error: Error;
|
|
788
803
|
}
|
|
789
804
|
interface DawEventMap {
|
|
790
805
|
'daw-selection': CustomEvent<DawSelectionDetail>;
|
|
@@ -814,6 +829,7 @@ interface DawEventMap {
|
|
|
814
829
|
'daw-clip-trim': CustomEvent<DawClipTrimDetail>;
|
|
815
830
|
'daw-clip-split': CustomEvent<DawClipSplitDetail>;
|
|
816
831
|
'daw-spectrogram-ready': CustomEvent<DawSpectrogramReadyDetail>;
|
|
832
|
+
'daw-spectrogram-error': CustomEvent<DawSpectrogramErrorDetail>;
|
|
817
833
|
}
|
|
818
834
|
type DawEvent<K extends keyof DawEventMap> = DawEventMap[K];
|
|
819
835
|
interface LoadFilesResult {
|
|
@@ -824,7 +840,29 @@ interface LoadFilesResult {
|
|
|
824
840
|
}>;
|
|
825
841
|
}
|
|
826
842
|
|
|
827
|
-
|
|
843
|
+
/**
|
|
844
|
+
* MIDI loading logic extracted from daw-editor. Operates on the editor via a
|
|
845
|
+
* narrow host interface (`addTrack` + `querySelectorAll`) — `<daw-editor>`
|
|
846
|
+
* satisfies it without any new public surface.
|
|
847
|
+
*
|
|
848
|
+
* Numbered steps below match the Data Flow diagram in
|
|
849
|
+
* `docs/specs/2026-05-23-dawcore-load-midi-design.md`.
|
|
850
|
+
*/
|
|
851
|
+
|
|
852
|
+
/**
|
|
853
|
+
* Minimal host surface needed by `loadMidiImpl`. `<daw-editor>` satisfies this
|
|
854
|
+
* structurally. `querySelectorAll` is needed for cleanup-on-failure so the
|
|
855
|
+
* loader can identify `<daw-track>` elements appended during this call (both
|
|
856
|
+
* those whose `addTrack` resolved and those that rejected after `_loadTrack`
|
|
857
|
+
* fired `daw-track-error` — the latter aren't in the `addTrack` resolution
|
|
858
|
+
* value, so we need DOM observation to find them).
|
|
859
|
+
*/
|
|
860
|
+
interface MidiLoaderHost {
|
|
861
|
+
addTrack(config: TrackConfig): Promise<DawTrackElement>;
|
|
862
|
+
querySelectorAll(selector: string): NodeListOf<Element>;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
declare class DawEditorElement extends LitElement implements MidiLoaderHost {
|
|
828
866
|
get samplesPerPixel(): number;
|
|
829
867
|
set samplesPerPixel(value: number);
|
|
830
868
|
private _samplesPerPixel;
|
|
@@ -877,9 +915,10 @@ declare class DawEditorElement extends LitElement {
|
|
|
877
915
|
/** Called by <daw-spectrogram> on chunk unmount / element disconnect. */
|
|
878
916
|
_spectrogramUnregisterCanvas(canvasId: string): void;
|
|
879
917
|
/**
|
|
880
|
-
*
|
|
881
|
-
*
|
|
882
|
-
*
|
|
918
|
+
* Forward a clip's AudioBuffer to the spectrogram controller if the parent
|
|
919
|
+
* track is in spectrogram render-mode. Eagerly creates the controller via
|
|
920
|
+
* `_ensureSpectrogramController` so the audio data is queued for the first
|
|
921
|
+
* render — even if no canvases have been registered yet.
|
|
883
922
|
*/
|
|
884
923
|
private _maybeRegisterSpectrogramClipAudio;
|
|
885
924
|
scaleMode: 'temporal' | 'beats';
|
|
@@ -985,7 +1024,10 @@ declare class DawEditorElement extends LitElement {
|
|
|
985
1024
|
* `_selectedTrackId`, etc.) — most of which don't affect the spectrogram
|
|
986
1025
|
* viewport. Skip the cross-controller call when nothing changed.
|
|
987
1026
|
*
|
|
988
|
-
* The orchestrator dedupes too,
|
|
1027
|
+
* The orchestrator dedupes identical viewports too, so removing this cache
|
|
1028
|
+
* wouldn't change observable behavior — but it would push a fresh
|
|
1029
|
+
* `setViewport` call (with object allocation) into every Lit reactive
|
|
1030
|
+
* update for properties unrelated to the viewport.
|
|
989
1031
|
*/
|
|
990
1032
|
private _lastSpectrogramViewport;
|
|
991
1033
|
protected updated(_changed: Map<string, unknown>): void;
|
|
@@ -1066,6 +1108,20 @@ declare class DawEditorElement extends LitElement {
|
|
|
1066
1108
|
private _onDragLeave;
|
|
1067
1109
|
private _onDrop;
|
|
1068
1110
|
loadFiles(files: FileList | File[]): Promise<LoadFilesResult>;
|
|
1111
|
+
/**
|
|
1112
|
+
* Imperatively load a `.mid` file (URL or File) and create N `<daw-track>`
|
|
1113
|
+
* elements — one per note-bearing MIDI track. On any per-track failure,
|
|
1114
|
+
* every `<daw-track>` appended during the call is removed (both successful
|
|
1115
|
+
* and failed) so the editor returns to its pre-call state.
|
|
1116
|
+
*
|
|
1117
|
+
* `options.signal` is forwarded to `fetch()` only for URL sources; aborting
|
|
1118
|
+
* after parsing does not cancel in-flight `addTrack` calls.
|
|
1119
|
+
*
|
|
1120
|
+
* Requires the optional `@dawcore/midi` peer dep — throws with an install
|
|
1121
|
+
* hint (and `console.warn`s the original error) when the dynamic import
|
|
1122
|
+
* fails for any reason.
|
|
1123
|
+
*/
|
|
1124
|
+
loadMidi(source: string | File, options?: MidiLoadOptions): Promise<MidiLoadResult>;
|
|
1069
1125
|
/**
|
|
1070
1126
|
* Build the engine if it hasn't been built yet. Lets consumers obtain a
|
|
1071
1127
|
* non-null `editor.engine` before any track has been loaded — useful for
|
|
@@ -1306,6 +1362,7 @@ declare class DawSpectrogramElement extends LitElement {
|
|
|
1306
1362
|
static styles: lit.CSSResult;
|
|
1307
1363
|
private _canvases;
|
|
1308
1364
|
private _registeredCanvasIds;
|
|
1365
|
+
private _warnedNoHost;
|
|
1309
1366
|
/**
|
|
1310
1367
|
* Walk up to the editor host. `closest('daw-editor')` does NOT cross
|
|
1311
1368
|
* shadow boundaries — and this element lives inside the editor's shadow
|