@sudobility/music_drawing 0.0.36 → 0.0.38
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/cursor.d.ts +14 -2
- package/dist/cursor.d.ts.map +1 -1
- package/dist/cursor.js +9 -3
- package/dist/cursor.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/keyboard-geometry.d.ts +6 -18
- package/dist/keyboard-geometry.d.ts.map +1 -1
- package/dist/keyboard-geometry.js.map +1 -1
- package/dist/keyboard-keys.d.ts +2 -2
- package/dist/keyboard-keys.d.ts.map +1 -1
- package/dist/keyboard-keys.js.map +1 -1
- package/dist/pagination.d.ts +1 -7
- package/dist/pagination.d.ts.map +1 -1
- package/dist/pagination.js +0 -4
- package/dist/pagination.js.map +1 -1
- package/dist/playback-binding.d.ts +2 -0
- package/dist/playback-binding.d.ts.map +1 -1
- package/dist/playback-binding.js +13 -0
- package/dist/playback-binding.js.map +1 -1
- package/dist/playback-scroll.d.ts +33 -2
- package/dist/playback-scroll.d.ts.map +1 -1
- package/dist/playback-scroll.js +2 -23
- package/dist/playback-scroll.js.map +1 -1
- package/dist/playing-pitches.d.ts +44 -0
- package/dist/playing-pitches.d.ts.map +1 -0
- package/dist/playing-pitches.js +50 -0
- package/dist/playing-pitches.js.map +1 -0
- package/dist/print-plan.d.ts +2 -19
- package/dist/print-plan.d.ts.map +1 -1
- package/dist/print-plan.js +1 -33
- package/dist/print-plan.js.map +1 -1
- package/dist/score-canvas.d.ts +38 -23
- package/dist/score-canvas.d.ts.map +1 -1
- package/dist/score-canvas.js +52 -4
- package/dist/score-canvas.js.map +1 -1
- package/dist/types.d.ts +5 -13
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -17
- package/dist/types.js.map +1 -1
- package/package.json +3 -3
- package/dist/out-of-range.d.ts +0 -67
- package/dist/out-of-range.d.ts.map +0 -1
- package/dist/out-of-range.js +0 -101
- package/dist/out-of-range.js.map +0 -1
- package/dist/press.d.ts +0 -66
- package/dist/press.d.ts.map +0 -1
- package/dist/press.js +0 -64
- package/dist/press.js.map +0 -1
package/dist/out-of-range.d.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Notes an instrument cannot play, found in a score that already holds them.
|
|
3
|
-
*
|
|
4
|
-
* Here rather than in an app for the reason `note-colors.ts` beside it gives:
|
|
5
|
-
* two apps draw this score, and "which notes are lit, and why" having two
|
|
6
|
-
* answers is how the native app came to light nothing at all during playback.
|
|
7
|
-
*
|
|
8
|
-
* The compass lives in one place — `gm-catalogue.ts`, reached through
|
|
9
|
-
* `trackKeyboardRange` — and three of the four surfaces that care already read
|
|
10
|
-
* it: the keyboard shows exactly that span, generation now states it in the
|
|
11
|
-
* prompt, and `inspect.ts` judges a generated part against it. The notation is
|
|
12
|
-
* the exception, by design: it draws what the score holds, because a score is
|
|
13
|
-
* not only ever a generated one.
|
|
14
|
-
*
|
|
15
|
-
* That is the disagreement a reader actually meets. A timpani part written a
|
|
16
|
-
* fifth below its lowest drum draws perfectly well on the stave and cannot
|
|
17
|
-
* light a single key on the keyboard — measured on one project, 482 of 1,067
|
|
18
|
-
* notes. Nothing here rewrites those notes: they are marked, and moving them
|
|
19
|
-
* by an octave is a musical decision that belongs to the person reading, not
|
|
20
|
-
* to a scan.
|
|
21
|
-
*
|
|
22
|
-
* Gated on `trackRangeIsBinding`, the same condition the server applies, so the
|
|
23
|
-
* page and the server cannot disagree about what counts as out of range. A
|
|
24
|
-
* compass nobody verified marks nothing.
|
|
25
|
-
*
|
|
26
|
-
* ## Sounding pitch, and so the STORED score
|
|
27
|
-
*
|
|
28
|
-
* Every number in `gm-catalogue.ts` is sounding pitch, and `midiIsInRange` is
|
|
29
|
-
* documented as taking one. The score this package *draws* is not: the app
|
|
30
|
-
* hands `render` a `displayScore(score, pitchDisplay)`, which in written mode
|
|
31
|
-
* has moved a B-flat clarinet up a tone and, in every mode, has moved an
|
|
32
|
-
* `8va`'s noteheads down an octave. Scanning that would place a clarinet's
|
|
33
|
-
* whole part a tone above where it sounds and mark the top of it wrongly.
|
|
34
|
-
*
|
|
35
|
-
* So this takes the **stored** score — the one the app holds, before the
|
|
36
|
-
* lenses — and the result stays correct in either display mode because it is
|
|
37
|
-
* expressed as event **ids**, which both lenses preserve: `transposeEvents`
|
|
38
|
-
* and `ottavaScore` spread `...event` and replace only `pitch`. The renderer
|
|
39
|
-
* colours by id, so "which notes" survives a transposition that changes what
|
|
40
|
-
* those notes look like. `out-of-range.test.ts` pins that with a clarinet.
|
|
41
|
-
*/
|
|
42
|
-
import { type MidiRange, type Score } from '@sudobility/music_types';
|
|
43
|
-
export type OutOfRangeTrack = {
|
|
44
|
-
trackId: string;
|
|
45
|
-
name: string;
|
|
46
|
-
/** What the instrument can play. */
|
|
47
|
-
compass: MidiRange;
|
|
48
|
-
/** How many notes fall outside it. */
|
|
49
|
-
count: number;
|
|
50
|
-
/** The distinct pitches that do, lowest first. */
|
|
51
|
-
midis: number[];
|
|
52
|
-
};
|
|
53
|
-
export type OutOfRangeScan = {
|
|
54
|
-
/** Every offending note id, for the notation's colours. */
|
|
55
|
-
ids: string[];
|
|
56
|
-
/** One entry per track that has any, for the inspector's sentence. */
|
|
57
|
-
byTrack: OutOfRangeTrack[];
|
|
58
|
-
};
|
|
59
|
-
/**
|
|
60
|
-
* Every note `score` holds that its own instrument cannot play.
|
|
61
|
-
*
|
|
62
|
-
* `score` is the **stored** score — sounding pitch, before `displayScore`. Do
|
|
63
|
-
* not pass the score handed to `render`; see this module's doc for why, and
|
|
64
|
-
* why the ids come back usable in either display mode anyway.
|
|
65
|
-
*/
|
|
66
|
-
export declare function outOfRangeNoteIds(score: Score | null): OutOfRangeScan;
|
|
67
|
-
//# sourceMappingURL=out-of-range.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"out-of-range.d.ts","sourceRoot":"","sources":["../src/out-of-range.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,EAOL,KAAK,SAAS,EACd,KAAK,KAAK,EACX,MAAM,yBAAyB,CAAC;AAEjC,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,OAAO,EAAE,SAAS,CAAC;IACnB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,2DAA2D;IAC3D,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,sEAAsE;IACtE,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B,CAAC;AAIF;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,GAAG,cAAc,CAiDrE"}
|
package/dist/out-of-range.js
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Notes an instrument cannot play, found in a score that already holds them.
|
|
3
|
-
*
|
|
4
|
-
* Here rather than in an app for the reason `note-colors.ts` beside it gives:
|
|
5
|
-
* two apps draw this score, and "which notes are lit, and why" having two
|
|
6
|
-
* answers is how the native app came to light nothing at all during playback.
|
|
7
|
-
*
|
|
8
|
-
* The compass lives in one place — `gm-catalogue.ts`, reached through
|
|
9
|
-
* `trackKeyboardRange` — and three of the four surfaces that care already read
|
|
10
|
-
* it: the keyboard shows exactly that span, generation now states it in the
|
|
11
|
-
* prompt, and `inspect.ts` judges a generated part against it. The notation is
|
|
12
|
-
* the exception, by design: it draws what the score holds, because a score is
|
|
13
|
-
* not only ever a generated one.
|
|
14
|
-
*
|
|
15
|
-
* That is the disagreement a reader actually meets. A timpani part written a
|
|
16
|
-
* fifth below its lowest drum draws perfectly well on the stave and cannot
|
|
17
|
-
* light a single key on the keyboard — measured on one project, 482 of 1,067
|
|
18
|
-
* notes. Nothing here rewrites those notes: they are marked, and moving them
|
|
19
|
-
* by an octave is a musical decision that belongs to the person reading, not
|
|
20
|
-
* to a scan.
|
|
21
|
-
*
|
|
22
|
-
* Gated on `trackRangeIsBinding`, the same condition the server applies, so the
|
|
23
|
-
* page and the server cannot disagree about what counts as out of range. A
|
|
24
|
-
* compass nobody verified marks nothing.
|
|
25
|
-
*
|
|
26
|
-
* ## Sounding pitch, and so the STORED score
|
|
27
|
-
*
|
|
28
|
-
* Every number in `gm-catalogue.ts` is sounding pitch, and `midiIsInRange` is
|
|
29
|
-
* documented as taking one. The score this package *draws* is not: the app
|
|
30
|
-
* hands `render` a `displayScore(score, pitchDisplay)`, which in written mode
|
|
31
|
-
* has moved a B-flat clarinet up a tone and, in every mode, has moved an
|
|
32
|
-
* `8va`'s noteheads down an octave. Scanning that would place a clarinet's
|
|
33
|
-
* whole part a tone above where it sounds and mark the top of it wrongly.
|
|
34
|
-
*
|
|
35
|
-
* So this takes the **stored** score — the one the app holds, before the
|
|
36
|
-
* lenses — and the result stays correct in either display mode because it is
|
|
37
|
-
* expressed as event **ids**, which both lenses preserve: `transposeEvents`
|
|
38
|
-
* and `ottavaScore` spread `...event` and replace only `pitch`. The renderer
|
|
39
|
-
* colours by id, so "which notes" survives a transposition that changes what
|
|
40
|
-
* those notes look like. `out-of-range.test.ts` pins that with a clarinet.
|
|
41
|
-
*/
|
|
42
|
-
import { isNoteEvent, isPercussionTrack, midiIsInRange, pitchToMidi, trackKeyboardRange, trackRangeIsBinding, } from '@sudobility/music_types';
|
|
43
|
-
const EMPTY = { ids: [], byTrack: [] };
|
|
44
|
-
/**
|
|
45
|
-
* Every note `score` holds that its own instrument cannot play.
|
|
46
|
-
*
|
|
47
|
-
* `score` is the **stored** score — sounding pitch, before `displayScore`. Do
|
|
48
|
-
* not pass the score handed to `render`; see this module's doc for why, and
|
|
49
|
-
* why the ids come back usable in either display mode anyway.
|
|
50
|
-
*/
|
|
51
|
-
export function outOfRangeNoteIds(score) {
|
|
52
|
-
if (!score)
|
|
53
|
-
return EMPTY;
|
|
54
|
-
const ids = [];
|
|
55
|
-
const byTrack = [];
|
|
56
|
-
for (const track of score.tracks) {
|
|
57
|
-
/*
|
|
58
|
-
* A drum pitch names a drum rather than a place in a compass, so this test
|
|
59
|
-
* comes FIRST and is not folded into the gate below it.
|
|
60
|
-
*
|
|
61
|
-
* `trackRangeIsBinding` answers **true** for percussion on purpose — a kit
|
|
62
|
-
* has the pieces it has, which is the right answer for note entry and for
|
|
63
|
-
* generation, where refusing an address no drum sits at is a service. It is
|
|
64
|
-
* the wrong answer here: `percussion.ts` already handles a drum outside
|
|
65
|
-
* `GM_PERCUSSION_RANGE` by parking it on the middle line as `UNMAPPED`, and
|
|
66
|
-
* colouring it as well would be two marks for one fact.
|
|
67
|
-
*/
|
|
68
|
-
if (isPercussionTrack(track))
|
|
69
|
-
continue;
|
|
70
|
-
if (!trackRangeIsBinding(track))
|
|
71
|
-
continue;
|
|
72
|
-
const compass = trackKeyboardRange(track);
|
|
73
|
-
const midis = new Set();
|
|
74
|
-
let count = 0;
|
|
75
|
-
for (const measure of track.measures) {
|
|
76
|
-
for (const voice of measure.voices) {
|
|
77
|
-
for (const event of voice.events) {
|
|
78
|
-
if (!isNoteEvent(event))
|
|
79
|
-
continue;
|
|
80
|
-
const midi = pitchToMidi(event.pitch);
|
|
81
|
-
if (midiIsInRange(midi, compass))
|
|
82
|
-
continue;
|
|
83
|
-
ids.push(event.id);
|
|
84
|
-
midis.add(midi);
|
|
85
|
-
count += 1;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
if (count > 0) {
|
|
90
|
-
byTrack.push({
|
|
91
|
-
trackId: track.id,
|
|
92
|
-
name: track.name,
|
|
93
|
-
compass,
|
|
94
|
-
count,
|
|
95
|
-
midis: [...midis].sort((a, b) => a - b),
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
return ids.length > 0 ? { ids, byTrack } : EMPTY;
|
|
100
|
-
}
|
|
101
|
-
//# sourceMappingURL=out-of-range.js.map
|
package/dist/out-of-range.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"out-of-range.js","sourceRoot":"","sources":["../src/out-of-range.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,mBAAmB,GAGpB,MAAM,yBAAyB,CAAC;AAoBjC,MAAM,KAAK,GAAmB,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;AAEvD;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAmB;IACnD,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,OAAO,GAAsB,EAAE,CAAC;IAEtC,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjC;;;;;;;;;;WAUG;QACH,IAAI,iBAAiB,CAAC,KAAK,CAAC;YAAE,SAAS;QACvC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC;YAAE,SAAS;QAE1C,MAAM,OAAO,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;QAChC,IAAI,KAAK,GAAG,CAAC,CAAC;QAEd,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACrC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACnC,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;oBACjC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;wBAAE,SAAS;oBAClC,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;oBACtC,IAAI,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC;wBAAE,SAAS;oBAC3C,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;oBACnB,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;oBAChB,KAAK,IAAI,CAAC,CAAC;gBACb,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,OAAO,CAAC,IAAI,CAAC;gBACX,OAAO,EAAE,KAAK,CAAC,EAAE;gBACjB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,OAAO;gBACP,KAAK;gBACL,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;aACxC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;AACnD,CAAC"}
|
package/dist/press.d.ts
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* What a press on the score was: a tap, a long press, or a drag.
|
|
3
|
-
*
|
|
4
|
-
* Both apps answer this at the end of every press, and they answered it with
|
|
5
|
-
* different numbers in different files — the web's `DRAG_THRESHOLD` inside the
|
|
6
|
-
* notation view, the native app's `LONG_PRESS_MS`/`LONG_PRESS_SLOP` inside its
|
|
7
|
-
* scrolling score. The question is about the canvas (did the press stay on the
|
|
8
|
-
* thing under it?), so it lives beside the hit-testing that answers the next
|
|
9
|
-
* question.
|
|
10
|
-
*
|
|
11
|
-
* ## Mouse and touch differ, on purpose
|
|
12
|
-
*
|
|
13
|
-
* A mouse is still: a click that moved more than 3px was meant to move, which
|
|
14
|
-
* is exactly where the web's box select has always started. A finger is not —
|
|
15
|
-
* a deliberate tap on a phone routinely lands several points from where it
|
|
16
|
-
* touched down, and holding a finger to 3px would turn a good share of taps
|
|
17
|
-
* into drags. So a touch gets `TOUCH_TAP_SLOP`, the same allowance a long press
|
|
18
|
-
* already had: a press that stays put long enough to be a long press would
|
|
19
|
-
* otherwise have been a *drag* had it been released a moment sooner, which is
|
|
20
|
-
* not a distinction a thumb can make.
|
|
21
|
-
*
|
|
22
|
-
* A mouse never long-presses. It has a secondary button for the context menu,
|
|
23
|
-
* and a click held while the reader looks at something is not a request for
|
|
24
|
-
* one — reading it as one would change what an ordinary slow click does on the
|
|
25
|
-
* web. React Native on macOS passes `'touch'`, because its gesture model is the
|
|
26
|
-
* touch one: the long press is how it opens the menu.
|
|
27
|
-
*
|
|
28
|
-
* ## Distance
|
|
29
|
-
*
|
|
30
|
-
* Measured per axis (the larger of |dx| and |dy|), which is the web's existing
|
|
31
|
-
* rule to the pixel. The native app used the straight-line distance; per axis
|
|
32
|
-
* lets a diagonal wander up to √2 further, which is under five points at a
|
|
33
|
-
* 12pt slop and not something a hand can aim at.
|
|
34
|
-
*
|
|
35
|
-
* The caller latches: once a press has classified as a drag it stays one even
|
|
36
|
-
* if the pointer comes back, which is how the web's `drag.moved` behaves. This
|
|
37
|
-
* function answers for one moment and keeps no state.
|
|
38
|
-
*/
|
|
39
|
-
/** What produced the press. */
|
|
40
|
-
export type PointerKind = 'mouse' | 'touch';
|
|
41
|
-
export type PressKind = 'tap' | 'longPress' | 'drag';
|
|
42
|
-
/** How far a mouse press may move and still be a click, in px (web). */
|
|
43
|
-
export declare const TAP_SLOP = 3;
|
|
44
|
-
/** How far a finger may move and still be a tap, in pt. */
|
|
45
|
-
export declare const TOUCH_TAP_SLOP = 12;
|
|
46
|
-
/** How long a press is held to be a long press — iOS's and Android's own threshold. */
|
|
47
|
-
export declare const LONG_PRESS_MS = 500;
|
|
48
|
-
/** How far a long press may wander — about a thumb's width. */
|
|
49
|
-
export declare const LONG_PRESS_SLOP = 12;
|
|
50
|
-
/** The tap slop for a pointer kind. */
|
|
51
|
-
export declare function tapSlopFor(pointer: PointerKind): number;
|
|
52
|
-
export type PressMeasure = {
|
|
53
|
-
/** Movement since the press began, either sign. */
|
|
54
|
-
dx: number;
|
|
55
|
-
dy: number;
|
|
56
|
-
/** How long the press has been (or was) held. */
|
|
57
|
-
heldMs: number;
|
|
58
|
-
/** Defaults to `'mouse'`, the web's rule. */
|
|
59
|
-
pointer?: PointerKind;
|
|
60
|
-
};
|
|
61
|
-
/**
|
|
62
|
-
* `'longPress'` if a touch was held `LONG_PRESS_MS` within `LONG_PRESS_SLOP`;
|
|
63
|
-
* otherwise `'tap'` if it moved no more than the tap slop; otherwise `'drag'`.
|
|
64
|
-
*/
|
|
65
|
-
export declare function classifyPress({ dx, dy, heldMs, pointer, }: PressMeasure): PressKind;
|
|
66
|
-
//# sourceMappingURL=press.d.ts.map
|
package/dist/press.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"press.d.ts","sourceRoot":"","sources":["../src/press.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,+BAA+B;AAC/B,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,OAAO,CAAC;AAE5C,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,WAAW,GAAG,MAAM,CAAC;AAErD,wEAAwE;AACxE,eAAO,MAAM,QAAQ,IAAI,CAAC;AAE1B,2DAA2D;AAC3D,eAAO,MAAM,cAAc,KAAK,CAAC;AAEjC,uFAAuF;AACvF,eAAO,MAAM,aAAa,MAAM,CAAC;AAEjC,+DAA+D;AAC/D,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC,uCAAuC;AACvC,wBAAgB,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAEvD;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,mDAAmD;IACnD,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAC5B,EAAE,EACF,EAAE,EACF,MAAM,EACN,OAAiB,GAClB,EAAE,YAAY,GAAG,SAAS,CAU1B"}
|
package/dist/press.js
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* What a press on the score was: a tap, a long press, or a drag.
|
|
3
|
-
*
|
|
4
|
-
* Both apps answer this at the end of every press, and they answered it with
|
|
5
|
-
* different numbers in different files — the web's `DRAG_THRESHOLD` inside the
|
|
6
|
-
* notation view, the native app's `LONG_PRESS_MS`/`LONG_PRESS_SLOP` inside its
|
|
7
|
-
* scrolling score. The question is about the canvas (did the press stay on the
|
|
8
|
-
* thing under it?), so it lives beside the hit-testing that answers the next
|
|
9
|
-
* question.
|
|
10
|
-
*
|
|
11
|
-
* ## Mouse and touch differ, on purpose
|
|
12
|
-
*
|
|
13
|
-
* A mouse is still: a click that moved more than 3px was meant to move, which
|
|
14
|
-
* is exactly where the web's box select has always started. A finger is not —
|
|
15
|
-
* a deliberate tap on a phone routinely lands several points from where it
|
|
16
|
-
* touched down, and holding a finger to 3px would turn a good share of taps
|
|
17
|
-
* into drags. So a touch gets `TOUCH_TAP_SLOP`, the same allowance a long press
|
|
18
|
-
* already had: a press that stays put long enough to be a long press would
|
|
19
|
-
* otherwise have been a *drag* had it been released a moment sooner, which is
|
|
20
|
-
* not a distinction a thumb can make.
|
|
21
|
-
*
|
|
22
|
-
* A mouse never long-presses. It has a secondary button for the context menu,
|
|
23
|
-
* and a click held while the reader looks at something is not a request for
|
|
24
|
-
* one — reading it as one would change what an ordinary slow click does on the
|
|
25
|
-
* web. React Native on macOS passes `'touch'`, because its gesture model is the
|
|
26
|
-
* touch one: the long press is how it opens the menu.
|
|
27
|
-
*
|
|
28
|
-
* ## Distance
|
|
29
|
-
*
|
|
30
|
-
* Measured per axis (the larger of |dx| and |dy|), which is the web's existing
|
|
31
|
-
* rule to the pixel. The native app used the straight-line distance; per axis
|
|
32
|
-
* lets a diagonal wander up to √2 further, which is under five points at a
|
|
33
|
-
* 12pt slop and not something a hand can aim at.
|
|
34
|
-
*
|
|
35
|
-
* The caller latches: once a press has classified as a drag it stays one even
|
|
36
|
-
* if the pointer comes back, which is how the web's `drag.moved` behaves. This
|
|
37
|
-
* function answers for one moment and keeps no state.
|
|
38
|
-
*/
|
|
39
|
-
/** How far a mouse press may move and still be a click, in px (web). */
|
|
40
|
-
export const TAP_SLOP = 3;
|
|
41
|
-
/** How far a finger may move and still be a tap, in pt. */
|
|
42
|
-
export const TOUCH_TAP_SLOP = 12;
|
|
43
|
-
/** How long a press is held to be a long press — iOS's and Android's own threshold. */
|
|
44
|
-
export const LONG_PRESS_MS = 500;
|
|
45
|
-
/** How far a long press may wander — about a thumb's width. */
|
|
46
|
-
export const LONG_PRESS_SLOP = 12;
|
|
47
|
-
/** The tap slop for a pointer kind. */
|
|
48
|
-
export function tapSlopFor(pointer) {
|
|
49
|
-
return pointer === 'touch' ? TOUCH_TAP_SLOP : TAP_SLOP;
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* `'longPress'` if a touch was held `LONG_PRESS_MS` within `LONG_PRESS_SLOP`;
|
|
53
|
-
* otherwise `'tap'` if it moved no more than the tap slop; otherwise `'drag'`.
|
|
54
|
-
*/
|
|
55
|
-
export function classifyPress({ dx, dy, heldMs, pointer = 'mouse', }) {
|
|
56
|
-
const moved = Math.max(Math.abs(dx), Math.abs(dy));
|
|
57
|
-
if (pointer === 'touch' &&
|
|
58
|
-
heldMs >= LONG_PRESS_MS &&
|
|
59
|
-
moved <= LONG_PRESS_SLOP) {
|
|
60
|
-
return 'longPress';
|
|
61
|
-
}
|
|
62
|
-
return moved <= tapSlopFor(pointer) ? 'tap' : 'drag';
|
|
63
|
-
}
|
|
64
|
-
//# sourceMappingURL=press.js.map
|
package/dist/press.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"press.js","sourceRoot":"","sources":["../src/press.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAOH,wEAAwE;AACxE,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC;AAE1B,2DAA2D;AAC3D,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AAEjC,uFAAuF;AACvF,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC;AAEjC,+DAA+D;AAC/D,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAElC,uCAAuC;AACvC,MAAM,UAAU,UAAU,CAAC,OAAoB;IAC7C,OAAO,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC;AACzD,CAAC;AAYD;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,EAC5B,EAAE,EACF,EAAE,EACF,MAAM,EACN,OAAO,GAAG,OAAO,GACJ;IACb,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACnD,IACE,OAAO,KAAK,OAAO;QACnB,MAAM,IAAI,aAAa;QACvB,KAAK,IAAI,eAAe,EACxB,CAAC;QACD,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,OAAO,KAAK,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;AACvD,CAAC"}
|