@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.
Files changed (53) hide show
  1. package/dist/index.cjs +343 -595
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +230 -284
  4. package/dist/index.d.cts.map +1 -1
  5. package/dist/index.d.ts +230 -284
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +325 -572
  8. package/dist/index.js.map +1 -1
  9. package/dist/internal.cjs +530 -0
  10. package/dist/internal.cjs.map +1 -0
  11. package/dist/internal.d.cts +365 -0
  12. package/dist/internal.d.cts.map +1 -0
  13. package/dist/internal.d.ts +365 -0
  14. package/dist/internal.d.ts.map +1 -0
  15. package/dist/internal.js +500 -0
  16. package/dist/internal.js.map +1 -0
  17. package/dist/marks-DK7xJmGM.d.cts +305 -0
  18. package/dist/marks-DK7xJmGM.d.cts.map +1 -0
  19. package/dist/marks-DK7xJmGM.d.ts +305 -0
  20. package/dist/marks-DK7xJmGM.d.ts.map +1 -0
  21. package/dist/xy-5Oc6JeJr.cjs +952 -0
  22. package/dist/xy-5Oc6JeJr.cjs.map +1 -0
  23. package/dist/xy-lNFl1CTO.js +827 -0
  24. package/dist/xy-lNFl1CTO.js.map +1 -0
  25. package/package.json +12 -2
  26. package/src/canvas/animation.ts +8 -0
  27. package/src/canvas/context.ts +0 -5
  28. package/src/file/accept.ts +17 -0
  29. package/src/file/drop-zone.ts +8 -10
  30. package/src/index.ts +44 -32
  31. package/src/input/change-gesture.ts +104 -0
  32. package/src/input/check-steps.ts +144 -0
  33. package/src/input/defaults.ts +32 -0
  34. package/src/input/direction.ts +107 -0
  35. package/src/internal.ts +51 -0
  36. package/src/knob/geometry.ts +100 -0
  37. package/src/midi/access.ts +16 -15
  38. package/src/midi/input.ts +2 -9
  39. package/src/number-input/stepper-drag.ts +147 -0
  40. package/src/number-input/text.ts +100 -0
  41. package/src/number-input/value.ts +129 -0
  42. package/src/options/replace.ts +22 -0
  43. package/src/piano/index.ts +128 -2
  44. package/src/piano/layout.ts +19 -0
  45. package/src/piano/shortcuts.ts +86 -0
  46. package/src/pointer/drag-value.ts +3 -1
  47. package/src/pointer/long-press.ts +103 -0
  48. package/src/pointer/wheel.ts +10 -7
  49. package/src/points-editor/index.ts +367 -0
  50. package/src/position.ts +20 -0
  51. package/src/slider/decimal-digits.ts +23 -0
  52. package/src/slider/marks.ts +56 -0
  53. package/src/style.ts +41 -0
