@tremolo-ui/dom 0.7.0 → 0.9.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/dist/index.cjs +343 -595
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +230 -284
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +230 -284
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +325 -572
- package/dist/index.js.map +1 -1
- package/dist/internal.cjs +530 -0
- package/dist/internal.cjs.map +1 -0
- package/dist/internal.d.cts +365 -0
- package/dist/internal.d.cts.map +1 -0
- package/dist/internal.d.ts +365 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +500 -0
- package/dist/internal.js.map +1 -0
- package/dist/marks-DK7xJmGM.d.cts +305 -0
- package/dist/marks-DK7xJmGM.d.cts.map +1 -0
- package/dist/marks-DK7xJmGM.d.ts +305 -0
- package/dist/marks-DK7xJmGM.d.ts.map +1 -0
- package/dist/xy-5Oc6JeJr.cjs +952 -0
- package/dist/xy-5Oc6JeJr.cjs.map +1 -0
- package/dist/xy-lNFl1CTO.js +827 -0
- package/dist/xy-lNFl1CTO.js.map +1 -0
- package/package.json +12 -2
- package/src/canvas/animation.ts +8 -0
- package/src/canvas/context.ts +0 -5
- package/src/file/accept.ts +17 -0
- package/src/file/drop-zone.ts +8 -10
- package/src/index.ts +44 -32
- package/src/input/change-gesture.ts +104 -0
- package/src/input/check-steps.ts +144 -0
- package/src/input/defaults.ts +32 -0
- package/src/input/direction.ts +107 -0
- package/src/internal.ts +51 -0
- package/src/knob/geometry.ts +100 -0
- package/src/midi/access.ts +16 -15
- package/src/midi/input.ts +2 -9
- package/src/number-input/stepper-drag.ts +147 -0
- package/src/number-input/text.ts +100 -0
- package/src/number-input/value.ts +129 -0
- package/src/options/replace.ts +22 -0
- package/src/piano/index.ts +128 -2
- package/src/piano/layout.ts +19 -0
- package/src/piano/shortcuts.ts +86 -0
- package/src/pointer/drag-value.ts +3 -1
- package/src/pointer/long-press.ts +103 -0
- package/src/pointer/wheel.ts +10 -7
- package/src/points-editor/index.ts +367 -0
- package/src/position.ts +20 -0
- package/src/slider/decimal-digits.ts +23 -0
- package/src/slider/marks.ts +56 -0
- package/src/style.ts +41 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
//#region src/input/modifiers.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Options for setting the amount of keyboard and mouse wheel changes.
|
|
4
|
+
*/
|
|
5
|
+
type InputEventOption = readonly ['normalized' | 'raw', number];
|
|
6
|
+
/**
|
|
7
|
+
* A modifier key that can carry an amount of its own.
|
|
8
|
+
*
|
|
9
|
+
* `ctrl` and `meta` are kept apart rather than folded into one "command" key:
|
|
10
|
+
* a plugin UI that mirrors a desktop host usually wants the same physical key
|
|
11
|
+
* on every platform, not the platform's own convention.
|
|
12
|
+
*/
|
|
13
|
+
type Modifier = 'shift' | 'alt' | 'ctrl' | 'meta';
|
|
14
|
+
/** The modifier flags of a `WheelEvent` or a `KeyboardEvent`. */
|
|
15
|
+
interface ModifierState {
|
|
16
|
+
shiftKey: boolean;
|
|
17
|
+
altKey: boolean;
|
|
18
|
+
ctrlKey: boolean;
|
|
19
|
+
metaKey: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** One setting per modifier key, with `default` for none of them. */
|
|
22
|
+
type ModifierSetting = number | InputEventOption;
|
|
23
|
+
type ModifierMap<T extends ModifierSetting> = {
|
|
24
|
+
default: T;
|
|
25
|
+
} & Partial<Record<Modifier, T>>;
|
|
26
|
+
/**
|
|
27
|
+
* A single setting, or one per modifier key.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ['raw', 1]
|
|
31
|
+
* { default: ['raw', 1], shift: ['raw', 0.1] }
|
|
32
|
+
*/
|
|
33
|
+
type ModifierValue<T extends ModifierSetting> = T | ModifierMap<T>;
|
|
34
|
+
/**
|
|
35
|
+
* Pick the setting that applies, given the modifier keys being held.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* selectModifier({ default: 1, shift: 0.1 }, event)
|
|
39
|
+
*/
|
|
40
|
+
declare function selectModifier<T extends ModifierSetting>(options: ModifierValue<T>, modifiers?: ModifierState): {
|
|
41
|
+
value: T;
|
|
42
|
+
modifier: Modifier | null;
|
|
43
|
+
};
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/piano/layout.d.ts
|
|
46
|
+
type NoteRange = {
|
|
47
|
+
first: number;
|
|
48
|
+
last: number;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* `[noteRange.first, noteRange.first + 1, ..., noteRange.last]`
|
|
52
|
+
*/
|
|
53
|
+
declare function getNoteRangeArray(noteRange: NoteRange): number[];
|
|
54
|
+
/**
|
|
55
|
+
* The geometry of a drawn keyboard.
|
|
56
|
+
*
|
|
57
|
+
* One description is shared by the drawing and the hit testing, so a key cannot
|
|
58
|
+
* be drawn somewhere other than where it responds.
|
|
59
|
+
*/
|
|
60
|
+
interface PianoLayout {
|
|
61
|
+
noteRange: NoteRange;
|
|
62
|
+
/** Width of a white key, excluding {@link PianoLayout.keyGap}. */
|
|
63
|
+
whiteKeyWidth: number;
|
|
64
|
+
/**
|
|
65
|
+
* Space between two white keys. Part of the slot a white key occupies, so it
|
|
66
|
+
* still belongs to one of the keys for the purpose of hit testing.
|
|
67
|
+
*
|
|
68
|
+
* @default 1
|
|
69
|
+
*/
|
|
70
|
+
keyGap?: number;
|
|
71
|
+
/**
|
|
72
|
+
* Width of a black key, as a fraction of {@link PianoLayout.whiteKeyWidth}.
|
|
73
|
+
*
|
|
74
|
+
* @default 0.65
|
|
75
|
+
*/
|
|
76
|
+
blackKeyWidthRatio?: number;
|
|
77
|
+
/**
|
|
78
|
+
* Height of a black key, as a fraction of the height of the keyboard.
|
|
79
|
+
*
|
|
80
|
+
* @default 0.6
|
|
81
|
+
*/
|
|
82
|
+
blackKeyHeightRatio?: number;
|
|
83
|
+
}
|
|
84
|
+
/** Width of a black key in pixels. */
|
|
85
|
+
declare function blackKeyWidth(layout: PianoLayout): number;
|
|
86
|
+
/** Width of the whole keyboard in pixels. */
|
|
87
|
+
declare function pianoWidth(layout: PianoLayout): number;
|
|
88
|
+
/**
|
|
89
|
+
* Offset of the left edge of a key from the left edge of the keyboard, in
|
|
90
|
+
* pixels.
|
|
91
|
+
*
|
|
92
|
+
* Notes outside `noteRange` are placed too, so the value is negative below
|
|
93
|
+
* `noteRange.first`.
|
|
94
|
+
*/
|
|
95
|
+
declare function notePosition(note: number, layout: PianoLayout): number;
|
|
96
|
+
/**
|
|
97
|
+
* The white key width that makes the keyboard exactly `width` wide, for a
|
|
98
|
+
* keyboard that follows the size of its container.
|
|
99
|
+
*
|
|
100
|
+
* Solved from {@link pianoWidth} rather than by dividing among the white
|
|
101
|
+
* keys, so that a range that starts or ends on a black key — which sticks out
|
|
102
|
+
* by a fraction of a white key — still fills the container. The width grows
|
|
103
|
+
* linearly with the white key width, so two samples pin it down.
|
|
104
|
+
*/
|
|
105
|
+
declare function fitWhiteKeyWidth(width: number, layout: Omit<PianoLayout, 'whiteKeyWidth'>): number;
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region src/xy.d.ts
|
|
108
|
+
/**
|
|
109
|
+
* A pair of per-axis values. The tuple elements are labelled, so editors show
|
|
110
|
+
* `[x: number, y: number]` rather than a bare pair.
|
|
111
|
+
*/
|
|
112
|
+
type XY<T> = [x: T, y: T];
|
|
113
|
+
/**
|
|
114
|
+
* A setting that may be given once for both axes, or per axis.
|
|
115
|
+
*
|
|
116
|
+
* A single value is told from a pair with `Array.isArray`, so the single form
|
|
117
|
+
* is only offered while `T` cannot itself be an array. Where it can, the pair
|
|
118
|
+
* is the only way to write it, since a lone array would be read as a pair.
|
|
119
|
+
*/
|
|
120
|
+
type XYInput<T> = [T] extends [readonly unknown[]] ? readonly [x: T, y: T] : T | readonly [x: T, y: T];
|
|
121
|
+
/**
|
|
122
|
+
* Spread a setting that may have been given as a single value.
|
|
123
|
+
*
|
|
124
|
+
* The parameter is written out rather than taken as `XYInput<T>`: a
|
|
125
|
+
* conditional type cannot be narrowed, so the constraint stays where it is
|
|
126
|
+
* declared and this takes both forms.
|
|
127
|
+
*
|
|
128
|
+
* The pair is copied rather than passed along, so that the result is a tuple
|
|
129
|
+
* the caller owns even when a readonly one was given.
|
|
130
|
+
*/
|
|
131
|
+
declare function toXY<T>(value: T | readonly [x: T, y: T]): XY<T>;
|
|
132
|
+
//#endregion
|
|
133
|
+
//#region src/selection/box.d.ts
|
|
134
|
+
/**
|
|
135
|
+
* A rectangle in the 0..1 space of whatever the box is drawn over, with `y`
|
|
136
|
+
* growing downwards — the same space the items are given in.
|
|
137
|
+
*/
|
|
138
|
+
interface SelectionBoxRect {
|
|
139
|
+
x: number;
|
|
140
|
+
y: number;
|
|
141
|
+
width: number;
|
|
142
|
+
height: number;
|
|
143
|
+
}
|
|
144
|
+
//#endregion
|
|
145
|
+
//#region src/points-editor/index.d.ts
|
|
146
|
+
/** Where a point is: 0..1 on each axis, with y growing downwards. */
|
|
147
|
+
interface PointPosition {
|
|
148
|
+
x: number;
|
|
149
|
+
y: number;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* A point's value is its position in the editor, so its range is the editor:
|
|
153
|
+
* no scaling, and no rounding to a step.
|
|
154
|
+
*/
|
|
155
|
+
declare const POINT_AXIS: {
|
|
156
|
+
min: number;
|
|
157
|
+
max: number;
|
|
158
|
+
};
|
|
159
|
+
/**
|
|
160
|
+
* How much one wheel notch moves a point by default: a hundredth of the
|
|
161
|
+
* editor, whatever its pixel size.
|
|
162
|
+
*/
|
|
163
|
+
declare const POINTS_EDITOR_DEFAULT_WHEEL: ModifierValue<InputEventOption>;
|
|
164
|
+
/**
|
|
165
|
+
* How much one arrow key press moves a point by default. Shift is the
|
|
166
|
+
* fine-adjustment key everywhere else, so it is bound here too — but only on
|
|
167
|
+
* the keyboard. On the wheel it already means the x axis, and browsers hand
|
|
168
|
+
* shift+wheel over as horizontal scrolling anyway.
|
|
169
|
+
*/
|
|
170
|
+
declare const POINTS_EDITOR_DEFAULT_KEYBOARD: ModifierValue<InputEventOption>;
|
|
171
|
+
/** Keep a point within its range. An axis left out runs from 0 to 1. */
|
|
172
|
+
declare function clampPoint(point: PointPosition, min?: Partial<PointPosition>, max?: Partial<PointPosition>): PointPosition;
|
|
173
|
+
/**
|
|
174
|
+
* What a point tells the editor about itself, so that a selection can be
|
|
175
|
+
* moved without the editor knowing how the points are stored.
|
|
176
|
+
*/
|
|
177
|
+
interface PointsEditorPoint {
|
|
178
|
+
value: PointPosition;
|
|
179
|
+
min?: Partial<PointPosition>;
|
|
180
|
+
max?: Partial<PointPosition>;
|
|
181
|
+
/** A point that cannot move stays put while the rest of a selection moves. */
|
|
182
|
+
readonly?: boolean;
|
|
183
|
+
onChange?: (value: PointPosition) => void;
|
|
184
|
+
/** The point's own element, to match the focus and a press against. */
|
|
185
|
+
element?: Element | null;
|
|
186
|
+
/** The wheel option the point resolved, `null` for no wheel. */
|
|
187
|
+
wheel?: ModifierValue<InputEventOption> | null;
|
|
188
|
+
/**
|
|
189
|
+
* Called just before the wheel moves this point as the focused one, so that
|
|
190
|
+
* it can report its change as started before the value arrives.
|
|
191
|
+
*/
|
|
192
|
+
beforeWheel?: () => void;
|
|
193
|
+
}
|
|
194
|
+
interface PointsEditorOptions {
|
|
195
|
+
/**
|
|
196
|
+
* Let points be selected, and a selection be moved as one. While it is off
|
|
197
|
+
* nothing is selected, and a drag moves only the point it started on.
|
|
198
|
+
*
|
|
199
|
+
* @default false
|
|
200
|
+
*/
|
|
201
|
+
selectable?: boolean;
|
|
202
|
+
/**
|
|
203
|
+
* The ids of the selected points. Whoever holds the selection pushes it
|
|
204
|
+
* back with `update()` after {@link PointsEditorOptions.onSelectionChange}.
|
|
205
|
+
*/
|
|
206
|
+
selection?: readonly string[];
|
|
207
|
+
/** Called whenever a press or a selection box changes the selection. */
|
|
208
|
+
onSelectionChange?: (selection: string[]) => void;
|
|
209
|
+
/** Called whenever the selection box changes, with `null` once it is gone. */
|
|
210
|
+
onSelectionBoxChange?: (rect: SelectionBoxRect | null) => void;
|
|
211
|
+
}
|
|
212
|
+
interface PointsEditorInstance {
|
|
213
|
+
/** Replace the given options. */
|
|
214
|
+
update: (options: Partial<PointsEditorOptions>) => void;
|
|
215
|
+
/**
|
|
216
|
+
* Register a point under `id`. `read` is called whenever the editor needs
|
|
217
|
+
* the point, so it can return what the point is now rather than what it
|
|
218
|
+
* was when it registered. Returns the function that unregisters it.
|
|
219
|
+
*/
|
|
220
|
+
registerPoint: (id: string, read: () => PointsEditorPoint) => () => void;
|
|
221
|
+
/** Whether the element is a point, or inside one. */
|
|
222
|
+
isPointElement: (element: Element | null | undefined) => boolean;
|
|
223
|
+
/**
|
|
224
|
+
* A pointer went down on a point: work out the new selection and remember
|
|
225
|
+
* where everything the drag picked up started.
|
|
226
|
+
*
|
|
227
|
+
* Ctrl / meta add the point to the selection or take it out: shift is the
|
|
228
|
+
* fine-adjustment key on every control here, and it cannot be both. A
|
|
229
|
+
* press on a point already selected keeps the selection, so the group can
|
|
230
|
+
* be dragged.
|
|
231
|
+
*/
|
|
232
|
+
beginPointDrag: (id: string, modifiers: ModifierState) => void;
|
|
233
|
+
/**
|
|
234
|
+
* Move everything the drag picked up by `delta` from where it started,
|
|
235
|
+
* stopping the whole group together at the edge.
|
|
236
|
+
*/
|
|
237
|
+
movePointDrag: (delta: PointPosition) => void;
|
|
238
|
+
/**
|
|
239
|
+
* Move `id` — and the selection, when it is part of one — by `delta` from
|
|
240
|
+
* where the points are now: an input that is not a drag has no earlier
|
|
241
|
+
* position to measure against.
|
|
242
|
+
*/
|
|
243
|
+
nudgeSelection: (id: string, delta: PointPosition) => void;
|
|
244
|
+
/**
|
|
245
|
+
* Move `id` by one press of `option` along one axis, taking the selection
|
|
246
|
+
* along as {@link PointsEditorInstance.nudgeSelection} does.
|
|
247
|
+
*/
|
|
248
|
+
nudgePoint: (id: string, axis: 'x' | 'y', direction: number, option: ModifierValue<InputEventOption>, modifiers?: ModifierState) => void;
|
|
249
|
+
/**
|
|
250
|
+
* Move the point holding the focus by one wheel notch, with its own wheel
|
|
251
|
+
* option. The wheel is listened to once for the whole editor, since a wheel
|
|
252
|
+
* event only reaches what the cursor is over. Returns whether a point took
|
|
253
|
+
* it, so the caller knows whether to consume the event.
|
|
254
|
+
*/
|
|
255
|
+
nudgeFocusedPoint: (axis: 'x' | 'y', direction: number, modifiers: ModifierState) => boolean;
|
|
256
|
+
/** A drag on empty space started at `at`: start a selection box there. */
|
|
257
|
+
beginSelectionBox: (at: PointPosition, modifiers: ModifierState) => void;
|
|
258
|
+
moveSelectionBox: (to: PointPosition) => void;
|
|
259
|
+
/**
|
|
260
|
+
* End the selection box. The press that started it left the focus on
|
|
261
|
+
* nothing, and the arrow keys and the wheel reach a point only through the
|
|
262
|
+
* focus, so it is handed to one of the points the box selected.
|
|
263
|
+
*/
|
|
264
|
+
endSelectionBox: () => void;
|
|
265
|
+
destroy: () => void;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* The selection and the moves of a points editor: which points a press or a
|
|
269
|
+
* box selects, and how a selection moves as one.
|
|
270
|
+
*
|
|
271
|
+
* The points stay with the wrapper, which registers each one; the editor only
|
|
272
|
+
* reads them when it needs to, so a point's value can change on every frame
|
|
273
|
+
* of a drag without anything being re-registered.
|
|
274
|
+
*/
|
|
275
|
+
declare function createPointsEditor(options?: PointsEditorOptions): PointsEditorInstance;
|
|
276
|
+
//#endregion
|
|
277
|
+
//#region src/slider/marks.d.ts
|
|
278
|
+
/**
|
|
279
|
+
* How `Slider.Marks` fills itself in when it is given no children: one option
|
|
280
|
+
* every `per`, or every `step` of the slider. The object form turns off the
|
|
281
|
+
* mark or the label for the whole set; a single option is customized by
|
|
282
|
+
* writing `Slider.MarksOption` out instead.
|
|
283
|
+
*/
|
|
284
|
+
type MarksOptions = 'step' | number | {
|
|
285
|
+
per: 'step' | number;
|
|
286
|
+
mark?: boolean;
|
|
287
|
+
label?: boolean;
|
|
288
|
+
};
|
|
289
|
+
/** One mark along a slider, as {@link sliderMarks} lays them out. */
|
|
290
|
+
interface SliderMark {
|
|
291
|
+
value: number;
|
|
292
|
+
mark: boolean;
|
|
293
|
+
label: boolean;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* The marks `options` asks for between `min` and `max`, in ascending order.
|
|
297
|
+
*
|
|
298
|
+
* Each value is a whole multiple of the interval, rounded to the digits the
|
|
299
|
+
* interval has: stepping by 0.1 would otherwise put binary debris in the
|
|
300
|
+
* labels (`0.1 * 3` is `0.30000000000000004`).
|
|
301
|
+
*/
|
|
302
|
+
declare function sliderMarks(options: MarksOptions, min: number, max: number, step: number): SliderMark[];
|
|
303
|
+
//#endregion
|
|
304
|
+
export { pianoWidth as C, ModifierState as D, ModifierMap as E, ModifierValue as O, notePosition as S, Modifier as T, NoteRange as _, POINTS_EDITOR_DEFAULT_WHEEL as a, fitWhiteKeyWidth as b, PointsEditorInstance as c, clampPoint as d, createPointsEditor as f, toXY as g, XYInput as h, POINTS_EDITOR_DEFAULT_KEYBOARD as i, selectModifier as k, PointsEditorOptions as l, XY as m, SliderMark as n, POINT_AXIS as o, SelectionBoxRect as p, sliderMarks as r, PointPosition as s, MarksOptions as t, PointsEditorPoint as u, PianoLayout as v, InputEventOption as w, getNoteRangeArray as x, blackKeyWidth as y };
|
|
305
|
+
//# sourceMappingURL=marks-DK7xJmGM.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marks-DK7xJmGM.d.cts","names":[],"sources":["../src/input/modifiers.ts","../src/piano/layout.ts","../src/xy.ts","../src/selection/box.ts","../src/points-editor/index.ts","../src/slider/marks.ts"],"mappings":";;;;KAGY;;;;;;;;KASA;;UAGK;EACf;EACA;EACA;EACA;;;KAIG,2BAA2B;KAEpB,YAAY,UAAU;EAAqB,SAAS;IAAM,QACpE,OAAO,UAAU;;;;;;;;KAUP,cAAc,UAAU,mBAAmB,IAAI,YAAY;;;;;;;iBAqCvD,eAAe,UAAU,iBACvC,SAAS,cAAc,IACvB,YAAY;EACT,OAAO;EAAG,UAAU;;;;KCpEb;EACV;EACA;;;;;iBAMc,kBAAkB,WAAW;;;;;;;UAa5B;EACf,WAAW;;EAGX;;;;;;;EAQA;;;;;;EAOA;;;;;;EAOA;;;iBA8Bc,cAAc,QAAQ;;iBA0CtB,WAAW,QAAQ;;;;;;;;iBAYnB,aAAa,cAAc,QAAQ;;;;;;;;;;iBAsDnC,iBACd,eACA,QAAQ,KAAK;;;;;;;KC/LH,GAAG,MAAM,GAAG,GAAG,GAAG;;;;;;;;KASlB,QAAQ,MAAM,4CACZ,GAAG,GAAG,GAAG,KACnB,cAAc,GAAG,GAAG,GAAG;;;;;;;;;;;iBAoBX,KAAK,GAAG,OAAO,cAAc,GAAG,GAAG,GAAG,KAAK,GAAG;;;;;;;UC7B7C;EACf;EACA;EACA;EACA;;;;;UCEe;EACf;EACA;;;;;;cAOW;EAAA;EAAA;;;;;;cAMA,6BAA6B,cAAc;;;;;;;cAW3C,gCAAgC,cAAc;;iBAM3C,WACd,OAAO,eACP,MAAM,QAAQ,gBACd,MAAM,QAAQ,iBACb;;;;;UAWc;EACf,OAAO;EACP,MAAM,QAAQ;EACd,MAAM,QAAQ;;EAEd;EACA,YAAY,OAAO;;EAEnB,UAAU;;EAEV,QAAQ,cAAc;;;;;EAKtB;;UAGe;;;;;;;EAOf;;;;;EAKA;;EAEA,qBAAqB;;EAErB,wBAAwB,MAAM;;UAGf;;EAEf,SAAS,SAAS,QAAQ;;;;;;EAM1B,gBAAgB,YAAY,YAAY;;EAExC,iBAAiB,SAAS;;;;;;;;;;EAU1B,iBAAiB,YAAY,WAAW;;;;;EAKxC,gBAAgB,OAAO;;;;;;EAMvB,iBAAiB,YAAY,OAAO;;;;;EAKpC,aACE,YACA,iBACA,mBACA,QAAQ,cAAc,mBACtB,YAAY;;;;;;;EAQd,oBACE,iBACA,mBACA,WAAW;;EAGb,oBAAoB,IAAI,eAAe,WAAW;EAClD,mBAAmB,IAAI;;;;;;EAMvB;EACA;;;;;;;;;;iBA4Cc,mBACd,UAAS,sBACR;;;;;;;;;KCnMS;EAIN;EACA;EACA;;;UAIW;EACf;EACA;EACA;;;;;;;;;iBAUc,YACd,SAAS,cACT,aACA,aACA,eACC"}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
//#region src/input/modifiers.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Options for setting the amount of keyboard and mouse wheel changes.
|
|
4
|
+
*/
|
|
5
|
+
type InputEventOption = readonly ['normalized' | 'raw', number];
|
|
6
|
+
/**
|
|
7
|
+
* A modifier key that can carry an amount of its own.
|
|
8
|
+
*
|
|
9
|
+
* `ctrl` and `meta` are kept apart rather than folded into one "command" key:
|
|
10
|
+
* a plugin UI that mirrors a desktop host usually wants the same physical key
|
|
11
|
+
* on every platform, not the platform's own convention.
|
|
12
|
+
*/
|
|
13
|
+
type Modifier = 'shift' | 'alt' | 'ctrl' | 'meta';
|
|
14
|
+
/** The modifier flags of a `WheelEvent` or a `KeyboardEvent`. */
|
|
15
|
+
interface ModifierState {
|
|
16
|
+
shiftKey: boolean;
|
|
17
|
+
altKey: boolean;
|
|
18
|
+
ctrlKey: boolean;
|
|
19
|
+
metaKey: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** One setting per modifier key, with `default` for none of them. */
|
|
22
|
+
type ModifierSetting = number | InputEventOption;
|
|
23
|
+
type ModifierMap<T extends ModifierSetting> = {
|
|
24
|
+
default: T;
|
|
25
|
+
} & Partial<Record<Modifier, T>>;
|
|
26
|
+
/**
|
|
27
|
+
* A single setting, or one per modifier key.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ['raw', 1]
|
|
31
|
+
* { default: ['raw', 1], shift: ['raw', 0.1] }
|
|
32
|
+
*/
|
|
33
|
+
type ModifierValue<T extends ModifierSetting> = T | ModifierMap<T>;
|
|
34
|
+
/**
|
|
35
|
+
* Pick the setting that applies, given the modifier keys being held.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* selectModifier({ default: 1, shift: 0.1 }, event)
|
|
39
|
+
*/
|
|
40
|
+
declare function selectModifier<T extends ModifierSetting>(options: ModifierValue<T>, modifiers?: ModifierState): {
|
|
41
|
+
value: T;
|
|
42
|
+
modifier: Modifier | null;
|
|
43
|
+
};
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/piano/layout.d.ts
|
|
46
|
+
type NoteRange = {
|
|
47
|
+
first: number;
|
|
48
|
+
last: number;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* `[noteRange.first, noteRange.first + 1, ..., noteRange.last]`
|
|
52
|
+
*/
|
|
53
|
+
declare function getNoteRangeArray(noteRange: NoteRange): number[];
|
|
54
|
+
/**
|
|
55
|
+
* The geometry of a drawn keyboard.
|
|
56
|
+
*
|
|
57
|
+
* One description is shared by the drawing and the hit testing, so a key cannot
|
|
58
|
+
* be drawn somewhere other than where it responds.
|
|
59
|
+
*/
|
|
60
|
+
interface PianoLayout {
|
|
61
|
+
noteRange: NoteRange;
|
|
62
|
+
/** Width of a white key, excluding {@link PianoLayout.keyGap}. */
|
|
63
|
+
whiteKeyWidth: number;
|
|
64
|
+
/**
|
|
65
|
+
* Space between two white keys. Part of the slot a white key occupies, so it
|
|
66
|
+
* still belongs to one of the keys for the purpose of hit testing.
|
|
67
|
+
*
|
|
68
|
+
* @default 1
|
|
69
|
+
*/
|
|
70
|
+
keyGap?: number;
|
|
71
|
+
/**
|
|
72
|
+
* Width of a black key, as a fraction of {@link PianoLayout.whiteKeyWidth}.
|
|
73
|
+
*
|
|
74
|
+
* @default 0.65
|
|
75
|
+
*/
|
|
76
|
+
blackKeyWidthRatio?: number;
|
|
77
|
+
/**
|
|
78
|
+
* Height of a black key, as a fraction of the height of the keyboard.
|
|
79
|
+
*
|
|
80
|
+
* @default 0.6
|
|
81
|
+
*/
|
|
82
|
+
blackKeyHeightRatio?: number;
|
|
83
|
+
}
|
|
84
|
+
/** Width of a black key in pixels. */
|
|
85
|
+
declare function blackKeyWidth(layout: PianoLayout): number;
|
|
86
|
+
/** Width of the whole keyboard in pixels. */
|
|
87
|
+
declare function pianoWidth(layout: PianoLayout): number;
|
|
88
|
+
/**
|
|
89
|
+
* Offset of the left edge of a key from the left edge of the keyboard, in
|
|
90
|
+
* pixels.
|
|
91
|
+
*
|
|
92
|
+
* Notes outside `noteRange` are placed too, so the value is negative below
|
|
93
|
+
* `noteRange.first`.
|
|
94
|
+
*/
|
|
95
|
+
declare function notePosition(note: number, layout: PianoLayout): number;
|
|
96
|
+
/**
|
|
97
|
+
* The white key width that makes the keyboard exactly `width` wide, for a
|
|
98
|
+
* keyboard that follows the size of its container.
|
|
99
|
+
*
|
|
100
|
+
* Solved from {@link pianoWidth} rather than by dividing among the white
|
|
101
|
+
* keys, so that a range that starts or ends on a black key — which sticks out
|
|
102
|
+
* by a fraction of a white key — still fills the container. The width grows
|
|
103
|
+
* linearly with the white key width, so two samples pin it down.
|
|
104
|
+
*/
|
|
105
|
+
declare function fitWhiteKeyWidth(width: number, layout: Omit<PianoLayout, 'whiteKeyWidth'>): number;
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region src/xy.d.ts
|
|
108
|
+
/**
|
|
109
|
+
* A pair of per-axis values. The tuple elements are labelled, so editors show
|
|
110
|
+
* `[x: number, y: number]` rather than a bare pair.
|
|
111
|
+
*/
|
|
112
|
+
type XY<T> = [x: T, y: T];
|
|
113
|
+
/**
|
|
114
|
+
* A setting that may be given once for both axes, or per axis.
|
|
115
|
+
*
|
|
116
|
+
* A single value is told from a pair with `Array.isArray`, so the single form
|
|
117
|
+
* is only offered while `T` cannot itself be an array. Where it can, the pair
|
|
118
|
+
* is the only way to write it, since a lone array would be read as a pair.
|
|
119
|
+
*/
|
|
120
|
+
type XYInput<T> = [T] extends [readonly unknown[]] ? readonly [x: T, y: T] : T | readonly [x: T, y: T];
|
|
121
|
+
/**
|
|
122
|
+
* Spread a setting that may have been given as a single value.
|
|
123
|
+
*
|
|
124
|
+
* The parameter is written out rather than taken as `XYInput<T>`: a
|
|
125
|
+
* conditional type cannot be narrowed, so the constraint stays where it is
|
|
126
|
+
* declared and this takes both forms.
|
|
127
|
+
*
|
|
128
|
+
* The pair is copied rather than passed along, so that the result is a tuple
|
|
129
|
+
* the caller owns even when a readonly one was given.
|
|
130
|
+
*/
|
|
131
|
+
declare function toXY<T>(value: T | readonly [x: T, y: T]): XY<T>;
|
|
132
|
+
//#endregion
|
|
133
|
+
//#region src/selection/box.d.ts
|
|
134
|
+
/**
|
|
135
|
+
* A rectangle in the 0..1 space of whatever the box is drawn over, with `y`
|
|
136
|
+
* growing downwards — the same space the items are given in.
|
|
137
|
+
*/
|
|
138
|
+
interface SelectionBoxRect {
|
|
139
|
+
x: number;
|
|
140
|
+
y: number;
|
|
141
|
+
width: number;
|
|
142
|
+
height: number;
|
|
143
|
+
}
|
|
144
|
+
//#endregion
|
|
145
|
+
//#region src/points-editor/index.d.ts
|
|
146
|
+
/** Where a point is: 0..1 on each axis, with y growing downwards. */
|
|
147
|
+
interface PointPosition {
|
|
148
|
+
x: number;
|
|
149
|
+
y: number;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* A point's value is its position in the editor, so its range is the editor:
|
|
153
|
+
* no scaling, and no rounding to a step.
|
|
154
|
+
*/
|
|
155
|
+
declare const POINT_AXIS: {
|
|
156
|
+
min: number;
|
|
157
|
+
max: number;
|
|
158
|
+
};
|
|
159
|
+
/**
|
|
160
|
+
* How much one wheel notch moves a point by default: a hundredth of the
|
|
161
|
+
* editor, whatever its pixel size.
|
|
162
|
+
*/
|
|
163
|
+
declare const POINTS_EDITOR_DEFAULT_WHEEL: ModifierValue<InputEventOption>;
|
|
164
|
+
/**
|
|
165
|
+
* How much one arrow key press moves a point by default. Shift is the
|
|
166
|
+
* fine-adjustment key everywhere else, so it is bound here too — but only on
|
|
167
|
+
* the keyboard. On the wheel it already means the x axis, and browsers hand
|
|
168
|
+
* shift+wheel over as horizontal scrolling anyway.
|
|
169
|
+
*/
|
|
170
|
+
declare const POINTS_EDITOR_DEFAULT_KEYBOARD: ModifierValue<InputEventOption>;
|
|
171
|
+
/** Keep a point within its range. An axis left out runs from 0 to 1. */
|
|
172
|
+
declare function clampPoint(point: PointPosition, min?: Partial<PointPosition>, max?: Partial<PointPosition>): PointPosition;
|
|
173
|
+
/**
|
|
174
|
+
* What a point tells the editor about itself, so that a selection can be
|
|
175
|
+
* moved without the editor knowing how the points are stored.
|
|
176
|
+
*/
|
|
177
|
+
interface PointsEditorPoint {
|
|
178
|
+
value: PointPosition;
|
|
179
|
+
min?: Partial<PointPosition>;
|
|
180
|
+
max?: Partial<PointPosition>;
|
|
181
|
+
/** A point that cannot move stays put while the rest of a selection moves. */
|
|
182
|
+
readonly?: boolean;
|
|
183
|
+
onChange?: (value: PointPosition) => void;
|
|
184
|
+
/** The point's own element, to match the focus and a press against. */
|
|
185
|
+
element?: Element | null;
|
|
186
|
+
/** The wheel option the point resolved, `null` for no wheel. */
|
|
187
|
+
wheel?: ModifierValue<InputEventOption> | null;
|
|
188
|
+
/**
|
|
189
|
+
* Called just before the wheel moves this point as the focused one, so that
|
|
190
|
+
* it can report its change as started before the value arrives.
|
|
191
|
+
*/
|
|
192
|
+
beforeWheel?: () => void;
|
|
193
|
+
}
|
|
194
|
+
interface PointsEditorOptions {
|
|
195
|
+
/**
|
|
196
|
+
* Let points be selected, and a selection be moved as one. While it is off
|
|
197
|
+
* nothing is selected, and a drag moves only the point it started on.
|
|
198
|
+
*
|
|
199
|
+
* @default false
|
|
200
|
+
*/
|
|
201
|
+
selectable?: boolean;
|
|
202
|
+
/**
|
|
203
|
+
* The ids of the selected points. Whoever holds the selection pushes it
|
|
204
|
+
* back with `update()` after {@link PointsEditorOptions.onSelectionChange}.
|
|
205
|
+
*/
|
|
206
|
+
selection?: readonly string[];
|
|
207
|
+
/** Called whenever a press or a selection box changes the selection. */
|
|
208
|
+
onSelectionChange?: (selection: string[]) => void;
|
|
209
|
+
/** Called whenever the selection box changes, with `null` once it is gone. */
|
|
210
|
+
onSelectionBoxChange?: (rect: SelectionBoxRect | null) => void;
|
|
211
|
+
}
|
|
212
|
+
interface PointsEditorInstance {
|
|
213
|
+
/** Replace the given options. */
|
|
214
|
+
update: (options: Partial<PointsEditorOptions>) => void;
|
|
215
|
+
/**
|
|
216
|
+
* Register a point under `id`. `read` is called whenever the editor needs
|
|
217
|
+
* the point, so it can return what the point is now rather than what it
|
|
218
|
+
* was when it registered. Returns the function that unregisters it.
|
|
219
|
+
*/
|
|
220
|
+
registerPoint: (id: string, read: () => PointsEditorPoint) => () => void;
|
|
221
|
+
/** Whether the element is a point, or inside one. */
|
|
222
|
+
isPointElement: (element: Element | null | undefined) => boolean;
|
|
223
|
+
/**
|
|
224
|
+
* A pointer went down on a point: work out the new selection and remember
|
|
225
|
+
* where everything the drag picked up started.
|
|
226
|
+
*
|
|
227
|
+
* Ctrl / meta add the point to the selection or take it out: shift is the
|
|
228
|
+
* fine-adjustment key on every control here, and it cannot be both. A
|
|
229
|
+
* press on a point already selected keeps the selection, so the group can
|
|
230
|
+
* be dragged.
|
|
231
|
+
*/
|
|
232
|
+
beginPointDrag: (id: string, modifiers: ModifierState) => void;
|
|
233
|
+
/**
|
|
234
|
+
* Move everything the drag picked up by `delta` from where it started,
|
|
235
|
+
* stopping the whole group together at the edge.
|
|
236
|
+
*/
|
|
237
|
+
movePointDrag: (delta: PointPosition) => void;
|
|
238
|
+
/**
|
|
239
|
+
* Move `id` — and the selection, when it is part of one — by `delta` from
|
|
240
|
+
* where the points are now: an input that is not a drag has no earlier
|
|
241
|
+
* position to measure against.
|
|
242
|
+
*/
|
|
243
|
+
nudgeSelection: (id: string, delta: PointPosition) => void;
|
|
244
|
+
/**
|
|
245
|
+
* Move `id` by one press of `option` along one axis, taking the selection
|
|
246
|
+
* along as {@link PointsEditorInstance.nudgeSelection} does.
|
|
247
|
+
*/
|
|
248
|
+
nudgePoint: (id: string, axis: 'x' | 'y', direction: number, option: ModifierValue<InputEventOption>, modifiers?: ModifierState) => void;
|
|
249
|
+
/**
|
|
250
|
+
* Move the point holding the focus by one wheel notch, with its own wheel
|
|
251
|
+
* option. The wheel is listened to once for the whole editor, since a wheel
|
|
252
|
+
* event only reaches what the cursor is over. Returns whether a point took
|
|
253
|
+
* it, so the caller knows whether to consume the event.
|
|
254
|
+
*/
|
|
255
|
+
nudgeFocusedPoint: (axis: 'x' | 'y', direction: number, modifiers: ModifierState) => boolean;
|
|
256
|
+
/** A drag on empty space started at `at`: start a selection box there. */
|
|
257
|
+
beginSelectionBox: (at: PointPosition, modifiers: ModifierState) => void;
|
|
258
|
+
moveSelectionBox: (to: PointPosition) => void;
|
|
259
|
+
/**
|
|
260
|
+
* End the selection box. The press that started it left the focus on
|
|
261
|
+
* nothing, and the arrow keys and the wheel reach a point only through the
|
|
262
|
+
* focus, so it is handed to one of the points the box selected.
|
|
263
|
+
*/
|
|
264
|
+
endSelectionBox: () => void;
|
|
265
|
+
destroy: () => void;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* The selection and the moves of a points editor: which points a press or a
|
|
269
|
+
* box selects, and how a selection moves as one.
|
|
270
|
+
*
|
|
271
|
+
* The points stay with the wrapper, which registers each one; the editor only
|
|
272
|
+
* reads them when it needs to, so a point's value can change on every frame
|
|
273
|
+
* of a drag without anything being re-registered.
|
|
274
|
+
*/
|
|
275
|
+
declare function createPointsEditor(options?: PointsEditorOptions): PointsEditorInstance;
|
|
276
|
+
//#endregion
|
|
277
|
+
//#region src/slider/marks.d.ts
|
|
278
|
+
/**
|
|
279
|
+
* How `Slider.Marks` fills itself in when it is given no children: one option
|
|
280
|
+
* every `per`, or every `step` of the slider. The object form turns off the
|
|
281
|
+
* mark or the label for the whole set; a single option is customized by
|
|
282
|
+
* writing `Slider.MarksOption` out instead.
|
|
283
|
+
*/
|
|
284
|
+
type MarksOptions = 'step' | number | {
|
|
285
|
+
per: 'step' | number;
|
|
286
|
+
mark?: boolean;
|
|
287
|
+
label?: boolean;
|
|
288
|
+
};
|
|
289
|
+
/** One mark along a slider, as {@link sliderMarks} lays them out. */
|
|
290
|
+
interface SliderMark {
|
|
291
|
+
value: number;
|
|
292
|
+
mark: boolean;
|
|
293
|
+
label: boolean;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* The marks `options` asks for between `min` and `max`, in ascending order.
|
|
297
|
+
*
|
|
298
|
+
* Each value is a whole multiple of the interval, rounded to the digits the
|
|
299
|
+
* interval has: stepping by 0.1 would otherwise put binary debris in the
|
|
300
|
+
* labels (`0.1 * 3` is `0.30000000000000004`).
|
|
301
|
+
*/
|
|
302
|
+
declare function sliderMarks(options: MarksOptions, min: number, max: number, step: number): SliderMark[];
|
|
303
|
+
//#endregion
|
|
304
|
+
export { pianoWidth as C, ModifierState as D, ModifierMap as E, ModifierValue as O, notePosition as S, Modifier as T, NoteRange as _, POINTS_EDITOR_DEFAULT_WHEEL as a, fitWhiteKeyWidth as b, PointsEditorInstance as c, clampPoint as d, createPointsEditor as f, toXY as g, XYInput as h, POINTS_EDITOR_DEFAULT_KEYBOARD as i, selectModifier as k, PointsEditorOptions as l, XY as m, SliderMark as n, POINT_AXIS as o, SelectionBoxRect as p, sliderMarks as r, PointPosition as s, MarksOptions as t, PointsEditorPoint as u, PianoLayout as v, InputEventOption as w, getNoteRangeArray as x, blackKeyWidth as y };
|
|
305
|
+
//# sourceMappingURL=marks-DK7xJmGM.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marks-DK7xJmGM.d.ts","names":[],"sources":["../src/input/modifiers.ts","../src/piano/layout.ts","../src/xy.ts","../src/selection/box.ts","../src/points-editor/index.ts","../src/slider/marks.ts"],"mappings":";;;;KAGY;;;;;;;;KASA;;UAGK;EACf;EACA;EACA;EACA;;;KAIG,2BAA2B;KAEpB,YAAY,UAAU;EAAqB,SAAS;IAAM,QACpE,OAAO,UAAU;;;;;;;;KAUP,cAAc,UAAU,mBAAmB,IAAI,YAAY;;;;;;;iBAqCvD,eAAe,UAAU,iBACvC,SAAS,cAAc,IACvB,YAAY;EACT,OAAO;EAAG,UAAU;;;;KCpEb;EACV;EACA;;;;;iBAMc,kBAAkB,WAAW;;;;;;;UAa5B;EACf,WAAW;;EAGX;;;;;;;EAQA;;;;;;EAOA;;;;;;EAOA;;;iBA8Bc,cAAc,QAAQ;;iBA0CtB,WAAW,QAAQ;;;;;;;;iBAYnB,aAAa,cAAc,QAAQ;;;;;;;;;;iBAsDnC,iBACd,eACA,QAAQ,KAAK;;;;;;;KC/LH,GAAG,MAAM,GAAG,GAAG,GAAG;;;;;;;;KASlB,QAAQ,MAAM,4CACZ,GAAG,GAAG,GAAG,KACnB,cAAc,GAAG,GAAG,GAAG;;;;;;;;;;;iBAoBX,KAAK,GAAG,OAAO,cAAc,GAAG,GAAG,GAAG,KAAK,GAAG;;;;;;;UC7B7C;EACf;EACA;EACA;EACA;;;;;UCEe;EACf;EACA;;;;;;cAOW;EAAA;EAAA;;;;;;cAMA,6BAA6B,cAAc;;;;;;;cAW3C,gCAAgC,cAAc;;iBAM3C,WACd,OAAO,eACP,MAAM,QAAQ,gBACd,MAAM,QAAQ,iBACb;;;;;UAWc;EACf,OAAO;EACP,MAAM,QAAQ;EACd,MAAM,QAAQ;;EAEd;EACA,YAAY,OAAO;;EAEnB,UAAU;;EAEV,QAAQ,cAAc;;;;;EAKtB;;UAGe;;;;;;;EAOf;;;;;EAKA;;EAEA,qBAAqB;;EAErB,wBAAwB,MAAM;;UAGf;;EAEf,SAAS,SAAS,QAAQ;;;;;;EAM1B,gBAAgB,YAAY,YAAY;;EAExC,iBAAiB,SAAS;;;;;;;;;;EAU1B,iBAAiB,YAAY,WAAW;;;;;EAKxC,gBAAgB,OAAO;;;;;;EAMvB,iBAAiB,YAAY,OAAO;;;;;EAKpC,aACE,YACA,iBACA,mBACA,QAAQ,cAAc,mBACtB,YAAY;;;;;;;EAQd,oBACE,iBACA,mBACA,WAAW;;EAGb,oBAAoB,IAAI,eAAe,WAAW;EAClD,mBAAmB,IAAI;;;;;;EAMvB;EACA;;;;;;;;;;iBA4Cc,mBACd,UAAS,sBACR;;;;;;;;;KCnMS;EAIN;EACA;EACA;;;UAIW;EACf;EACA;EACA;;;;;;;;;iBAUc,YACd,SAAS,cACT,aACA,aACA,eACC"}
|