@tremolo-ui/dom 0.6.0 → 0.8.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 +1590 -145
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1030 -99
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +1030 -99
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1544 -146
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/file/accept.ts +75 -0
- package/src/file/drop-zone.ts +200 -0
- package/src/index.ts +101 -0
- package/src/input/apply-delta.ts +73 -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/input/modifiers.ts +121 -0
- package/src/knob/geometry.ts +100 -0
- package/src/number-input/stepper-drag.ts +139 -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 +130 -4
- package/src/piano/layout.ts +202 -0
- package/src/piano/shortcuts.ts +86 -0
- package/src/pointer/long-press.ts +103 -0
- package/src/points-editor/index.ts +361 -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
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Scale, ValueRange } from "@tremolo-ui/functions";
|
|
2
2
|
//#region src/canvas/animation.d.ts
|
|
3
3
|
/** What the canvas looked like when a frame was drawn. */
|
|
4
4
|
interface AnimationFrame {
|
|
@@ -89,7 +89,7 @@ interface AnimationCanvasInstance {
|
|
|
89
89
|
* Drawing code works in CSS pixels: the context is scaled by the device pixel
|
|
90
90
|
* ratio, and `width` / `height` of each {@link AnimationFrame} are CSS pixels.
|
|
91
91
|
*/
|
|
92
|
-
declare function createAnimationCanvas(canvas: HTMLCanvasElement, options: AnimationCanvasOptions): AnimationCanvasInstance;
|
|
92
|
+
export declare function createAnimationCanvas(canvas: HTMLCanvasElement, options: AnimationCanvasOptions): AnimationCanvasInstance;
|
|
93
93
|
//#endregion
|
|
94
94
|
//#region src/canvas/context.d.ts
|
|
95
95
|
/**
|
|
@@ -100,7 +100,7 @@ declare function createAnimationCanvas(canvas: HTMLCanvasElement, options: Anima
|
|
|
100
100
|
*
|
|
101
101
|
* @see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/save
|
|
102
102
|
*/
|
|
103
|
-
declare const drawingState: readonly ["strokeStyle", "fillStyle", "globalAlpha", "lineWidth", "lineCap", "lineJoin", "miterLimit", "lineDashOffset", "shadowOffsetX", "shadowOffsetY", "shadowBlur", "shadowColor", "globalCompositeOperation", "filter", "font", "fontKerning", "fontStretch", "fontVariantCaps", "textAlign", "textBaseline", "direction", "letterSpacing", "textRendering", "wordSpacing", "imageSmoothingEnabled", "imageSmoothingQuality"];
|
|
103
|
+
export declare const drawingState: readonly ["strokeStyle", "fillStyle", "globalAlpha", "lineWidth", "lineCap", "lineJoin", "miterLimit", "lineDashOffset", "shadowOffsetX", "shadowOffsetY", "shadowBlur", "shadowColor", "globalCompositeOperation", "filter", "font", "fontKerning", "fontStretch", "fontVariantCaps", "textAlign", "textBaseline", "direction", "letterSpacing", "textRendering", "wordSpacing", "imageSmoothingEnabled", "imageSmoothingQuality"];
|
|
104
104
|
type DrawingState = (typeof drawingState)[number];
|
|
105
105
|
type DrawingStateValue = CanvasRenderingContext2D[DrawingState];
|
|
106
106
|
type DrawingContext = Pick<CanvasRenderingContext2D, DrawingState> & {
|
|
@@ -109,15 +109,396 @@ type DrawingContext = Pick<CanvasRenderingContext2D, DrawingState> & {
|
|
|
109
109
|
/** The current transformation matrix. */
|
|
110
110
|
transform: DOMMatrix;
|
|
111
111
|
};
|
|
112
|
-
declare function isDrawingState(value: unknown): value is DrawingState;
|
|
112
|
+
export declare function isDrawingState(value: unknown): value is DrawingState;
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region src/file/accept.d.ts
|
|
115
|
+
/**
|
|
116
|
+
* What an `accept` rule is matched against.
|
|
117
|
+
*
|
|
118
|
+
* `File` satisfies it, and so does `DataTransferItem` — which matters while a
|
|
119
|
+
* drag is still in the air, since the browser reports the type of what is
|
|
120
|
+
* being dragged but withholds the name.
|
|
121
|
+
*/
|
|
122
|
+
interface AcceptCandidate {
|
|
123
|
+
/** The file name, when it is known. */
|
|
124
|
+
name?: string;
|
|
125
|
+
/** The MIME type, or `''` when the browser has no type for it. */
|
|
126
|
+
type: string;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Does a file satisfy an `accept` attribute?
|
|
130
|
+
*
|
|
131
|
+
* `accept` is written the way the HTML attribute is: a comma separated list of
|
|
132
|
+
* extensions (`.wav`), MIME types (`audio/wav`) and type groups (`audio/*`).
|
|
133
|
+
* Anything that matches one entry is accepted, and an empty or missing
|
|
134
|
+
* `accept` takes everything.
|
|
135
|
+
*
|
|
136
|
+
* **The browser's own `accept` is only a hint to the file picker.** A person
|
|
137
|
+
* can switch it to "All Files", drag a file in, or pick one the picker was
|
|
138
|
+
* never asked about, so what arrives still has to be checked.
|
|
139
|
+
*
|
|
140
|
+
* A rule that cannot be decided is not treated as a rejection: with no `name`,
|
|
141
|
+
* an extension rule says nothing either way, and `accept=".wav"` reports a
|
|
142
|
+
* match rather than refusing a file it has not seen the name of. The name is
|
|
143
|
+
* there by the time the file is dropped, which is when the answer counts.
|
|
144
|
+
*/
|
|
145
|
+
export declare function matchesAccept(candidate: AcceptCandidate, accept?: string): boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Split files into those that satisfy `accept` and those that do not, keeping
|
|
148
|
+
* their order. See {@link matchesAccept}.
|
|
149
|
+
*/
|
|
150
|
+
export declare function partitionByAccept(files: Iterable<File>, accept?: string): {
|
|
151
|
+
accepted: File[];
|
|
152
|
+
rejected: File[];
|
|
153
|
+
};
|
|
154
|
+
//#endregion
|
|
155
|
+
//#region src/file/drop-zone.d.ts
|
|
156
|
+
/** What is in the air over the element. */
|
|
157
|
+
interface DropZoneState {
|
|
158
|
+
/** Files are being dragged over the element. */
|
|
159
|
+
over: boolean;
|
|
160
|
+
/**
|
|
161
|
+
* None of what is being dragged matches `accept`, as far as can be told
|
|
162
|
+
* before the drop.
|
|
163
|
+
*
|
|
164
|
+
* The browser reports the type of what is being dragged but withholds the
|
|
165
|
+
* name, so a rule written as an extension cannot be decided yet and is not
|
|
166
|
+
* counted against the drag. It is decided on the drop, where the name is.
|
|
167
|
+
*/
|
|
168
|
+
invalid: boolean;
|
|
169
|
+
}
|
|
170
|
+
interface DropZoneOptions {
|
|
171
|
+
/**
|
|
172
|
+
* Which files to take, written the way the `accept` attribute of a file
|
|
173
|
+
* input is: a comma separated list of extensions (`.wav`), MIME types
|
|
174
|
+
* (`audio/wav`) and type groups (`audio/*`).
|
|
175
|
+
*/
|
|
176
|
+
accept?: string;
|
|
177
|
+
/**
|
|
178
|
+
* Take more than one file from a single drop. With it off, only the first
|
|
179
|
+
* accepted file is reported, as a file input without `multiple` does.
|
|
180
|
+
*
|
|
181
|
+
* @default false
|
|
182
|
+
*/
|
|
183
|
+
multiple?: boolean;
|
|
184
|
+
/**
|
|
185
|
+
* Refuse the drop. The drag is still swallowed rather than let through: an
|
|
186
|
+
* unhandled drop makes the browser leave the page and open the file.
|
|
187
|
+
*
|
|
188
|
+
* @default false
|
|
189
|
+
*/
|
|
190
|
+
disabled?: boolean;
|
|
191
|
+
/** Called with the dropped files that match `accept`. */
|
|
192
|
+
onDrop?: (files: File[], event: DragEvent) => void;
|
|
193
|
+
/**
|
|
194
|
+
* Called with the dropped files that do not match `accept`, so that the
|
|
195
|
+
* reason can be shown. It comes after `onDrop` for the same drop, so a list
|
|
196
|
+
* of rejected files can be cleared in `onDrop` and filled here.
|
|
197
|
+
*/
|
|
198
|
+
onReject?: (files: File[], event: DragEvent) => void;
|
|
199
|
+
/** Called whenever {@link DropZoneInstance.state} would change. */
|
|
200
|
+
onStateChange?: (state: DropZoneState) => void;
|
|
201
|
+
}
|
|
202
|
+
interface DropZoneInstance {
|
|
203
|
+
/** What is in the air over the element, right now. */
|
|
204
|
+
readonly state: DropZoneState;
|
|
205
|
+
/** Replace the given options, keeping the listeners in place. */
|
|
206
|
+
update: (options: DropZoneOptions) => void;
|
|
207
|
+
destroy: () => void;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Take files dropped onto an element.
|
|
211
|
+
*
|
|
212
|
+
* ```ts
|
|
213
|
+
* const zone = createDropZone(element, {
|
|
214
|
+
* accept: 'audio/*',
|
|
215
|
+
* onDrop: (files) => load(files[0]),
|
|
216
|
+
* })
|
|
217
|
+
* ```
|
|
218
|
+
*
|
|
219
|
+
* The element needs no attribute of its own: a drop target is made by
|
|
220
|
+
* cancelling `dragover`, which this does.
|
|
221
|
+
*/
|
|
222
|
+
export declare function createDropZone(element: Element, options?: DropZoneOptions): DropZoneInstance;
|
|
223
|
+
//#endregion
|
|
224
|
+
//#region src/input/modifiers.d.ts
|
|
225
|
+
/**
|
|
226
|
+
* Options for setting the amount of keyboard and mouse wheel changes.
|
|
227
|
+
*/
|
|
228
|
+
type InputEventOption = readonly ['normalized' | 'raw', number];
|
|
229
|
+
/**
|
|
230
|
+
* A modifier key that can carry an amount of its own.
|
|
231
|
+
*
|
|
232
|
+
* `ctrl` and `meta` are kept apart rather than folded into one "command" key:
|
|
233
|
+
* a plugin UI that mirrors a desktop host usually wants the same physical key
|
|
234
|
+
* on every platform, not the platform's own convention.
|
|
235
|
+
*/
|
|
236
|
+
type Modifier = 'shift' | 'alt' | 'ctrl' | 'meta';
|
|
237
|
+
/** The modifier flags of a `WheelEvent` or a `KeyboardEvent`. */
|
|
238
|
+
interface ModifierState {
|
|
239
|
+
shiftKey: boolean;
|
|
240
|
+
altKey: boolean;
|
|
241
|
+
ctrlKey: boolean;
|
|
242
|
+
metaKey: boolean;
|
|
243
|
+
}
|
|
244
|
+
/** One setting per modifier key, with `default` for none of them. */
|
|
245
|
+
type ModifierSetting = number | InputEventOption;
|
|
246
|
+
type ModifierMap<T extends ModifierSetting> = {
|
|
247
|
+
default: T;
|
|
248
|
+
} & Partial<Record<Modifier, T>>;
|
|
249
|
+
/**
|
|
250
|
+
* A single setting, or one per modifier key.
|
|
251
|
+
*
|
|
252
|
+
* @example
|
|
253
|
+
* ['raw', 1]
|
|
254
|
+
* { default: ['raw', 1], shift: ['raw', 0.1] }
|
|
255
|
+
*/
|
|
256
|
+
type ModifierValue<T extends ModifierSetting> = T | ModifierMap<T>;
|
|
257
|
+
/**
|
|
258
|
+
* Pick the setting that applies, given the modifier keys being held.
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* selectModifier({ default: 1, shift: 0.1 }, event)
|
|
262
|
+
*/
|
|
263
|
+
export declare function selectModifier<T extends ModifierSetting>(options: ModifierValue<T>, modifiers?: ModifierState): {
|
|
264
|
+
value: T;
|
|
265
|
+
modifier: Modifier | null;
|
|
266
|
+
};
|
|
267
|
+
/**
|
|
268
|
+
* Turn every entry of a setting into another kind of setting, keeping which
|
|
269
|
+
* modifier each belongs to.
|
|
270
|
+
*
|
|
271
|
+
* A drag sensitivity is a number and a keyboard amount is a tuple, but the two
|
|
272
|
+
* describe the same thing from the caller's side. This carries one over to the
|
|
273
|
+
* other so that a component can hand a sensitivity to {@link applyDelta}
|
|
274
|
+
* without unpicking the modifier map itself — which matters, since naming a
|
|
275
|
+
* modifier is also what takes `step` out of the pipeline.
|
|
276
|
+
*
|
|
277
|
+
* @example
|
|
278
|
+
* mapModifier({ default: 1, shift: 0.1 }, (f) => ['raw', step * f])
|
|
279
|
+
* // { default: ['raw', 1], shift: ['raw', 0.1] }
|
|
280
|
+
*/
|
|
281
|
+
export declare function mapModifier<T extends ModifierSetting, U extends ModifierSetting>(options: ModifierValue<T>, fn: (value: T) => U): ModifierValue<U>;
|
|
282
|
+
//#endregion
|
|
283
|
+
//#region src/input/apply-delta.d.ts
|
|
284
|
+
/**
|
|
285
|
+
* Move a value by an amount of input, as reported by a wheel or an arrow key.
|
|
286
|
+
*
|
|
287
|
+
* The pipeline matches {@link createDragValue}: scale, then step, then clamp.
|
|
288
|
+
* Which key or which sign of `deltaY` counts as which direction is left to the
|
|
289
|
+
* caller, since it differs per component.
|
|
290
|
+
*
|
|
291
|
+
* @param direction which way, and how many times, to apply the option. The
|
|
292
|
+
* size of one step is `option[1]`, so this is normally `1` or `-1`.
|
|
293
|
+
*
|
|
294
|
+
* @param modifiers the event, for `options` that name a modifier key. See
|
|
295
|
+
* {@link selectModifier}.
|
|
296
|
+
*
|
|
297
|
+
* @example
|
|
298
|
+
* // ArrowDown on a slider whose keyboard option is ['raw', 1]
|
|
299
|
+
* applyDelta(value, -1, keyboard, { min, max, step, scale })
|
|
300
|
+
*
|
|
301
|
+
* @example
|
|
302
|
+
* // Shift+ArrowDown, where `keyboard` is { default: …, shift: ['raw', 0.1] }
|
|
303
|
+
* applyDelta(value, -1, keyboard, range, event)
|
|
304
|
+
*/
|
|
305
|
+
export declare function applyDelta(value: number, direction: number, options: ModifierValue<InputEventOption>, { min, max, step, scale }: ValueRange, modifiers?: ModifierState): number;
|
|
306
|
+
//#endregion
|
|
307
|
+
//#region src/input/check-steps.d.ts
|
|
308
|
+
interface CheckStepsOptions {
|
|
309
|
+
/** The component, for the message. */
|
|
310
|
+
component: string;
|
|
311
|
+
/** The axis, for a component that has more than one. */
|
|
312
|
+
axis?: string;
|
|
313
|
+
/**
|
|
314
|
+
* The range to probe, or `null` to check nothing. An unbounded input has no
|
|
315
|
+
* travel to sample, so `NumberInput` passes `null` when `min` and `max` are
|
|
316
|
+
* not both there.
|
|
317
|
+
*/
|
|
318
|
+
range: ValueRange | null;
|
|
319
|
+
keyboard?: ModifierValue<InputEventOption> | null;
|
|
320
|
+
wheel?: ModifierValue<InputEventOption> | null;
|
|
321
|
+
/**
|
|
322
|
+
* How the value is displayed, where the component shows one. Called with
|
|
323
|
+
* probe values only.
|
|
324
|
+
*/
|
|
325
|
+
format?: (value: number) => string;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* The warnings to show when a key press or a wheel notch cannot produce a
|
|
329
|
+
* change the user can see. Empty when there is nothing to say.
|
|
330
|
+
*
|
|
331
|
+
* Two settings that are each fine on their own can cancel out, and nothing
|
|
332
|
+
* fails when they do — the control simply sits there:
|
|
333
|
+
*
|
|
334
|
+
* - **`step` coarser than the amount.** `keyboard={['raw', 0.1]}` with
|
|
335
|
+
* `step={1}` rounds every press straight back to where it started
|
|
336
|
+
* - **the display coarser than the amount.** A `format` showing two decimals
|
|
337
|
+
* of a kHz value cannot show a press worth 1 Hz
|
|
338
|
+
*
|
|
339
|
+
* The second is only reported when the press is invisible at *every* point
|
|
340
|
+
* along the travel. A display that rounds is a deliberate choice and is
|
|
341
|
+
* normally right — it is being too coarse everywhere that makes it a mistake.
|
|
342
|
+
*
|
|
343
|
+
* **Meant for development builds only.** It probes the whole travel, so call
|
|
344
|
+
* it behind an inline `process.env.NODE_ENV` check: the bundler then drops
|
|
345
|
+
* the call, and this function and its messages with it.
|
|
346
|
+
*/
|
|
347
|
+
export declare function checkSteps({ component, axis, range, keyboard, wheel, format }: CheckStepsOptions): string[];
|
|
348
|
+
//#endregion
|
|
349
|
+
//#region src/input/defaults.d.ts
|
|
350
|
+
/**
|
|
351
|
+
* The keyboard amount used by Knob, NumberInput, Slider, and XYPad by default:
|
|
352
|
+
* 1 per press in the units of the value, and 0.1 with shift held. That is one
|
|
353
|
+
* `step` only while `step` is 1; a coarser `step` rounds 1 straight back, which
|
|
354
|
+
* `checkSteps` warns about.
|
|
355
|
+
*
|
|
356
|
+
* A modifier entry is not snapped to `step`, which is what lets the finer
|
|
357
|
+
* amount move at all — see `applyDelta`.
|
|
358
|
+
*/
|
|
359
|
+
export declare const DEFAULT_KEYBOARD_OPTIONS: ModifierValue<InputEventOption>;
|
|
360
|
+
/**
|
|
361
|
+
* The wheel amount used by Knob, NumberInput, Slider, and XYPad by default.
|
|
362
|
+
*
|
|
363
|
+
* Browsers turn shift+wheel into horizontal scrolling, which empties `deltaY`
|
|
364
|
+
* and fills `deltaX`, so no modifier is bound here.
|
|
365
|
+
*/
|
|
366
|
+
export declare const DEFAULT_WHEEL_OPTIONS: ModifierValue<InputEventOption>;
|
|
367
|
+
/**
|
|
368
|
+
* The drag sensitivity used by value controls by default. Shift makes the
|
|
369
|
+
* same movement cover a tenth of the range, matching the arrow keys.
|
|
370
|
+
*/
|
|
371
|
+
export declare const DEFAULT_DRAG_SENSITIVITY: ModifierValue<number>;
|
|
372
|
+
//#endregion
|
|
373
|
+
//#region src/input/direction.d.ts
|
|
374
|
+
/**
|
|
375
|
+
* Which way an input moves a value, before any amount is applied.
|
|
376
|
+
*
|
|
377
|
+
* `applyDelta` takes the direction as given, since which key or which sign of
|
|
378
|
+
* `deltaY` counts as "up" differs per control. The answers are collected here
|
|
379
|
+
* so that every wrapper gives the same one: a knob that turns the other way
|
|
380
|
+
* in one framework would be a bug nobody could see from the code.
|
|
381
|
+
*
|
|
382
|
+
* Two families, by what the control looks like:
|
|
383
|
+
*
|
|
384
|
+
* - **one value** (`Knob`, `Slider`, `NumberInput`): right and up raise it
|
|
385
|
+
* - **a position on screen** (`XYPad`, `PointsEditor`): in screen coordinates,
|
|
386
|
+
* x growing rightwards and y growing downwards, plus which axis moves
|
|
387
|
+
*
|
|
388
|
+
* A control that runs the other way (`reverse`) flips the result itself.
|
|
389
|
+
*/
|
|
390
|
+
/** One of the four arrow keys, as `KeyboardEvent.key` names it. */
|
|
391
|
+
type ArrowKey = 'ArrowRight' | 'ArrowLeft' | 'ArrowUp' | 'ArrowDown';
|
|
392
|
+
/** Is `key` one of the four arrow keys? */
|
|
393
|
+
export declare function isArrowKey(key: string): key is ArrowKey;
|
|
394
|
+
/** A move along one of the two axes of a position on screen. */
|
|
395
|
+
interface AxisMove {
|
|
396
|
+
/** 0 = x, 1 = y. */
|
|
397
|
+
axis: 0 | 1;
|
|
398
|
+
/** `1` towards the right or the bottom, `-1` towards the left or the top. */
|
|
399
|
+
direction: 1 | -1;
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* The direction an arrow key moves a single value: right and up raise it.
|
|
403
|
+
* `null` for any other key.
|
|
404
|
+
*/
|
|
405
|
+
export declare function arrowKeyDirection(key: string): 1 | -1 | null;
|
|
406
|
+
/**
|
|
407
|
+
* The axis and direction an arrow key moves a position on screen. `null` for
|
|
408
|
+
* any other key.
|
|
409
|
+
*
|
|
410
|
+
* The key picks the axis, whichever element inside the control holds the
|
|
411
|
+
* focus: a two-dimensional control is one control to the person moving it.
|
|
412
|
+
*/
|
|
413
|
+
export declare function arrowKeyMove(key: string): AxisMove | null;
|
|
414
|
+
interface WheelDirectionOptions {
|
|
415
|
+
/**
|
|
416
|
+
* Read horizontal scrolling as well, for a control laid out horizontally:
|
|
417
|
+
* scrolling right raises the value. Vertical scrolling still counts when
|
|
418
|
+
* there is no horizontal movement.
|
|
419
|
+
*
|
|
420
|
+
* @default false
|
|
421
|
+
*/
|
|
422
|
+
horizontal?: boolean;
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* The direction one wheel event moves a single value: scrolling up raises it.
|
|
426
|
+
* `null` when the event carries no movement the control reads.
|
|
427
|
+
*/
|
|
428
|
+
export declare function wheelDirection(event: Pick<WheelEvent, 'deltaX' | 'deltaY'>, { horizontal }?: WheelDirectionOptions): 1 | -1 | null;
|
|
429
|
+
/**
|
|
430
|
+
* The axis and direction one wheel event moves a position on screen. `null`
|
|
431
|
+
* when the event carries no movement.
|
|
432
|
+
*
|
|
433
|
+
* Scrolling moves y, and shift switches to x. Browsers turn shift+wheel into
|
|
434
|
+
* horizontal scrolling: `deltaY` comes out empty and `deltaX` carries the
|
|
435
|
+
* movement. Reading whichever axis moved keeps shift working as the x-axis
|
|
436
|
+
* modifier — and picks up a trackpad's own horizontal gesture, which never
|
|
437
|
+
* had a modifier.
|
|
438
|
+
*/
|
|
439
|
+
export declare function wheelMove(event: Pick<WheelEvent, 'deltaX' | 'deltaY' | 'shiftKey'>): AxisMove | null;
|
|
440
|
+
//#endregion
|
|
441
|
+
//#region src/knob/geometry.d.ts
|
|
442
|
+
/**
|
|
443
|
+
* Width and height of the viewBox a knob is drawn in. The arcs and the thumb
|
|
444
|
+
* are laid out in these units, and the SVG scales them to the knob's size.
|
|
445
|
+
*/
|
|
446
|
+
export declare const KNOB_VIEWBOX_SIZE = 100;
|
|
447
|
+
interface KnobAngleOptions {
|
|
448
|
+
value: number;
|
|
449
|
+
min: number;
|
|
450
|
+
max: number;
|
|
451
|
+
scale: Scale;
|
|
452
|
+
/** Where the active arc starts from, so that it can grow from the middle. */
|
|
453
|
+
startValue: number;
|
|
454
|
+
/** How far the knob turns from `min` to `max`, in degrees. */
|
|
455
|
+
angleRange: number;
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* The angles a knob is drawn with, in degrees clockwise from the top.
|
|
459
|
+
*
|
|
460
|
+
* The travel is centred on the top, so `angleRange` of 270 runs from -135 to
|
|
461
|
+
* 135. Derived from the value alone, so a wrapper can call it while rendering.
|
|
462
|
+
*/
|
|
463
|
+
interface KnobAngles {
|
|
464
|
+
/** The value, normalized to 0..1 along the scale. */
|
|
465
|
+
p: number;
|
|
466
|
+
/** Where the travel starts. */
|
|
467
|
+
r1: number;
|
|
468
|
+
/** Where the active arc starts: the lower of the value and `startValue`. */
|
|
469
|
+
r2: number;
|
|
470
|
+
/** Where the active arc ends: the higher of the value and `startValue`. */
|
|
471
|
+
r3: number;
|
|
472
|
+
/** Where the travel ends. */
|
|
473
|
+
r4: number;
|
|
474
|
+
}
|
|
475
|
+
export declare function knobAngles({ value, min, max, scale, startValue, angleRange }: KnobAngleOptions): KnobAngles;
|
|
476
|
+
/**
|
|
477
|
+
* The point at `angle` on a circle of `radius` around the centre of the
|
|
478
|
+
* viewBox.
|
|
479
|
+
*
|
|
480
|
+
* The radius depends on the stroke of the line being drawn, which each arc
|
|
481
|
+
* has its own of, so the point is found per arc rather than once for the knob.
|
|
482
|
+
*/
|
|
483
|
+
export declare function knobArcPoint(angle: number, radius: number): {
|
|
484
|
+
x: number;
|
|
485
|
+
y: number;
|
|
486
|
+
};
|
|
487
|
+
/**
|
|
488
|
+
* The radius that keeps a stroke of `strokeWidth` inside the viewBox: half of
|
|
489
|
+
* the stroke falls outside the path it is drawn along.
|
|
490
|
+
*/
|
|
491
|
+
export declare function knobArcRadius(strokeWidth: number | string | undefined): number;
|
|
492
|
+
/** Build an SVG path for an arc, splitting full turns into drawable segments. */
|
|
493
|
+
export declare function knobArcPath(startAngle: number, endAngle: number, radius: number): string;
|
|
113
494
|
//#endregion
|
|
114
495
|
//#region src/midi/access.d.ts
|
|
115
496
|
/** @private */
|
|
116
|
-
declare const PERMISSION_DENIED = "PERMISSION_DENIED";
|
|
497
|
+
export declare const PERMISSION_DENIED = "PERMISSION_DENIED";
|
|
117
498
|
/** @private */
|
|
118
|
-
declare const NOT_SUPPORTED = "NOT_SUPPORTED";
|
|
499
|
+
export declare const NOT_SUPPORTED = "NOT_SUPPORTED";
|
|
119
500
|
/** @private */
|
|
120
|
-
declare const UNAVAILABLE = "UNAVAILABLE";
|
|
501
|
+
export declare const UNAVAILABLE = "UNAVAILABLE";
|
|
121
502
|
/** @private */
|
|
122
503
|
type MIDIAccessError = typeof PERMISSION_DENIED | typeof NOT_SUPPORTED | typeof UNAVAILABLE;
|
|
123
504
|
type MIDIAccessOptions = {
|
|
@@ -158,7 +539,7 @@ interface MIDIAccessInstance {
|
|
|
158
539
|
* The returned instance holds the state and notifies subscribers when it changes,
|
|
159
540
|
* so it can be consumed from any framework.
|
|
160
541
|
*/
|
|
161
|
-
declare function createMIDIAccess(): MIDIAccessInstance;
|
|
542
|
+
export declare function createMIDIAccess(): MIDIAccessInstance;
|
|
162
543
|
//#endregion
|
|
163
544
|
//#region src/midi/input.d.ts
|
|
164
545
|
/**
|
|
@@ -167,7 +548,7 @@ declare function createMIDIAccess(): MIDIAccessInstance;
|
|
|
167
548
|
* The range is not symmetric — 0 is 8192 below centre and 16383 is 8191 above
|
|
168
549
|
* — so a wheel at rest reports exactly this rather than half of the maximum.
|
|
169
550
|
*/
|
|
170
|
-
declare const PITCH_BEND_CENTER = 8192;
|
|
551
|
+
export declare const PITCH_BEND_CENTER = 8192;
|
|
171
552
|
/**
|
|
172
553
|
* Every handler is given the channel last, as 0-15. MIDI channels are written
|
|
173
554
|
* 1-16 on hardware, so add one before showing it to anyone.
|
|
@@ -203,7 +584,7 @@ interface MIDIInputInstance {
|
|
|
203
584
|
* System messages (clock, sysex, and the rest of `0xf0`-`0xff`) are not
|
|
204
585
|
* decoded here; reach for {@link createMIDIMessage} for those.
|
|
205
586
|
*/
|
|
206
|
-
declare function createMIDIInput(midiAccess: MIDIAccess | null, handlers: MIDIInputHandlers): MIDIInputInstance;
|
|
587
|
+
export declare function createMIDIInput(midiAccess: MIDIAccess | null, handlers: MIDIInputHandlers): MIDIInputInstance;
|
|
207
588
|
//#endregion
|
|
208
589
|
//#region src/midi/message.d.ts
|
|
209
590
|
interface MIDIMessageInstance {
|
|
@@ -221,7 +602,292 @@ interface MIDIMessageInstance {
|
|
|
221
602
|
*
|
|
222
603
|
* Use this when you need more detail than {@link createMIDIInput} provides.
|
|
223
604
|
*/
|
|
224
|
-
declare function createMIDIMessage(midiAccess: MIDIAccess | null, onMIDIMessage: (event: MIDIMessageEvent) => void): MIDIMessageInstance;
|
|
605
|
+
export declare function createMIDIMessage(midiAccess: MIDIAccess | null, onMIDIMessage: (event: MIDIMessageEvent) => void): MIDIMessageInstance;
|
|
606
|
+
//#endregion
|
|
607
|
+
//#region src/number-input/stepper-drag.d.ts
|
|
608
|
+
interface StepperDragOptions {
|
|
609
|
+
/** The value now, read when the drag starts moving it. */
|
|
610
|
+
getValue: () => number;
|
|
611
|
+
/**
|
|
612
|
+
* The range the value moves across. Its `step` is what one step of the drag
|
|
613
|
+
* is worth; see `numberInputRanges` for the one a number input uses.
|
|
614
|
+
*/
|
|
615
|
+
range: ValueRange;
|
|
616
|
+
/**
|
|
617
|
+
* How many pixels of vertical movement make one step.
|
|
618
|
+
*
|
|
619
|
+
* @default 1
|
|
620
|
+
*/
|
|
621
|
+
pixels?: number;
|
|
622
|
+
/**
|
|
623
|
+
* How much a step is worth, per modifier key: `0.1` makes the same movement
|
|
624
|
+
* count a tenth as much. Pressing or releasing the key mid-drag does not
|
|
625
|
+
* move the value.
|
|
626
|
+
*
|
|
627
|
+
* @default { default: 1, shift: 0.1 }
|
|
628
|
+
*/
|
|
629
|
+
sensitivity?: ModifierValue<number>;
|
|
630
|
+
/** Hide the pointer and keep it from hitting the edge of the screen. */
|
|
631
|
+
pointerLock?: boolean;
|
|
632
|
+
/** Called with the new value whenever the drag moves it. */
|
|
633
|
+
onChange: (value: number) => void;
|
|
634
|
+
}
|
|
635
|
+
interface StepperDragInstance {
|
|
636
|
+
/** Replace the given options. `pointerLock` reaches the next drag. */
|
|
637
|
+
update: (options: Partial<StepperDragOptions>) => void;
|
|
638
|
+
/**
|
|
639
|
+
* Whether the drag in progress has moved the value. A stepper button's
|
|
640
|
+
* press-and-hold repeat stands down once it has, so the value is not moved
|
|
641
|
+
* twice.
|
|
642
|
+
*/
|
|
643
|
+
moved: () => boolean;
|
|
644
|
+
destroy: () => void;
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Drag up and down on the steppers of a number input to move its value, one
|
|
648
|
+
* `step` every `pixels` — up raises it, as on a knob.
|
|
649
|
+
*
|
|
650
|
+
* Counted from where the drag started moving rather than added up per
|
|
651
|
+
* event, so rounding cannot accumulate. The start is taken on the first
|
|
652
|
+
* move, not on pointerdown: a stepper button acts on pointerdown, so by then
|
|
653
|
+
* the value may already have been nudged once, and the drag carries on from
|
|
654
|
+
* there.
|
|
655
|
+
*/
|
|
656
|
+
export declare function createStepperDrag(element: Element, options: StepperDragOptions): StepperDragInstance;
|
|
657
|
+
//#endregion
|
|
658
|
+
//#region src/number-input/value.d.ts
|
|
659
|
+
/**
|
|
660
|
+
* The value a number input edits, and how far it may go.
|
|
661
|
+
*
|
|
662
|
+
* Unlike a slider, either end may be left open, and `clampValue: false` lets
|
|
663
|
+
* the value past the ends that are set.
|
|
664
|
+
*/
|
|
665
|
+
interface NumberInputValueOptions {
|
|
666
|
+
min?: number;
|
|
667
|
+
max?: number;
|
|
668
|
+
step?: number;
|
|
669
|
+
scale?: Scale;
|
|
670
|
+
/**
|
|
671
|
+
* Keep the value between `min` and `max`.
|
|
672
|
+
*
|
|
673
|
+
* @default true
|
|
674
|
+
*/
|
|
675
|
+
clampValue?: boolean;
|
|
676
|
+
}
|
|
677
|
+
/** The ranges {@link nudgeNumberInput} moves a value across. */
|
|
678
|
+
interface NumberInputRanges {
|
|
679
|
+
/** For a `normalized` amount, which needs a finite span to take a share of. */
|
|
680
|
+
normalized: ValueRange;
|
|
681
|
+
/** For a `raw` amount, which does not. */
|
|
682
|
+
raw: ValueRange;
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* The ranges a number input moves its value across, with the open ends
|
|
686
|
+
* filled in.
|
|
687
|
+
*
|
|
688
|
+
* A normalized amount needs a finite span even when an end is unbounded or
|
|
689
|
+
* clamping is off. Safe integers provide one without overflowing the span a
|
|
690
|
+
* scale calculates. A raw amount needs no span, so its open ends can cover
|
|
691
|
+
* every finite number instead of stopping at the safe-integer range.
|
|
692
|
+
*/
|
|
693
|
+
export declare function numberInputRanges({ min, max, step, scale, clampValue }: NumberInputValueOptions): NumberInputRanges;
|
|
694
|
+
/**
|
|
695
|
+
* Move a number input's value by one press of a key, a wheel notch or a
|
|
696
|
+
* stepper, picking the range that suits the kind of amount. See `applyDelta`.
|
|
697
|
+
*/
|
|
698
|
+
export declare function nudgeNumberInput(value: number, direction: number, options: ModifierValue<InputEventOption>, ranges: NumberInputRanges, modifiers?: ModifierState): number;
|
|
699
|
+
/**
|
|
700
|
+
* Where the value stands against the ends: whether it can go no further
|
|
701
|
+
* down or up, and whether it lies outside them — which only an unclamped
|
|
702
|
+
* input, or a value set from outside, can do.
|
|
703
|
+
*/
|
|
704
|
+
export declare function numberInputBounds(value: number, { min, max, clampValue }: NumberInputValueOptions): {
|
|
705
|
+
atMin: boolean;
|
|
706
|
+
atMax: boolean;
|
|
707
|
+
outOfRange: boolean;
|
|
708
|
+
};
|
|
709
|
+
/**
|
|
710
|
+
* The value typed text commits to, or `null` when there is no number in it.
|
|
711
|
+
*
|
|
712
|
+
* Text with no number is not a value: the input should go back to what it
|
|
713
|
+
* was showing rather than commit a zero the user never typed. What is read
|
|
714
|
+
* is clamped here and not while typing, since clamping as the user types
|
|
715
|
+
* would make "1500" impossible to enter into an input whose max is 100.
|
|
716
|
+
*/
|
|
717
|
+
export declare function commitNumberInputText(text: string, parse: (text: string) => number, { min, max, clampValue }: NumberInputValueOptions): number | null;
|
|
718
|
+
//#endregion
|
|
719
|
+
//#region src/number-input/text.d.ts
|
|
720
|
+
/**
|
|
721
|
+
* Reading a number out of the text of a number input, and keeping the caret
|
|
722
|
+
* in place while the number under it changes.
|
|
723
|
+
*
|
|
724
|
+
* The text is whatever `format` made of the value — `"440 Hz"`, `"-6.0 dB"` —
|
|
725
|
+
* or a half-typed entry, so none of this assumes the text is a number alone.
|
|
726
|
+
*/
|
|
727
|
+
/** Where the number is in the text; the rest, on either side, is the unit. */
|
|
728
|
+
interface NumberSpan {
|
|
729
|
+
start: number;
|
|
730
|
+
end: number;
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* Where the number is in the text: from its first digit to its last, with the
|
|
734
|
+
* sign and the decimal point in front of it. Whatever is left on either side
|
|
735
|
+
* is taken for the unit, so it does not matter whether a space separates them,
|
|
736
|
+
* or what the number looks like — `+6.0`, `1e+21`, `1,000` and `1:30` are each
|
|
737
|
+
* one number. `null` when the text has no digit at all.
|
|
738
|
+
*/
|
|
739
|
+
export declare function numberSpan(text: string): NumberSpan | null;
|
|
740
|
+
/**
|
|
741
|
+
* The number in the text, with the unit after it ignored: the default `parse`
|
|
742
|
+
* of a number input.
|
|
743
|
+
*
|
|
744
|
+
* `NaN`, which leaves the value alone, whenever the number cannot be read
|
|
745
|
+
* safely, rather than a part of it: text with no number, a number that is not
|
|
746
|
+
* a plain one (`1,000` would otherwise read as 1, and `1:30` as 1), and text
|
|
747
|
+
* with something in front of the number, which can change what it means (the
|
|
748
|
+
* `L` of a pan reading `L 30`). A `format` that writes any of those needs its
|
|
749
|
+
* own `parse`.
|
|
750
|
+
*/
|
|
751
|
+
export declare function parseNumberText(text: string): number;
|
|
752
|
+
/**
|
|
753
|
+
* Where the caret is, relative to the decimal point, so that it can be put
|
|
754
|
+
* back at the same digit once the value has changed. See
|
|
755
|
+
* {@link caretAtDecimalOffset}.
|
|
756
|
+
*/
|
|
757
|
+
export declare function caretDecimalOffset(text: string, caret: number): number;
|
|
758
|
+
/**
|
|
759
|
+
* The caret position `offset` characters from the decimal point of the new
|
|
760
|
+
* text, kept within the number.
|
|
761
|
+
*
|
|
762
|
+
* @example
|
|
763
|
+
* // The caret sits in front of the point of "9.9" when ArrowUp turns it
|
|
764
|
+
* // into "10.0"
|
|
765
|
+
* const offset = caretDecimalOffset('9.9', 1) // 0
|
|
766
|
+
* caretAtDecimalOffset('10.0', offset) // 2: still in front of the point
|
|
767
|
+
*/
|
|
768
|
+
export declare function caretAtDecimalOffset(text: string, offset: number): number;
|
|
769
|
+
//#endregion
|
|
770
|
+
//#region src/options/replace.d.ts
|
|
771
|
+
/**
|
|
772
|
+
* The `update()` argument that leaves an instance with exactly `next` as its
|
|
773
|
+
* options.
|
|
774
|
+
*
|
|
775
|
+
* `update()` merges into what the instance has, which suits a wrapper that
|
|
776
|
+
* pushes one setting at a time. A wrapper handed the whole new set instead —
|
|
777
|
+
* a Svelte action, a Vue composable — has to clear what the new set no longer
|
|
778
|
+
* carries, or a handler taken away, or an option left to its default, keeps
|
|
779
|
+
* working.
|
|
780
|
+
*
|
|
781
|
+
* @example
|
|
782
|
+
* instance.update(replaceOptions(previous, next))
|
|
783
|
+
*/
|
|
784
|
+
export declare function replaceOptions<T extends object>(previous: T | undefined, next: T | undefined): Partial<T>;
|
|
785
|
+
//#endregion
|
|
786
|
+
//#region src/piano/layout.d.ts
|
|
787
|
+
type NoteRange = {
|
|
788
|
+
first: number;
|
|
789
|
+
last: number;
|
|
790
|
+
};
|
|
791
|
+
/**
|
|
792
|
+
* `[noteRange.first, noteRange.first + 1, ..., noteRange.last]`
|
|
793
|
+
*/
|
|
794
|
+
export declare function getNoteRangeArray(noteRange: NoteRange): number[];
|
|
795
|
+
/**
|
|
796
|
+
* The geometry of a drawn keyboard.
|
|
797
|
+
*
|
|
798
|
+
* One description is shared by the drawing and the hit testing, so a key cannot
|
|
799
|
+
* be drawn somewhere other than where it responds.
|
|
800
|
+
*/
|
|
801
|
+
interface PianoLayout {
|
|
802
|
+
noteRange: NoteRange;
|
|
803
|
+
/** Width of a white key, excluding {@link PianoLayout.keyGap}. */
|
|
804
|
+
whiteKeyWidth: number;
|
|
805
|
+
/**
|
|
806
|
+
* Space between two white keys. Part of the slot a white key occupies, so it
|
|
807
|
+
* still belongs to one of the keys for the purpose of hit testing.
|
|
808
|
+
*
|
|
809
|
+
* @default 1
|
|
810
|
+
*/
|
|
811
|
+
keyGap?: number;
|
|
812
|
+
/**
|
|
813
|
+
* Width of a black key, as a fraction of {@link PianoLayout.whiteKeyWidth}.
|
|
814
|
+
*
|
|
815
|
+
* @default 0.65
|
|
816
|
+
*/
|
|
817
|
+
blackKeyWidthRatio?: number;
|
|
818
|
+
/**
|
|
819
|
+
* Height of a black key, as a fraction of the height of the keyboard.
|
|
820
|
+
*
|
|
821
|
+
* @default 0.6
|
|
822
|
+
*/
|
|
823
|
+
blackKeyHeightRatio?: number;
|
|
824
|
+
}
|
|
825
|
+
/** Width of a black key in pixels. */
|
|
826
|
+
export declare function blackKeyWidth(layout: PianoLayout): number;
|
|
827
|
+
/** Width of the whole keyboard in pixels. */
|
|
828
|
+
export declare function pianoWidth(layout: PianoLayout): number;
|
|
829
|
+
/**
|
|
830
|
+
* Offset of the left edge of a key from the left edge of the keyboard, in
|
|
831
|
+
* pixels.
|
|
832
|
+
*
|
|
833
|
+
* Notes outside `noteRange` are placed too, so the value is negative below
|
|
834
|
+
* `noteRange.first`.
|
|
835
|
+
*/
|
|
836
|
+
export declare function notePosition(note: number, layout: PianoLayout): number;
|
|
837
|
+
/**
|
|
838
|
+
* The note drawn at a point, or null where there is none.
|
|
839
|
+
*
|
|
840
|
+
* Black keys are tested first, so they win where they overlap a white one. A
|
|
841
|
+
* white key covers its gap as well as its width, so the whole width of the
|
|
842
|
+
* keyboard belongs to some key and a click cannot fall between two.
|
|
843
|
+
*
|
|
844
|
+
* @param x offset from the left edge of the keyboard, in pixels
|
|
845
|
+
* @param y offset from its top edge, in pixels
|
|
846
|
+
* @param height height of the keyboard, in pixels
|
|
847
|
+
*/
|
|
848
|
+
export declare function noteAt(x: number, y: number, height: number, layout: PianoLayout): number | null;
|
|
849
|
+
/**
|
|
850
|
+
* The white key width that makes the keyboard exactly `width` wide, for a
|
|
851
|
+
* keyboard that follows the size of its container.
|
|
852
|
+
*
|
|
853
|
+
* Solved from {@link pianoWidth} rather than by dividing among the white
|
|
854
|
+
* keys, so that a range that starts or ends on a black key — which sticks out
|
|
855
|
+
* by a fraction of a white key — still fills the container. The width grows
|
|
856
|
+
* linearly with the white key width, so two samples pin it down.
|
|
857
|
+
*/
|
|
858
|
+
export declare function fitWhiteKeyWidth(width: number, layout: Omit<PianoLayout, 'whiteKeyWidth'>): number;
|
|
859
|
+
//#endregion
|
|
860
|
+
//#region src/piano/shortcuts.d.ts
|
|
861
|
+
type KeyboardShortcuts = {
|
|
862
|
+
/**
|
|
863
|
+
* Keys laid out from `noteRange.first`, one entry per semitone.
|
|
864
|
+
*
|
|
865
|
+
* An empty string leaves that note without a shortcut: `KeyboardEvent.key` is
|
|
866
|
+
* never empty, so the entry can never match. Use it to skip the black keys
|
|
867
|
+
* (see {@link SHORTCUTS.HOME_ROW_NATURAL}) and keep the remaining entries
|
|
868
|
+
* lined up with the notes.
|
|
869
|
+
*/
|
|
870
|
+
keys: string[];
|
|
871
|
+
};
|
|
872
|
+
/**
|
|
873
|
+
* Ready-made keyboard layouts. Both assume `noteRange.first` is a C.
|
|
874
|
+
*/
|
|
875
|
+
export declare const SHORTCUTS: {
|
|
876
|
+
/** Every semitone from C, over the two rows of a QWERTY keyboard. */
|
|
877
|
+
HOME_ROW: {
|
|
878
|
+
keys: string[];
|
|
879
|
+
};
|
|
880
|
+
/** The white keys only, on the home row. Black keys have no shortcut. */
|
|
881
|
+
HOME_ROW_NATURAL: {
|
|
882
|
+
keys: string[];
|
|
883
|
+
};
|
|
884
|
+
};
|
|
885
|
+
/**
|
|
886
|
+
* Where keyboard shortcuts listen. `root` handles keys only while the piano
|
|
887
|
+
* or one of its descendants has focus; `window` handles them anywhere on the
|
|
888
|
+
* page except in editable elements.
|
|
889
|
+
*/
|
|
890
|
+
type KeyboardShortcutsScope = 'root' | 'window';
|
|
225
891
|
//#endregion
|
|
226
892
|
//#region src/piano/index.d.ts
|
|
227
893
|
/**
|
|
@@ -251,6 +917,24 @@ interface PianoInputOptions {
|
|
|
251
917
|
* @default 127
|
|
252
918
|
*/
|
|
253
919
|
midiMax?: number;
|
|
920
|
+
/**
|
|
921
|
+
* Play notes from the computer keyboard: `keys[i]` plays
|
|
922
|
+
* `layout.noteRange.first + i`. `SHORTCUTS` has ready-made layouts.
|
|
923
|
+
*
|
|
924
|
+
* A held key keeps its note until it is released, the focus leaves (with
|
|
925
|
+
* `root`), or the window loses focus. Changing the keys, the scope or the
|
|
926
|
+
* note range releases every note a key is holding, since the key would
|
|
927
|
+
* mean something else on release.
|
|
928
|
+
*/
|
|
929
|
+
keyboardShortcuts?: KeyboardShortcuts;
|
|
930
|
+
/**
|
|
931
|
+
* Where keyboard shortcuts listen: on the element (`root`), which has to
|
|
932
|
+
* be focusable, or anywhere on the page (`window`). Keys typed into an
|
|
933
|
+
* editable element are ignored either way.
|
|
934
|
+
*
|
|
935
|
+
* @default 'root'
|
|
936
|
+
*/
|
|
937
|
+
keyboardShortcutsScope?: KeyboardShortcutsScope;
|
|
254
938
|
/** Called when a note starts sounding, not for each source that asks. */
|
|
255
939
|
onPlayNote?: (note: number, velocity?: number) => void;
|
|
256
940
|
/** Called once the last source holding a note has let go. */
|
|
@@ -265,8 +949,8 @@ interface PianoInputInstance {
|
|
|
265
949
|
*/
|
|
266
950
|
update: (options: Partial<PianoInputOptions>) => void;
|
|
267
951
|
/**
|
|
268
|
-
* Start a note from something other than a pointer
|
|
269
|
-
*
|
|
952
|
+
* Start a note from something other than a pointer or a shortcut: a MIDI
|
|
953
|
+
* message, an imperative call.
|
|
270
954
|
*/
|
|
271
955
|
noteOn: (note: number, options?: {
|
|
272
956
|
source?: NoteSource;
|
|
@@ -290,7 +974,220 @@ interface PianoInputInstance {
|
|
|
290
974
|
*
|
|
291
975
|
* Tracks every pointer at once, so a chord can be played with several fingers.
|
|
292
976
|
*/
|
|
293
|
-
declare function createPianoInput(element: Element, options: PianoInputOptions): PianoInputInstance;
|
|
977
|
+
export declare function createPianoInput(element: Element, options: PianoInputOptions): PianoInputInstance;
|
|
978
|
+
//#endregion
|
|
979
|
+
//#region src/xy.d.ts
|
|
980
|
+
/**
|
|
981
|
+
* A pair of per-axis values. The tuple elements are labelled, so editors show
|
|
982
|
+
* `[x: number, y: number]` rather than a bare pair.
|
|
983
|
+
*/
|
|
984
|
+
type XY<T> = [x: T, y: T];
|
|
985
|
+
/**
|
|
986
|
+
* A setting that may be given once for both axes, or per axis.
|
|
987
|
+
*
|
|
988
|
+
* A single value is told from a pair with `Array.isArray`, so the single form
|
|
989
|
+
* is only offered while `T` cannot itself be an array. Where it can, the pair
|
|
990
|
+
* is the only way to write it, since a lone array would be read as a pair.
|
|
991
|
+
*/
|
|
992
|
+
type XYInput<T> = [T] extends [readonly unknown[]] ? readonly [x: T, y: T] : T | readonly [x: T, y: T];
|
|
993
|
+
/**
|
|
994
|
+
* Spread a setting that may have been given as a single value.
|
|
995
|
+
*
|
|
996
|
+
* The parameter is written out rather than taken as `XYInput<T>`: a
|
|
997
|
+
* conditional type cannot be narrowed, so the constraint stays where it is
|
|
998
|
+
* declared and this takes both forms.
|
|
999
|
+
*
|
|
1000
|
+
* The pair is copied rather than passed along, so that the result is a tuple
|
|
1001
|
+
* the caller owns even when a readonly one was given.
|
|
1002
|
+
*/
|
|
1003
|
+
export declare function toXY<T>(value: T | readonly [x: T, y: T]): XY<T>;
|
|
1004
|
+
//#endregion
|
|
1005
|
+
//#region src/selection/box.d.ts
|
|
1006
|
+
/**
|
|
1007
|
+
* A rectangle in the 0..1 space of whatever the box is drawn over, with `y`
|
|
1008
|
+
* growing downwards — the same space the items are given in.
|
|
1009
|
+
*/
|
|
1010
|
+
interface SelectionBoxRect {
|
|
1011
|
+
x: number;
|
|
1012
|
+
y: number;
|
|
1013
|
+
width: number;
|
|
1014
|
+
height: number;
|
|
1015
|
+
}
|
|
1016
|
+
interface SelectionBoxOptions<Id> {
|
|
1017
|
+
/**
|
|
1018
|
+
* Everything the box can pick up, read on every move rather than taken as a
|
|
1019
|
+
* snapshot: what is under the box changes while it is dragged, and an item
|
|
1020
|
+
* may have moved since the last one.
|
|
1021
|
+
*/
|
|
1022
|
+
items: () => Iterable<readonly [Id, XY<number>]>;
|
|
1023
|
+
/** The box as it is dragged, and `null` once it is gone. */
|
|
1024
|
+
onBoxChange?: (box: SelectionBoxRect | null) => void;
|
|
1025
|
+
/** What the box covers, added to whatever it started from. */
|
|
1026
|
+
onSelectionChange?: (ids: Id[]) => void;
|
|
1027
|
+
}
|
|
1028
|
+
interface SelectionBoxBeginOptions<Id> {
|
|
1029
|
+
/**
|
|
1030
|
+
* Add to `selection` rather than replacing it. Ctrl / meta rather than
|
|
1031
|
+
* shift, for the controls where shift is the fine-adjustment key.
|
|
1032
|
+
*/
|
|
1033
|
+
additive?: boolean;
|
|
1034
|
+
/** What was selected before the box started. Only read when `additive`. */
|
|
1035
|
+
selection?: readonly Id[];
|
|
1036
|
+
}
|
|
1037
|
+
interface SelectionBoxInstance<Id> {
|
|
1038
|
+
/** Replace the given options, without interrupting a box in progress. */
|
|
1039
|
+
update: (options: Partial<SelectionBoxOptions<Id>>) => void;
|
|
1040
|
+
/** Start a box at `at`, which is one of its corners. */
|
|
1041
|
+
begin: (at: XY<number>, options?: SelectionBoxBeginOptions<Id>) => void;
|
|
1042
|
+
/** Drag the opposite corner to `to`. */
|
|
1043
|
+
move: (to: XY<number>) => void;
|
|
1044
|
+
/**
|
|
1045
|
+
* Finish the box. The selection stays as it is.
|
|
1046
|
+
*
|
|
1047
|
+
* @returns whether a box was running, so that a caller can tell a drag from
|
|
1048
|
+
* a press that selected nothing.
|
|
1049
|
+
*/
|
|
1050
|
+
end: () => boolean;
|
|
1051
|
+
/** The box being dragged, or `null` when there is none. */
|
|
1052
|
+
box: () => SelectionBoxRect | null;
|
|
1053
|
+
destroy: () => void;
|
|
1054
|
+
}
|
|
1055
|
+
/** Whether the box covers the point, edges included. */
|
|
1056
|
+
export declare function selectionBoxCovers(box: SelectionBoxRect, [x, y]: XY<number>): boolean;
|
|
1057
|
+
/**
|
|
1058
|
+
* Selecting by dragging a box over a set of items.
|
|
1059
|
+
*
|
|
1060
|
+
* The drag itself is not here: the caller owns the pointer, and reports where
|
|
1061
|
+
* it went in the same 0..1 space the items are given in.
|
|
1062
|
+
*/
|
|
1063
|
+
export declare function createSelectionBox<Id>(options: SelectionBoxOptions<Id>): SelectionBoxInstance<Id>;
|
|
1064
|
+
//#endregion
|
|
1065
|
+
//#region src/points-editor/index.d.ts
|
|
1066
|
+
/** Where a point is: 0..1 on each axis, with y growing downwards. */
|
|
1067
|
+
interface PointPosition {
|
|
1068
|
+
x: number;
|
|
1069
|
+
y: number;
|
|
1070
|
+
}
|
|
1071
|
+
/**
|
|
1072
|
+
* A point's value is its position in the editor, so its range is the editor:
|
|
1073
|
+
* no scaling, and no rounding to a step.
|
|
1074
|
+
*/
|
|
1075
|
+
export declare const POINT_AXIS: {
|
|
1076
|
+
min: number;
|
|
1077
|
+
max: number;
|
|
1078
|
+
};
|
|
1079
|
+
/**
|
|
1080
|
+
* How much one wheel notch moves a point by default: a hundredth of the
|
|
1081
|
+
* editor, whatever its pixel size.
|
|
1082
|
+
*/
|
|
1083
|
+
export declare const POINTS_EDITOR_DEFAULT_WHEEL: ModifierValue<InputEventOption>;
|
|
1084
|
+
/**
|
|
1085
|
+
* How much one arrow key press moves a point by default. Shift is the
|
|
1086
|
+
* fine-adjustment key everywhere else, so it is bound here too — but only on
|
|
1087
|
+
* the keyboard. On the wheel it already means the x axis, and browsers hand
|
|
1088
|
+
* shift+wheel over as horizontal scrolling anyway.
|
|
1089
|
+
*/
|
|
1090
|
+
export declare const POINTS_EDITOR_DEFAULT_KEYBOARD: ModifierValue<InputEventOption>;
|
|
1091
|
+
/** Keep a point within its range. An axis left out runs from 0 to 1. */
|
|
1092
|
+
export declare function clampPoint(point: PointPosition, min?: Partial<PointPosition>, max?: Partial<PointPosition>): PointPosition;
|
|
1093
|
+
/**
|
|
1094
|
+
* What a point tells the editor about itself, so that a selection can be
|
|
1095
|
+
* moved without the editor knowing how the points are stored.
|
|
1096
|
+
*/
|
|
1097
|
+
interface PointsEditorPoint {
|
|
1098
|
+
value: PointPosition;
|
|
1099
|
+
min?: Partial<PointPosition>;
|
|
1100
|
+
max?: Partial<PointPosition>;
|
|
1101
|
+
/** A point that cannot move stays put while the rest of a selection moves. */
|
|
1102
|
+
readonly?: boolean;
|
|
1103
|
+
onChange?: (value: PointPosition) => void;
|
|
1104
|
+
/** The point's own element, to match the focus and a press against. */
|
|
1105
|
+
element?: Element | null;
|
|
1106
|
+
/** The wheel option the point resolved, `null` for no wheel. */
|
|
1107
|
+
wheel?: ModifierValue<InputEventOption> | null;
|
|
1108
|
+
}
|
|
1109
|
+
interface PointsEditorOptions {
|
|
1110
|
+
/**
|
|
1111
|
+
* Let points be selected, and a selection be moved as one. While it is off
|
|
1112
|
+
* nothing is selected, and a drag moves only the point it started on.
|
|
1113
|
+
*
|
|
1114
|
+
* @default false
|
|
1115
|
+
*/
|
|
1116
|
+
selectable?: boolean;
|
|
1117
|
+
/**
|
|
1118
|
+
* The ids of the selected points. Whoever holds the selection pushes it
|
|
1119
|
+
* back with `update()` after {@link PointsEditorOptions.onSelectionChange}.
|
|
1120
|
+
*/
|
|
1121
|
+
selection?: readonly string[];
|
|
1122
|
+
/** Called whenever a press or a selection box changes the selection. */
|
|
1123
|
+
onSelectionChange?: (selection: string[]) => void;
|
|
1124
|
+
/** Called whenever the selection box changes, with `null` once it is gone. */
|
|
1125
|
+
onSelectionBoxChange?: (rect: SelectionBoxRect | null) => void;
|
|
1126
|
+
}
|
|
1127
|
+
interface PointsEditorInstance {
|
|
1128
|
+
/** Replace the given options. */
|
|
1129
|
+
update: (options: Partial<PointsEditorOptions>) => void;
|
|
1130
|
+
/**
|
|
1131
|
+
* Register a point under `id`. `read` is called whenever the editor needs
|
|
1132
|
+
* the point, so it can return what the point is now rather than what it
|
|
1133
|
+
* was when it registered. Returns the function that unregisters it.
|
|
1134
|
+
*/
|
|
1135
|
+
registerPoint: (id: string, read: () => PointsEditorPoint) => () => void;
|
|
1136
|
+
/** Whether the element is a point, or inside one. */
|
|
1137
|
+
isPointElement: (element: Element | null | undefined) => boolean;
|
|
1138
|
+
/**
|
|
1139
|
+
* A pointer went down on a point: work out the new selection and remember
|
|
1140
|
+
* where everything the drag picked up started.
|
|
1141
|
+
*
|
|
1142
|
+
* Ctrl / meta add the point to the selection or take it out: shift is the
|
|
1143
|
+
* fine-adjustment key on every control here, and it cannot be both. A
|
|
1144
|
+
* press on a point already selected keeps the selection, so the group can
|
|
1145
|
+
* be dragged.
|
|
1146
|
+
*/
|
|
1147
|
+
beginPointDrag: (id: string, modifiers: ModifierState) => void;
|
|
1148
|
+
/**
|
|
1149
|
+
* Move everything the drag picked up by `delta` from where it started,
|
|
1150
|
+
* stopping the whole group together at the edge.
|
|
1151
|
+
*/
|
|
1152
|
+
movePointDrag: (delta: PointPosition) => void;
|
|
1153
|
+
/**
|
|
1154
|
+
* Move `id` — and the selection, when it is part of one — by `delta` from
|
|
1155
|
+
* where the points are now: an input that is not a drag has no earlier
|
|
1156
|
+
* position to measure against.
|
|
1157
|
+
*/
|
|
1158
|
+
nudgeSelection: (id: string, delta: PointPosition) => void;
|
|
1159
|
+
/**
|
|
1160
|
+
* Move `id` by one press of `option` along one axis, taking the selection
|
|
1161
|
+
* along as {@link PointsEditorInstance.nudgeSelection} does.
|
|
1162
|
+
*/
|
|
1163
|
+
nudgePoint: (id: string, axis: 'x' | 'y', direction: number, option: ModifierValue<InputEventOption>, modifiers?: ModifierState) => void;
|
|
1164
|
+
/**
|
|
1165
|
+
* Move the point holding the focus by one wheel notch, with its own wheel
|
|
1166
|
+
* option. The wheel is listened to once for the whole editor, since a wheel
|
|
1167
|
+
* event only reaches what the cursor is over. Returns whether a point took
|
|
1168
|
+
* it, so the caller knows whether to consume the event.
|
|
1169
|
+
*/
|
|
1170
|
+
nudgeFocusedPoint: (axis: 'x' | 'y', direction: number, modifiers: ModifierState) => boolean;
|
|
1171
|
+
/** A drag on empty space started at `at`: start a selection box there. */
|
|
1172
|
+
beginSelectionBox: (at: PointPosition, modifiers: ModifierState) => void;
|
|
1173
|
+
moveSelectionBox: (to: PointPosition) => void;
|
|
1174
|
+
/**
|
|
1175
|
+
* End the selection box. The press that started it left the focus on
|
|
1176
|
+
* nothing, and the arrow keys and the wheel reach a point only through the
|
|
1177
|
+
* focus, so it is handed to one of the points the box selected.
|
|
1178
|
+
*/
|
|
1179
|
+
endSelectionBox: () => void;
|
|
1180
|
+
destroy: () => void;
|
|
1181
|
+
}
|
|
1182
|
+
/**
|
|
1183
|
+
* The selection and the moves of a points editor: which points a press or a
|
|
1184
|
+
* box selects, and how a selection moves as one.
|
|
1185
|
+
*
|
|
1186
|
+
* The points stay with the wrapper, which registers each one; the editor only
|
|
1187
|
+
* reads them when it needs to, so a point's value can change on every frame
|
|
1188
|
+
* of a drag without anything being re-registered.
|
|
1189
|
+
*/
|
|
1190
|
+
export declare function createPointsEditor(options?: PointsEditorOptions): PointsEditorInstance;
|
|
294
1191
|
//#endregion
|
|
295
1192
|
//#region src/pointer/drag.d.ts
|
|
296
1193
|
type DragState = {
|
|
@@ -406,33 +1303,7 @@ interface DragInstance {
|
|
|
406
1303
|
*
|
|
407
1304
|
* One pointer at a time by default; see {@link DragOptions.multiPointer}.
|
|
408
1305
|
*/
|
|
409
|
-
declare function createDrag(element: Element, options?: DragOptions): DragInstance;
|
|
410
|
-
//#endregion
|
|
411
|
-
//#region src/xy.d.ts
|
|
412
|
-
/**
|
|
413
|
-
* A pair of per-axis values. The tuple elements are labelled, so editors show
|
|
414
|
-
* `[x: number, y: number]` rather than a bare pair.
|
|
415
|
-
*/
|
|
416
|
-
type XY<T> = [x: T, y: T];
|
|
417
|
-
/**
|
|
418
|
-
* A setting that may be given once for both axes, or per axis.
|
|
419
|
-
*
|
|
420
|
-
* A single value is told from a pair with `Array.isArray`, so the single form
|
|
421
|
-
* is only offered while `T` cannot itself be an array. Where it can, the pair
|
|
422
|
-
* is the only way to write it, since a lone array would be read as a pair.
|
|
423
|
-
*/
|
|
424
|
-
type XYInput<T> = [T] extends [readonly unknown[]] ? readonly [x: T, y: T] : T | readonly [x: T, y: T];
|
|
425
|
-
/**
|
|
426
|
-
* Spread a setting that may have been given as a single value.
|
|
427
|
-
*
|
|
428
|
-
* The parameter is written out rather than taken as `XYInput<T>`: a
|
|
429
|
-
* conditional type cannot be narrowed, so the constraint stays where it is
|
|
430
|
-
* declared and this takes both forms.
|
|
431
|
-
*
|
|
432
|
-
* The pair is copied rather than passed along, so that the result is a tuple
|
|
433
|
-
* the caller owns even when a readonly one was given.
|
|
434
|
-
*/
|
|
435
|
-
declare function toXY<T>(value: T | readonly [x: T, y: T]): XY<T>;
|
|
1306
|
+
export declare function createDrag(element: Element, options?: DragOptions): DragInstance;
|
|
436
1307
|
//#endregion
|
|
437
1308
|
//#region src/pointer/drag-value.d.ts
|
|
438
1309
|
/**
|
|
@@ -479,7 +1350,7 @@ interface DragValueMapping {
|
|
|
479
1350
|
* The element is read on every event, so it may be mounted after the drag is
|
|
480
1351
|
* set up and may change size while a drag is in progress.
|
|
481
1352
|
*/
|
|
482
|
-
declare function elementMapping(getElement: () => Element | null | undefined, { sensitivity }?: {
|
|
1353
|
+
export declare function elementMapping(getElement: () => Element | null | undefined, { sensitivity }?: {
|
|
483
1354
|
/**
|
|
484
1355
|
* How much the movement counts, read on every move. `1` is the pointer
|
|
485
1356
|
* position itself; `0.1` makes the same movement cover a tenth of the
|
|
@@ -499,7 +1370,7 @@ declare function elementMapping(getElement: () => Element | null | undefined, {
|
|
|
499
1370
|
* distance dragged. The pointer position itself carries no meaning, so the
|
|
500
1371
|
* value can be adjusted from anywhere on the screen.
|
|
501
1372
|
*/
|
|
502
|
-
declare function relativeMapping({ pixelRange, sensitivity }?: {
|
|
1373
|
+
export declare function relativeMapping({ pixelRange, sensitivity }?: {
|
|
503
1374
|
/**
|
|
504
1375
|
* Pixels of movement that span the whole range.
|
|
505
1376
|
* @default 100
|
|
@@ -571,7 +1442,51 @@ interface DragValueInstance {
|
|
|
571
1442
|
* mapping decides where the pointer sits on the 0-1 travel of each axis, and
|
|
572
1443
|
* the axis options turn that into a value.
|
|
573
1444
|
*/
|
|
574
|
-
declare function createDragValue(element: Element, options: DragValueOptions): DragValueInstance;
|
|
1445
|
+
export declare function createDragValue(element: Element, options: DragValueOptions): DragValueInstance;
|
|
1446
|
+
//#endregion
|
|
1447
|
+
//#region src/pointer/long-press.d.ts
|
|
1448
|
+
interface LongPressOptions {
|
|
1449
|
+
/** Called once on the press, then again every `interval` after `delay`. */
|
|
1450
|
+
onPress: () => void;
|
|
1451
|
+
/**
|
|
1452
|
+
* How long the press has to be held before it starts repeating, in
|
|
1453
|
+
* milliseconds.
|
|
1454
|
+
*
|
|
1455
|
+
* @default 500
|
|
1456
|
+
*/
|
|
1457
|
+
delay?: number;
|
|
1458
|
+
/**
|
|
1459
|
+
* How often it repeats once it has started, in milliseconds.
|
|
1460
|
+
*
|
|
1461
|
+
* @default 40
|
|
1462
|
+
*/
|
|
1463
|
+
interval?: number;
|
|
1464
|
+
}
|
|
1465
|
+
interface LongPressInstance {
|
|
1466
|
+
/**
|
|
1467
|
+
* Start a press, from a `pointerdown` or with no event at all. Only the
|
|
1468
|
+
* primary button starts one, and a press already in progress is left alone.
|
|
1469
|
+
*/
|
|
1470
|
+
start: (event?: Pick<PointerEvent, 'button' | 'pointerId'>) => void;
|
|
1471
|
+
/** End the press, as releasing the pointer would. */
|
|
1472
|
+
stop: () => void;
|
|
1473
|
+
/** Replace the given options. The press in progress picks them up. */
|
|
1474
|
+
update: (options: Partial<LongPressOptions>) => void;
|
|
1475
|
+
/** Whether a press is in progress. */
|
|
1476
|
+
pressed: () => boolean;
|
|
1477
|
+
destroy: () => void;
|
|
1478
|
+
}
|
|
1479
|
+
/**
|
|
1480
|
+
* Repeat an action while a pointer is held down: once on the press, then
|
|
1481
|
+
* again every `interval` after `delay` — the way a stepper button or a
|
|
1482
|
+
* key held on a keyboard behaves.
|
|
1483
|
+
*
|
|
1484
|
+
* The release is listened for on the window, not on the element: the
|
|
1485
|
+
* pointer may be let go anywhere. Only the pointer that started the press
|
|
1486
|
+
* ends it, so a second finger lifting elsewhere does not. The window losing
|
|
1487
|
+
* focus ends it too, since the release would never arrive.
|
|
1488
|
+
*/
|
|
1489
|
+
export declare function createLongPress(options: LongPressOptions): LongPressInstance;
|
|
575
1490
|
//#endregion
|
|
576
1491
|
//#region src/pointer/wheel.d.ts
|
|
577
1492
|
interface WheelOptions {
|
|
@@ -603,67 +1518,83 @@ interface WheelInstance {
|
|
|
603
1518
|
* The listener is registered with `passive: false` so that the handler can call
|
|
604
1519
|
* `preventDefault()` to stop the page from scrolling.
|
|
605
1520
|
*/
|
|
606
|
-
declare function createWheel(element: Element, onWheel: (event: WheelEvent) => void, options?: WheelOptions): WheelInstance;
|
|
1521
|
+
export declare function createWheel(element: Element, onWheel: (event: WheelEvent) => void, options?: WheelOptions): WheelInstance;
|
|
607
1522
|
//#endregion
|
|
608
|
-
//#region src/
|
|
1523
|
+
//#region src/position.d.ts
|
|
609
1524
|
/**
|
|
610
|
-
*
|
|
611
|
-
*
|
|
1525
|
+
* Where a value sits along a track, as a whole percentage from its start.
|
|
1526
|
+
*
|
|
1527
|
+
* Normalized along the scale, so a thumb, the fill behind it and the marks
|
|
1528
|
+
* all sit on the curve the drag follows. `reversed` measures from the other
|
|
1529
|
+
* end — for a track that grows upwards or leftwards on screen, since CSS
|
|
1530
|
+
* places things from the top and the left.
|
|
612
1531
|
*/
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
/**
|
|
633
|
-
* Add to `selection` rather than replacing it. Ctrl / meta rather than
|
|
634
|
-
* shift, for the controls where shift is the fine-adjustment key.
|
|
635
|
-
*/
|
|
636
|
-
additive?: boolean;
|
|
637
|
-
/** What was selected before the box started. Only read when `additive`. */
|
|
638
|
-
selection?: readonly Id[];
|
|
639
|
-
}
|
|
640
|
-
interface SelectionBoxInstance<Id> {
|
|
641
|
-
/** Replace the given options, without interrupting a box in progress. */
|
|
642
|
-
update: (options: Partial<SelectionBoxOptions<Id>>) => void;
|
|
643
|
-
/** Start a box at `at`, which is one of its corners. */
|
|
644
|
-
begin: (at: XY<number>, options?: SelectionBoxBeginOptions<Id>) => void;
|
|
645
|
-
/** Drag the opposite corner to `to`. */
|
|
646
|
-
move: (to: XY<number>) => void;
|
|
647
|
-
/**
|
|
648
|
-
* Finish the box. The selection stays as it is.
|
|
649
|
-
*
|
|
650
|
-
* @returns whether a box was running, so that a caller can tell a drag from
|
|
651
|
-
* a press that selected nothing.
|
|
652
|
-
*/
|
|
653
|
-
end: () => boolean;
|
|
654
|
-
/** The box being dragged, or `null` when there is none. */
|
|
655
|
-
box: () => SelectionBoxRect | null;
|
|
656
|
-
destroy: () => void;
|
|
1532
|
+
export declare function valuePercent(value: number, { min, max, scale }: Pick<ValueRange, 'min' | 'max' | 'scale'>, reversed?: boolean): number;
|
|
1533
|
+
//#endregion
|
|
1534
|
+
//#region src/slider/marks.d.ts
|
|
1535
|
+
/**
|
|
1536
|
+
* How `Slider.Marks` fills itself in when it is given no children: one option
|
|
1537
|
+
* every `per`, or every `step` of the slider. The object form turns off the
|
|
1538
|
+
* mark or the label for the whole set; a single option is customized by
|
|
1539
|
+
* writing `Slider.MarksOption` out instead.
|
|
1540
|
+
*/
|
|
1541
|
+
type MarksOptions = 'step' | number | {
|
|
1542
|
+
per: 'step' | number;
|
|
1543
|
+
mark?: boolean;
|
|
1544
|
+
label?: boolean;
|
|
1545
|
+
};
|
|
1546
|
+
/** One mark along a slider, as {@link sliderMarks} lays them out. */
|
|
1547
|
+
interface SliderMark {
|
|
1548
|
+
value: number;
|
|
1549
|
+
mark: boolean;
|
|
1550
|
+
label: boolean;
|
|
657
1551
|
}
|
|
658
|
-
/** Whether the box covers the point, edges included. */
|
|
659
|
-
declare function selectionBoxCovers(box: SelectionBoxRect, [x, y]: XY<number>): boolean;
|
|
660
1552
|
/**
|
|
661
|
-
*
|
|
1553
|
+
* The marks `options` asks for between `min` and `max`, in ascending order.
|
|
662
1554
|
*
|
|
663
|
-
*
|
|
664
|
-
*
|
|
1555
|
+
* Each value is a whole multiple of the interval, rounded to the digits the
|
|
1556
|
+
* interval has: stepping by 0.1 would otherwise put binary debris in the
|
|
1557
|
+
* labels (`0.1 * 3` is `0.30000000000000004`).
|
|
1558
|
+
*/
|
|
1559
|
+
export declare function sliderMarks(options: MarksOptions, min: number, max: number, step: number): SliderMark[];
|
|
1560
|
+
//#endregion
|
|
1561
|
+
//#region src/style.d.ts
|
|
1562
|
+
/**
|
|
1563
|
+
* A number as a CSS length, for a custom property.
|
|
1564
|
+
*
|
|
1565
|
+
* A custom property takes whatever text it is given, so `--size: 50` comes out
|
|
1566
|
+
* as the invalid `50` rather than `50px`. React appends `px` to a bare number
|
|
1567
|
+
* only for the properties it knows take a length, and a custom property is
|
|
1568
|
+
* never one of them; Vue and Svelte append nothing at all. Anything already a
|
|
1569
|
+
* string is passed through, so `'3rem'` and `'100%'` still work.
|
|
665
1570
|
*/
|
|
666
|
-
declare function
|
|
1571
|
+
export declare function cssLength(value: number | string | undefined): string | undefined;
|
|
1572
|
+
/**
|
|
1573
|
+
* Take an element out of sight while leaving it in the accessibility tree and
|
|
1574
|
+
* in the tab order.
|
|
1575
|
+
*
|
|
1576
|
+
* `display: none` and `visibility: hidden` would remove it from both, and the
|
|
1577
|
+
* native control underneath a headless component is what carries the ARIA and
|
|
1578
|
+
* the keyboard behaviour. `pointer-events: none` is safe because nothing is
|
|
1579
|
+
* ever clicked here directly: a `<label>` forwards its click, and a drag is
|
|
1580
|
+
* handled by the part that is visible.
|
|
1581
|
+
*
|
|
1582
|
+
* Every value is a string with its unit, so the object can be handed to any
|
|
1583
|
+
* framework's `style` binding as it is.
|
|
1584
|
+
*/
|
|
1585
|
+
export declare const visuallyHiddenStyle: {
|
|
1586
|
+
readonly position: "absolute";
|
|
1587
|
+
readonly width: "1px";
|
|
1588
|
+
readonly height: "1px";
|
|
1589
|
+
readonly padding: "0";
|
|
1590
|
+
readonly margin: "-1px";
|
|
1591
|
+
readonly overflow: "hidden";
|
|
1592
|
+
readonly clip: "rect(0, 0, 0, 0)";
|
|
1593
|
+
readonly clipPath: "inset(50%)";
|
|
1594
|
+
readonly whiteSpace: "nowrap";
|
|
1595
|
+
readonly border: "0";
|
|
1596
|
+
readonly pointerEvents: "none";
|
|
1597
|
+
};
|
|
667
1598
|
//#endregion
|
|
668
|
-
export {
|
|
1599
|
+
export type { AcceptCandidate, AnimationCanvasInstance, AnimationCanvasOptions, AnimationFrame, ArrowKey, AxisMove, AxisOptions, CanvasDrawFunction, CanvasInitFunction, CheckStepsOptions, DragInstance, DragOptions, DragState, DragValueInstance, DragValueMapping, DragValueOptions, DrawingContext, DrawingState, DrawingStateValue, DropZoneInstance, DropZoneOptions, DropZoneState, InputEventOption, KeyboardShortcuts, KeyboardShortcutsScope, KnobAngleOptions, KnobAngles, LongPressInstance, LongPressOptions, MIDIAccessError, MIDIAccessInstance, MIDIAccessOptions, MIDIAccessState, MIDIInputHandlers, MIDIInputInstance, MIDIMessageInstance, MappingContext, MarksOptions, Modifier, ModifierMap, ModifierState, ModifierValue, NoteRange, NoteSource, NumberInputRanges, NumberInputValueOptions, NumberSpan, PianoInputInstance, PianoInputOptions, PianoLayout, PointPosition, PointsEditorInstance, PointsEditorOptions, PointsEditorPoint, SelectionBoxBeginOptions, SelectionBoxInstance, SelectionBoxOptions, SelectionBoxRect, SliderMark, StepperDragInstance, StepperDragOptions, WheelDirectionOptions, WheelInstance, WheelOptions, XY, XYInput };
|
|
669
1600
|
//# sourceMappingURL=index.d.cts.map
|