@@ -0,0 +1,365 @@
1
+ import { C as pianoWidth, D as ModifierState, O as ModifierValue, a as POINTS_EDITOR_DEFAULT_WHEEL, b as fitWhiteKeyWidth, d as clampPoint, g as toXY, i as POINTS_EDITOR_DEFAULT_KEYBOARD, k as selectModifier, n as SliderMark, o as POINT_AXIS, r as sliderMarks, w as InputEventOption, x as getNoteRangeArray, y as blackKeyWidth } from "./marks-DK7xJmGM.cjs";
2
+ import { Scale, ValueRange } from "@tremolo-ui/functions";
3
+ //#region src/file/accept.d.ts
4
+ /**
5
+ * What an `accept` rule is matched against.
6
+ *
7
+ * `File` satisfies it, and so does `DataTransferItem` — which matters while a
8
+ * drag is still in the air, since the browser reports the type of what is
9
+ * being dragged but withholds the name.
10
+ */
11
+ interface AcceptCandidate {
12
+ /** The file name, when it is known. */
13
+ name?: string;
14
+ /** The MIME type, or `''` when the browser has no type for it. */
15
+ type: string;
16
+ }
17
+ /**
18
+ * Split files into those that satisfy `accept` and those that do not, keeping
19
+ * their order. See {@link matchesAccept}.
20
+ */
21
+ export declare function partitionByAccept(files: Iterable<File>, accept?: string): {
22
+ accepted: File[];
23
+ rejected: File[];
24
+ };
25
+ //#endregion
26
+ //#region src/input/apply-delta.d.ts
27
+ /**
28
+ * Move a value by an amount of input, as reported by a wheel or an arrow key.
29
+ *
30
+ * The pipeline matches {@link createDragValue}: scale, then step, then clamp.
31
+ * Which key or which sign of `deltaY` counts as which direction is left to the
32
+ * caller, since it differs per component.
33
+ *
34
+ * @param direction which way, and how many times, to apply the option. The
35
+ * size of one step is `option[1]`, so this is normally `1` or `-1`.
36
+ *
37
+ * @param modifiers the event, for `options` that name a modifier key. See
38
+ * {@link selectModifier}.
39
+ *
40
+ * @example
41
+ * // ArrowDown on a slider whose keyboard option is ['raw', 1]
42
+ * applyDelta(value, -1, keyboard, { min, max, step, scale })
43
+ *
44
+ * @example
45
+ * // Shift+ArrowDown, where `keyboard` is { default: …, shift: ['raw', 0.1] }
46
+ * applyDelta(value, -1, keyboard, range, event)
47
+ */
48
+ export declare function applyDelta(value: number, direction: number, options: ModifierValue<InputEventOption>, { min, max, step, scale }: ValueRange, modifiers?: ModifierState): number;
49
+ //#endregion
50
+ //#region src/input/check-steps.d.ts
51
+ interface CheckStepsOptions {
52
+ /** The component, for the message. */
53
+ component: string;
54
+ /** The axis, for a component that has more than one. */
55
+ axis?: string;
56
+ /**
57
+ * The range to probe, or `null` to check nothing. An unbounded input has no
58
+ * travel to sample, so `NumberInput` passes `null` when `min` and `max` are
59
+ * not both there.
60
+ */
61
+ range: ValueRange | null;
62
+ keyboard?: ModifierValue<InputEventOption> | null;
63
+ wheel?: ModifierValue<InputEventOption> | null;
64
+ /**
65
+ * How the value is displayed, where the component shows one. Called with
66
+ * probe values only.
67
+ */
68
+ format?: (value: number) => string;
69
+ }
70
+ /**
71
+ * The warnings to show when a key press or a wheel notch cannot produce a
72
+ * change the user can see. Empty when there is nothing to say.
73
+ *
74
+ * Two settings that are each fine on their own can cancel out, and nothing
75
+ * fails when they do — the control simply sits there:
76
+ *
77
+ * - **`step` coarser than the amount.** `keyboard={['raw', 0.1]}` with
78
+ * `step={1}` rounds every press straight back to where it started
79
+ * - **the display coarser than the amount.** A `format` showing two decimals
80
+ * of a kHz value cannot show a press worth 1 Hz
81
+ *
82
+ * The second is only reported when the press is invisible at *every* point
83
+ * along the travel. A display that rounds is a deliberate choice and is
84
+ * normally right — it is being too coarse everywhere that makes it a mistake.
85
+ *
86
+ * **Meant for development builds only.** It probes the whole travel, so call
87
+ * it behind an inline `process.env.NODE_ENV` check: the bundler then drops
88
+ * the call, and this function and its messages with it.
89
+ */
90
+ export declare function checkSteps({ component, axis, range, keyboard, wheel, format }: CheckStepsOptions): string[];
91
+ //#endregion
92
+ //#region src/input/direction.d.ts
93
+ /** A move along one of the two axes of a position on screen. */
94
+ interface AxisMove {
95
+ /** 0 = x, 1 = y. */
96
+ axis: 0 | 1;
97
+ /** `1` towards the right or the bottom, `-1` towards the left or the top. */
98
+ direction: 1 | -1;
99
+ }
100
+ /**
101
+ * The direction an arrow key moves a single value: right and up raise it.
102
+ * `null` for any other key.
103
+ */
104
+ export declare function arrowKeyDirection(key: string): 1 | -1 | null;
105
+ /**
106
+ * The axis and direction an arrow key moves a position on screen. `null` for
107
+ * any other key.
108
+ *
109
+ * The key picks the axis, whichever element inside the control holds the
110
+ * focus: a two-dimensional control is one control to the person moving it.
111
+ */
112
+ export declare function arrowKeyMove(key: string): AxisMove | null;
113
+ interface WheelDirectionOptions {
114
+ /**
115
+ * Read horizontal scrolling as well, for a control laid out horizontally:
116
+ * scrolling right raises the value. Vertical scrolling still counts when
117
+ * there is no horizontal movement.
118
+ *
119
+ * @default false
120
+ */
121
+ horizontal?: boolean;
122
+ }
123
+ /**
124
+ * The direction one wheel event moves a single value: scrolling up raises it.
125
+ * `null` when the event carries no movement the control reads.
126
+ */
127
+ export declare function wheelDirection(event: Pick<WheelEvent, 'deltaX' | 'deltaY'>, { horizontal }?: WheelDirectionOptions): 1 | -1 | null;
128
+ /**
129
+ * The axis and direction one wheel event moves a position on screen. `null`
130
+ * when the event carries no movement.
131
+ *
132
+ * Scrolling moves y, and shift switches to x. Browsers turn shift+wheel into
133
+ * horizontal scrolling: `deltaY` comes out empty and `deltaX` carries the
134
+ * movement. Reading whichever axis moved keeps shift working as the x-axis
135
+ * modifier — and picks up a trackpad's own horizontal gesture, which never
136
+ * had a modifier.
137
+ */
138
+ export declare function wheelMove(event: Pick<WheelEvent, 'deltaX' | 'deltaY' | 'shiftKey'>): AxisMove | null;
139
+ //#endregion
140
+ //#region src/number-input/stepper-drag.d.ts
141
+ interface StepperDragOptions {
142
+ /** The value now, read when the drag starts moving it. */
143
+ getValue: () => number;
144
+ /**
145
+ * The range the value moves across. Its `step` is what one step of the drag
146
+ * is worth; see `numberInputRanges` for the one a number input uses.
147
+ */
148
+ range: ValueRange;
149
+ /**
150
+ * How many pixels of vertical movement make one step.
151
+ *
152
+ * @default 1
153
+ */
154
+ pixels?: number;
155
+ /**
156
+ * How much a step is worth, per modifier key: `0.1` makes the same movement
157
+ * count a tenth as much. Pressing or releasing the key mid-drag does not
158
+ * move the value.
159
+ *
160
+ * @default { default: 1, shift: 0.1 }
161
+ */
162
+ sensitivity?: ModifierValue<number>;
163
+ /** Hide the pointer and keep it from hitting the edge of the screen. */
164
+ pointerLock?: boolean;
165
+ /**
166
+ * The cursor to show while dragging. Applied to the element itself, as
167
+ * `createDrag` does.
168
+ *
169
+ * @default 'ns-resize'
170
+ */
171
+ cursor?: string;
172
+ /** Called with the new value whenever the drag moves it. */
173
+ onChange: (value: number) => void;
174
+ }
175
+ interface StepperDragInstance {
176
+ /** Replace the given options. `pointerLock` reaches the next drag. */
177
+ update: (options: Partial<StepperDragOptions>) => void;
178
+ /**
179
+ * Whether the drag in progress has moved the value. A stepper button's
180
+ * press-and-hold repeat stands down once it has, so the value is not moved
181
+ * twice.
182
+ */
183
+ moved: () => boolean;
184
+ destroy: () => void;
185
+ }
186
+ /**
187
+ * Drag up and down on the steppers of a number input to move its value, one
188
+ * `step` every `pixels` — up raises it, as on a knob.
189
+ *
190
+ * Counted from where the drag started moving rather than added up per
191
+ * event, so rounding cannot accumulate. The start is taken on the first
192
+ * move, not on pointerdown: a stepper button acts on pointerdown, so by then
193
+ * the value may already have been nudged once, and the drag carries on from
194
+ * there.
195
+ */
196
+ export declare function createStepperDrag(element: Element, options: StepperDragOptions): StepperDragInstance;
197
+ //#endregion
198
+ //#region src/number-input/value.d.ts
199
+ /**
200
+ * The value a number input edits, and how far it may go.
201
+ *
202
+ * Unlike a slider, either end may be left open, and `clampValue: false` lets
203
+ * the value past the ends that are set.
204
+ */
205
+ interface NumberInputValueOptions {
206
+ min?: number;
207
+ max?: number;
208
+ step?: number;
209
+ scale?: Scale;
210
+ /**
211
+ * Keep the value between `min` and `max`.
212
+ *
213
+ * @default true
214
+ */
215
+ clampValue?: boolean;
216
+ }
217
+ /** The ranges {@link nudgeNumberInput} moves a value across. */
218
+ interface NumberInputRanges {
219
+ /** For a `normalized` amount, which needs a finite span to take a share of. */
220
+ normalized: ValueRange;
221
+ /** For a `raw` amount, which does not. */
222
+ raw: ValueRange;
223
+ }
224
+ /**
225
+ * The ranges a number input moves its value across, with the open ends
226
+ * filled in.
227
+ *
228
+ * A normalized amount needs a finite span even when an end is unbounded or
229
+ * clamping is off. Safe integers provide one without overflowing the span a
230
+ * scale calculates. A raw amount needs no span, so its open ends can cover
231
+ * every finite number instead of stopping at the safe-integer range.
232
+ */
233
+ export declare function numberInputRanges({ min, max, step, scale, clampValue }: NumberInputValueOptions): NumberInputRanges;
234
+ /**
235
+ * Move a number input's value by one press of a key, a wheel notch or a
236
+ * stepper, picking the range that suits the kind of amount. See `applyDelta`.
237
+ */
238
+ export declare function nudgeNumberInput(value: number, direction: number, options: ModifierValue<InputEventOption>, ranges: NumberInputRanges, modifiers?: ModifierState): number;
239
+ /**
240
+ * Where the value stands against the ends: whether it can go no further
241
+ * down or up, and whether it lies outside them — which only an unclamped
242
+ * input, or a value set from outside, can do.
243
+ */
244
+ export declare function numberInputBounds(value: number, { min, max, clampValue }: NumberInputValueOptions): {
245
+ atMin: boolean;
246
+ atMax: boolean;
247
+ outOfRange: boolean;
248
+ };
249
+ /**
250
+ * The value typed text commits to, or `null` when there is no number in it.
251
+ *
252
+ * Text with no number is not a value: the input should go back to what it
253
+ * was showing rather than commit a zero the user never typed. What is read
254
+ * is clamped here and not while typing, since clamping as the user types
255
+ * would make "1500" impossible to enter into an input whose max is 100.
256
+ */
257
+ export declare function commitNumberInputText(text: string, parse: (text: string) => number, { min, max, clampValue }: NumberInputValueOptions): number | null;
258
+ //#endregion
259
+ //#region src/number-input/text.d.ts
260
+ /**
261
+ * Reading a number out of the text of a number input, and keeping the caret
262
+ * in place while the number under it changes.
263
+ *
264
+ * The text is whatever `format` made of the value — `"440 Hz"`, `"-6.0 dB"` —
265
+ * or a half-typed entry, so none of this assumes the text is a number alone.
266
+ */
267
+ /** Where the number is in the text; the rest, on either side, is the unit. */
268
+ interface NumberSpan {
269
+ start: number;
270
+ end: number;
271
+ }
272
+ /**
273
+ * Where the number is in the text: from its first digit to its last, with the
274
+ * sign and the decimal point in front of it. Whatever is left on either side
275
+ * is taken for the unit, so it does not matter whether a space separates them,
276
+ * or what the number looks like — `+6.0`, `1e+21`, `1,000` and `1:30` are each
277
+ * one number. `null` when the text has no digit at all.
278
+ */
279
+ export declare function numberSpan(text: string): NumberSpan | null;
280
+ /**
281
+ * The number in the text, with the unit after it ignored: the default `parse`
282
+ * of a number input.
283
+ *
284
+ * `NaN`, which leaves the value alone, whenever the number cannot be read
285
+ * safely, rather than a part of it: text with no number, a number that is not
286
+ * a plain one (`1,000` would otherwise read as 1, and `1:30` as 1), and text
287
+ * with something in front of the number, which can change what it means (the
288
+ * `L` of a pan reading `L 30`). A `format` that writes any of those needs its
289
+ * own `parse`.
290
+ */
291
+ export declare function parseNumberText(text: string): number;
292
+ /**
293
+ * Where the caret is, relative to the decimal point, so that it can be put
294
+ * back at the same digit once the value has changed. See
295
+ * {@link caretAtDecimalOffset}.
296
+ */
297
+ export declare function caretDecimalOffset(text: string, caret: number): number;
298
+ /**
299
+ * The caret position `offset` characters from the decimal point of the new
300
+ * text, kept within the number.
301
+ *
302
+ * @example
303
+ * // The caret sits in front of the point of "9.9" when ArrowUp turns it
304
+ * // into "10.0"
305
+ * const offset = caretDecimalOffset('9.9', 1) // 0
306
+ * caretAtDecimalOffset('10.0', offset) // 2: still in front of the point
307
+ */
308
+ export declare function caretAtDecimalOffset(text: string, offset: number): number;
309
+ //#endregion
310
+ //#region src/options/replace.d.ts
311
+ /**
312
+ * The `update()` argument that leaves an instance with exactly `next` as its
313
+ * options.
314
+ *
315
+ * `update()` merges into what the instance has, which suits a wrapper that
316
+ * pushes one setting at a time. A wrapper handed the whole new set instead —
317
+ * a Svelte action, a Vue composable — has to clear what the new set no longer
318
+ * carries, or a handler taken away, or an option left to its default, keeps
319
+ * working.
320
+ *
321
+ * @example
322
+ * instance.update(replaceOptions(previous, next))
323
+ */
324
+ export declare function replaceOptions<T extends object>(previous: T | undefined, next: T | undefined): Partial<T>;
325
+ //#endregion
326
+ //#region src/style.d.ts
327
+ /**
328
+ * A number as a CSS length, for a custom property.
329
+ *
330
+ * A custom property takes whatever text it is given, so `--size: 50` comes out
331
+ * as the invalid `50` rather than `50px`. React appends `px` to a bare number
332
+ * only for the properties it knows take a length, and a custom property is
333
+ * never one of them; Vue and Svelte append nothing at all. Anything already a
334
+ * string is passed through, so `'3rem'` and `'100%'` still work.
335
+ */
336
+ export declare function cssLength(value: number | string | undefined): string | undefined;
337
+ /**
338
+ * Take an element out of sight while leaving it in the accessibility tree and
339
+ * in the tab order.
340
+ *
341
+ * `display: none` and `visibility: hidden` would remove it from both, and the
342
+ * native control underneath a headless component is what carries the ARIA and
343
+ * the keyboard behaviour. `pointer-events: none` is safe because nothing is
344
+ * ever clicked here directly: a `<label>` forwards its click, and a drag is
345
+ * handled by the part that is visible.
346
+ *
347
+ * Every value is a string with its unit, so the object can be handed to any
348
+ * framework's `style` binding as it is.
349
+ */
350
+ export declare const visuallyHiddenStyle: {
351
+ readonly position: "absolute";
352
+ readonly width: "1px";
353
+ readonly height: "1px";
354
+ readonly padding: "0";
355
+ readonly margin: "-1px";
356
+ readonly overflow: "hidden";
357
+ readonly clip: "rect(0, 0, 0, 0)";
358
+ readonly clipPath: "inset(50%)";
359
+ readonly whiteSpace: "nowrap";
360
+ readonly border: "0";
361
+ readonly pointerEvents: "none";
362
+ };
363
+ //#endregion
364
+ export { type AcceptCandidate, type AxisMove, type CheckStepsOptions, type NumberInputRanges, type NumberInputValueOptions, type NumberSpan, POINTS_EDITOR_DEFAULT_KEYBOARD, POINTS_EDITOR_DEFAULT_WHEEL, POINT_AXIS, type SliderMark, type StepperDragInstance, type StepperDragOptions, type WheelDirectionOptions, blackKeyWidth, clampPoint, fitWhiteKeyWidth, getNoteRangeArray, pianoWidth, selectModifier, sliderMarks, toXY };
365
+ //# sourceMappingURL=internal.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.d.cts","names":[],"sources":["../src/file/accept.ts","../src/input/apply-delta.ts","../src/input/check-steps.ts","../src/input/direction.ts","../src/number-input/stepper-drag.ts","../src/number-input/value.ts","../src/number-input/text.ts","../src/options/replace.ts","../src/style.ts"],"mappings":";;;;;;;;;;UAOiB;;EAEf;;EAEA;;;;;;wBAoDc,kBACd,OAAO,SAAS,OAChB;EACG,UAAU;EAAQ,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;wBC9BjB,WACd,eACA,mBACA,SAAS,cAAc,qBACrB,KAAK,KAAK,MAAM,SAAuB,YACzC,YAAY;;;UC4BG;;EAEf;;EAEA;;;;;;EAMA,OAAO;EACP,WAAW,cAAc;EACzB,QAAQ,cAAc;;;;;EAKtB,UAAU;;;;;;;;;;;;;;;;;;;;;;wBAuBI,aACd,WACA,MACA,OACA,UACA,OACA,UACC;;;;UCrFc;;EAEf;;EAEA;;;;;;wBAOc,kBAAkB;;;;;;;;wBAYlB,aAAa,cAAc;UAQ1B;;;;;;;;EAQf;;;;;;wBAOc,eACd,OAAO,KAAK,oCACV,eAAsB;;;;;;;;;;;wBAiBV,UACd,OAAO,KAAK,gDACX;;;UCtFc;;EAEf;;;;;EAKA,OAAO;;;;;;EAMP;;;;;;;;EAQA,cAAc;;EAEd;;;;;;;EAOA;;EAEA,WAAW;;UAGI;;EAEf,SAAS,SAAS,QAAQ;;;;;;EAM1B;EACA;;;;;;;;;;;;wBAac,kBACd,SAAS,SACT,SAAS,qBACR;;;;;;;;;UCxDc;EACf;EACA;EACA;EACA,QAAQ;;;;;;EAMR;;;UAIe;;EAEf,YAAY;;EAEZ,KAAK;;;;;;;;;;;wBAYS,oBACd,KACA,KACA,MACA,OACA,cACC,0BAA0B;;;;;wBAuBb,iBACd,eACA,mBACA,SAAS,cAAc,mBACvB,QAAQ,mBACR,YAAY;;;;;;wBAiBE,kBACd,iBACE,KAAK,KAAK,cAAqB;;;;;;;;;;;;;wBAkBnB,sBACd,cACA,QAAQ,2BACN,KAAK,KAAK,cAAqB;;;;;;;;;;;UC5GlB;EACf;EACA;;;;;;;;;wBAUc,WAAW,eAAe;;;;;;;;;;;;wBAwB1B,gBAAgB;;;;;;wBAiChB,mBAAmB,cAAc;;;;;;;;;;;wBAcjC,qBAAqB,cAAc;;;;;;;;;;;;;;;;wBClFnC,eAAe,kBAC7B,UAAU,eACV,MAAM,gBACL,QAAQ;;;;;;;;;;;;wBCPK,UACd;;;;;;;;;;;;;;qBAkBW"}