@astryxdesign/core 0.7.7-canary.36f8ea1 → 0.7.7-canary.550ff21

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 (67) hide show
  1. package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
  2. package/dist/CommandPalette/CommandPaletteInput.js +8 -1
  3. package/dist/DateInput/MonthScroller.d.ts.map +1 -1
  4. package/dist/DateInput/MonthScroller.js +72 -2
  5. package/dist/Field/PanelSearchInput.d.ts.map +1 -1
  6. package/dist/Field/PanelSearchInput.js +8 -1
  7. package/dist/Field/textEntryTraits.d.ts +6 -6
  8. package/dist/Field/textEntryTraits.js +6 -6
  9. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  10. package/dist/ProgressBar/ProgressBar.js +20 -9
  11. package/dist/ProgressBar/ProgressBarTouch.d.ts +29 -0
  12. package/dist/ProgressBar/ProgressBarTouch.d.ts.map +1 -0
  13. package/dist/ProgressBar/ProgressBarTouch.js +91 -0
  14. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  15. package/dist/Typeahead/BaseTypeahead.js +9 -1
  16. package/dist/astryx.css +7 -0
  17. package/dist/gestures/GestureArena.d.ts +21 -2
  18. package/dist/gestures/GestureArena.d.ts.map +1 -1
  19. package/dist/gestures/GestureArena.js +19 -2
  20. package/dist/gestures/GestureHost.d.ts +51 -1
  21. package/dist/gestures/GestureHost.d.ts.map +1 -1
  22. package/dist/gestures/GestureHost.js +148 -7
  23. package/dist/motion/animator.d.ts.map +1 -1
  24. package/dist/motion/animator.js +63 -5
  25. package/dist/motion/paging.d.ts +58 -0
  26. package/dist/motion/paging.d.ts.map +1 -0
  27. package/dist/motion/paging.js +128 -0
  28. package/dist/motion/uikit/index.d.ts +4 -3
  29. package/dist/motion/uikit/index.d.ts.map +1 -1
  30. package/dist/motion/uikit/index.js +4 -3
  31. package/dist/motion/uikit/paging.d.ts +160 -0
  32. package/dist/motion/uikit/paging.d.ts.map +1 -0
  33. package/dist/motion/uikit/paging.js +162 -0
  34. package/dist/motion/uikit/progressBar.d.ts +59 -0
  35. package/dist/motion/uikit/progressBar.d.ts.map +1 -0
  36. package/dist/motion/uikit/progressBar.js +82 -0
  37. package/dist/motion/uikit/scroll.d.ts +0 -19
  38. package/dist/motion/uikit/scroll.d.ts.map +1 -1
  39. package/dist/motion/uikit/scroll.js +2 -21
  40. package/dist/utils/selectionLock.d.ts +43 -0
  41. package/dist/utils/selectionLock.d.ts.map +1 -1
  42. package/dist/utils/selectionLock.js +394 -6
  43. package/package.json +4 -4
  44. package/src/CommandPalette/CommandPaletteInput.tsx +6 -0
  45. package/src/DateInput/MonthScroller.tsx +63 -5
  46. package/src/Field/PanelSearchInput.tsx +6 -0
  47. package/src/Field/textEntryTraits.ts +6 -6
  48. package/src/ProgressBar/ProgressBar.doc.mjs +3 -3
  49. package/src/ProgressBar/ProgressBar.tsx +82 -11
  50. package/src/ProgressBar/ProgressBarTouch.ts +109 -0
  51. package/src/Typeahead/BaseTypeahead.tsx +7 -0
  52. package/src/gestures/GestureArena.ts +44 -4
  53. package/src/gestures/GestureHost.ts +184 -7
  54. package/src/gestures/README.md +19 -3
  55. package/src/motion/MEASUREMENTS.md +8 -1
  56. package/src/motion/README.md +6 -3
  57. package/src/motion/animator.ts +78 -6
  58. package/src/motion/paging.ts +138 -0
  59. package/src/motion/uikit/index.ts +4 -3
  60. package/src/motion/uikit/paging.ts +162 -0
  61. package/src/motion/uikit/progressBar.ts +82 -0
  62. package/src/motion/uikit/scroll.ts +2 -18
  63. package/src/utils/selectionLock.ts +501 -6
  64. package/dist/motion/selectPage.d.ts +0 -26
  65. package/dist/motion/selectPage.d.ts.map +0 -1
  66. package/dist/motion/selectPage.js +0 -55
  67. package/src/motion/selectPage.ts +0 -55
@@ -0,0 +1,128 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file paging.ts
5
+ * @input A release velocity, a settle's start, end and velocity, and the UIKit
6
+ * paging constants
7
+ * @output Exports `pagingSettleVelocity`, `solvePaging` (UIKit's paging settle
8
+ * as a curve the animator plays) and `solveAnimatedPageScroll`
9
+ * @position Pure math, with no DOM and no React
10
+ *
11
+ * SYNC: When modified, update:
12
+ * - /packages/core/src/motion/paging.test.ts
13
+ * - /packages/core/src/motion/README.md
14
+ */
15
+
16
+ import { paging } from "./uikit/paging.js";
17
+
18
+ /**
19
+ * The velocity a paging settle starts at. It is the release velocity that every
20
+ * gesture reads, zeroed below `velocityFloor`. The page choice reads the
21
+ * release velocity itself.
22
+ */
23
+ export function pagingSettleVelocity(velocity) {
24
+ return Math.abs(velocity) < paging.release.velocityFloor ? 0 : velocity;
25
+ }
26
+
27
+ /** A paging settle: the curve and where it ends. */
28
+
29
+ /**
30
+ * UIKit's paging settle from `from` (px), moving at `velocity` (px/s), onto
31
+ * `to`. It steps `paging.integrator` `stepsPerSecond` times a second and ends
32
+ * exactly on `to`. The same motion returns an overscrolled pager to its first
33
+ * or last page.
34
+ *
35
+ * Positions are content offsets along the paging axis, 0 at page 0 and growing
36
+ * toward later pages. Velocities are px/s of that offset.
37
+ *
38
+ * No closed form reproduces the per-frame stepping, so the settle integrates
39
+ * once into a table, and the curve reads the table. A release needs at most
40
+ * about 400 steps, well under a millisecond of work.
41
+ *
42
+ * The release velocity enters in px per millisecond per step, as UIKit hands it
43
+ * to the integrator. At 960 steps a second, the content starts at 96 % of the
44
+ * finger's speed, as in UIKit.
45
+ */
46
+ export function solvePaging({
47
+ from,
48
+ velocity,
49
+ to
50
+ }) {
51
+ const {
52
+ springPull,
53
+ friction,
54
+ stepsPerSecond,
55
+ restDistance,
56
+ restSpeed
57
+ } = paging.integrator;
58
+ const xs = [from];
59
+ const vs = [velocity / 1000];
60
+ let x = from;
61
+ let v = velocity / 1000;
62
+ // ~10 s of steps: far beyond any settle (≈ 0.35 s from rest).
63
+ const maxSteps = stepsPerSecond * 10;
64
+ let steps = 0;
65
+ while (steps < maxSteps) {
66
+ if (Math.abs(to - x) < restDistance && Math.abs(v) < restSpeed) {
67
+ break;
68
+ }
69
+ v = (v + (to - x) * springPull) * friction;
70
+ x += v;
71
+ steps += 1;
72
+ xs.push(x);
73
+ vs.push(v);
74
+ }
75
+ xs[xs.length - 1] = to;
76
+ vs[vs.length - 1] = 0;
77
+ const duration = steps / stepsPerSecond;
78
+ const last = xs.length - 1;
79
+ const read = (table, t) => {
80
+ if (!(t > 0)) {
81
+ return table[0];
82
+ }
83
+ const s = t * stepsPerSecond;
84
+ if (s >= last) {
85
+ return table[last];
86
+ }
87
+ const i = Math.floor(s);
88
+ const f = s - i;
89
+ return table[i] + (table[i + 1] - table[i]) * f;
90
+ };
91
+ return {
92
+ from,
93
+ to,
94
+ steps,
95
+ duration,
96
+ at: t => read(xs, t),
97
+ // px per step × steps per second
98
+ velocity: t => read(vs, t) * stepsPerSecond
99
+ };
100
+ }
101
+
102
+ /**
103
+ * `setContentOffset(_:animated:)`: `paging.animatedScroll.duration` on a
104
+ * sinusoidal ease-in-out, whatever the distance. UIKit starts it from the
105
+ * current offset and drops any velocity, as here.
106
+ */
107
+ export function solveAnimatedPageScroll({
108
+ from,
109
+ to
110
+ }) {
111
+ const {
112
+ duration
113
+ } = paging.animatedScroll;
114
+ const distance = to - from;
115
+ return {
116
+ duration,
117
+ at: t => {
118
+ const u = Math.min(1, Math.max(0, t / duration));
119
+ return from + distance * (1 - Math.cos(Math.PI * u)) / 2;
120
+ },
121
+ velocity: t => {
122
+ if (t <= 0 || t >= duration) {
123
+ return 0;
124
+ }
125
+ return distance * Math.PI / (2 * duration) * Math.sin(Math.PI * t / duration);
126
+ }
127
+ };
128
+ }
@@ -2,9 +2,9 @@
2
2
  * @file index.ts
3
3
  * @input The domain files of the UIKit constants table
4
4
  * @output Re-exports `springs` and one constant per spring (`SHEET_PRESENT_SPRING`,
5
- * …), `scroll`, `timing`, `navigation`, the `slider` domain and the
6
- * gesture thresholds (one `UIKIT_*` group per recognizer, their union
7
- * `UIKIT_GESTURES`, and the haptic tables)
5
+ * …), `scroll`, `timing`, `navigation`, `progressBar`, the `slider` domain
6
+ * and the gesture thresholds (one `UIKIT_*` group per recognizer, their
7
+ * union `UIKIT_GESTURES`, and the haptic tables)
8
8
  * @position Entry of the UIKit constants table (motion/uikit). Internal to
9
9
  * core: not exported from the package entry point
10
10
  *
@@ -18,6 +18,7 @@
18
18
  */
19
19
  export { HAPTIC_FEEDBACK_KINDS, HAPTIC_VIBRATION_PATTERNS, UIKIT_CLICK, UIKIT_CONTROL, UIKIT_GESTURES, UIKIT_LONG_PRESS, UIKIT_PAN, UIKIT_PINCH, UIKIT_PRESS, UIKIT_ROTATION, UIKIT_SCREEN_EDGE_PAN, UIKIT_SWIPE, UIKIT_TAP, UIKIT_VELOCITY, type GestureConstant, type GestureConstantUnit, type HapticFeedbackKind, } from './gestures.js';
20
20
  export { navigation, registerNavigationTable } from './navigation.js';
21
+ export { progressBar, registerProgressBarTable } from './progressBar.js';
21
22
  export { registerScrollTable, scroll } from './scroll.js';
22
23
  export { slider } from './slider.js';
23
24
  export { ACTION_SHEET_DISMISS_SPRING, ACTION_SHEET_PRESENT_SPRING, ALERT_DISMISS_SPRING, ALERT_PRESENT_SPRING, BANNER_SPRING, CONTEXT_MENU_DISMISS_SPRING, CONTEXT_MENU_LIFT_SPRING, CONTEXT_MENU_MORPH_SPRING, DIRECT_CHANGE_SPRING, EMPHASIS_SPRING, FINGER_TRACKING_SPRING, KEYBOARD_SPRING, MENU_CLOSE_SPRING, MENU_OPEN_SPRING, MENU_REDUCED_MOTION_SPRING, NAVIGATION_BAR_ELEMENTS_SPRING, NAVIGATION_INTERACTIVE_POP_FINISH_SPRING, NAVIGATION_POP_SPRING, NAVIGATION_PUSH_SPRING, QUICK_CHANGE_SPRING, SEGMENTED_THUMB_SPRING, SETTLE_SPRING, SHEET_DETENT_SPRING, SHEET_DISMISS_SPRING, SHEET_DISMISS_SWIPE_SPRING, SHEET_PRESENT_SPRING, SHEET_RELEASE_FAST_SPRING, STATE_CHANGE_SPRING, SUB_MENU_BACK_SPRING, SUB_MENU_OPEN_SPRING, SWITCH_THUMB_MOVE_SPRING, SWITCH_THUMB_STRETCH_SPRING, TIMED_CHANGE_SPRING, VIEW_CHANGE_SPRING, registerSpringsTable, springs, } from './springs.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/motion/uikit/index.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,WAAW,EACX,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,WAAW,EACX,WAAW,EACX,cAAc,EACd,qBAAqB,EACrB,WAAW,EACX,SAAS,EACT,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,GACxB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAC,UAAU,EAAE,uBAAuB,EAAC,MAAM,cAAc,CAAC;AACjE,OAAO,EAAC,mBAAmB,EAAE,MAAM,EAAC,MAAM,UAAU,CAAC;AACrD,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAC;AAChC,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,EAC3B,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,2BAA2B,EAC3B,wBAAwB,EACxB,yBAAyB,EACzB,oBAAoB,EACpB,eAAe,EACf,sBAAsB,EACtB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,0BAA0B,EAC1B,8BAA8B,EAC9B,wCAAwC,EACxC,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,0BAA0B,EAC1B,oBAAoB,EACpB,yBAAyB,EACzB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,2BAA2B,EAC3B,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,OAAO,GACR,MAAM,WAAW,CAAC;AACnB,OAAO,EAAC,mBAAmB,EAAE,MAAM,EAAC,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/motion/uikit/index.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,WAAW,EACX,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,WAAW,EACX,WAAW,EACX,cAAc,EACd,qBAAqB,EACrB,WAAW,EACX,SAAS,EACT,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,GACxB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAC,UAAU,EAAE,uBAAuB,EAAC,MAAM,cAAc,CAAC;AACjE,OAAO,EAAC,WAAW,EAAE,wBAAwB,EAAC,MAAM,eAAe,CAAC;AACpE,OAAO,EAAC,mBAAmB,EAAE,MAAM,EAAC,MAAM,UAAU,CAAC;AACrD,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAC;AAChC,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,EAC3B,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,2BAA2B,EAC3B,wBAAwB,EACxB,yBAAyB,EACzB,oBAAoB,EACpB,eAAe,EACf,sBAAsB,EACtB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,0BAA0B,EAC1B,8BAA8B,EAC9B,wCAAwC,EACxC,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,0BAA0B,EAC1B,oBAAoB,EACpB,yBAAyB,EACzB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,2BAA2B,EAC3B,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,OAAO,GACR,MAAM,WAAW,CAAC;AACnB,OAAO,EAAC,mBAAmB,EAAE,MAAM,EAAC,MAAM,UAAU,CAAC"}
@@ -4,9 +4,9 @@
4
4
  * @file index.ts
5
5
  * @input The domain files of the UIKit constants table
6
6
  * @output Re-exports `springs` and one constant per spring (`SHEET_PRESENT_SPRING`,
7
- * …), `scroll`, `timing`, `navigation`, the `slider` domain and the
8
- * gesture thresholds (one `UIKIT_*` group per recognizer, their union
9
- * `UIKIT_GESTURES`, and the haptic tables)
7
+ * …), `scroll`, `timing`, `navigation`, `progressBar`, the `slider` domain
8
+ * and the gesture thresholds (one `UIKIT_*` group per recognizer, their
9
+ * union `UIKIT_GESTURES`, and the haptic tables)
10
10
  * @position Entry of the UIKit constants table (motion/uikit). Internal to
11
11
  * core: not exported from the package entry point
12
12
  *
@@ -21,6 +21,7 @@
21
21
 
22
22
  export { HAPTIC_FEEDBACK_KINDS, HAPTIC_VIBRATION_PATTERNS, UIKIT_CLICK, UIKIT_CONTROL, UIKIT_GESTURES, UIKIT_LONG_PRESS, UIKIT_PAN, UIKIT_PINCH, UIKIT_PRESS, UIKIT_ROTATION, UIKIT_SCREEN_EDGE_PAN, UIKIT_SWIPE, UIKIT_TAP, UIKIT_VELOCITY } from "./gestures.js";
23
23
  export { navigation, registerNavigationTable } from "./navigation.js";
24
+ export { progressBar, registerProgressBarTable } from "./progressBar.js";
24
25
  export { registerScrollTable, scroll } from "./scroll.js";
25
26
  export { slider } from "./slider.js";
26
27
  export { ACTION_SHEET_DISMISS_SPRING, ACTION_SHEET_PRESENT_SPRING, ALERT_DISMISS_SPRING, ALERT_PRESENT_SPRING, BANNER_SPRING, CONTEXT_MENU_DISMISS_SPRING, CONTEXT_MENU_LIFT_SPRING, CONTEXT_MENU_MORPH_SPRING, DIRECT_CHANGE_SPRING, EMPHASIS_SPRING, FINGER_TRACKING_SPRING, KEYBOARD_SPRING, MENU_CLOSE_SPRING, MENU_OPEN_SPRING, MENU_REDUCED_MOTION_SPRING, NAVIGATION_BAR_ELEMENTS_SPRING, NAVIGATION_INTERACTIVE_POP_FINISH_SPRING, NAVIGATION_POP_SPRING, NAVIGATION_PUSH_SPRING, QUICK_CHANGE_SPRING, SEGMENTED_THUMB_SPRING, SETTLE_SPRING, SHEET_DETENT_SPRING, SHEET_DISMISS_SPRING, SHEET_DISMISS_SWIPE_SPRING, SHEET_PRESENT_SPRING, SHEET_RELEASE_FAST_SPRING, STATE_CHANGE_SPRING, SUB_MENU_BACK_SPRING, SUB_MENU_OPEN_SPRING, SWITCH_THUMB_MOVE_SPRING, SWITCH_THUMB_STRETCH_SPRING, TIMED_CHANGE_SPRING, VIEW_CHANGE_SPRING, registerSpringsTable, springs } from "./springs.js";
@@ -0,0 +1,160 @@
1
+ /**
2
+ * @file paging.ts
3
+ * @input Nothing; data only
4
+ * @output Exports `paging`, the measured constants of a paging UIScrollView
5
+ * @position The paging domain of the UIKit constants table (motion/uikit). Only
6
+ * core reads it, so the `uikit` namespace does not re-export it
7
+ *
8
+ * SYNC: When modified, update:
9
+ * - /packages/core/src/motion/MEASUREMENTS.md (measurement tasks)
10
+ * - /packages/core/src/motion/paging.ts and paging.test.ts
11
+ */
12
+ export declare const paging: {
13
+ /**
14
+ * After the lift, one model moves the content: the settle onto the chosen
15
+ * page and the return from an overscroll. Each display frame runs floor(frame
16
+ * interval in ms) steps of 1 ms:
17
+ *
18
+ * v = (v + (target − x) · springPull) · friction; x += v (v: pt per step)
19
+ *
20
+ * A 60 Hz frame runs 16 steps, not 16.67. With these values, the model
21
+ * replays eight captured releases to 0.20 pt RMS. It replays five overscroll
22
+ * returns to 0.16–0.33 pt RMS (402 pt pages, iOS 26.2, 3× screen). Without
23
+ * the floor, the error is 1.0 pt RMS, with a systematic shape.
24
+ */
25
+ readonly integrator: {
26
+ /**
27
+ * Velocity added per 1 ms step, per point of distance to the target page
28
+ * (pt per step²).
29
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026.
30
+ * `_pagingSpringPull` reads the same on a 402 pt paging UIScrollView and
31
+ * on UIPageViewController's scroll view. It replays 8 captured settles to
32
+ * 0.20 pt RMS.
33
+ */
34
+ readonly springPull: 0.000284858;
35
+ /**
36
+ * Velocity kept per step after the pull (`_pagingFriction`, equal to
37
+ * `_defaultPagingFriction`).
38
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026. Both read
39
+ * the same on the two scroll views of `springPull`, and they replay with
40
+ * it.
41
+ */
42
+ readonly friction: 0.970815;
43
+ /**
44
+ * Integration steps per second: floor(16.67 ms) = 16 steps per 60 Hz frame,
45
+ * and floor(8.33 ms) = 8 per 120 Hz frame, so 960.
46
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026. In a 60 fps
47
+ * log of 8 releases at rest, floored stepping fits to 0.20 pt RMS.
48
+ * Unfloored stepping fits to 1.0 pt RMS.
49
+ */
50
+ readonly stepsPerSecond: 960;
51
+ /**
52
+ * A settle ends exactly on the page once the remaining distance is below
53
+ * this many points and the step velocity is below `restSpeed`.
54
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026. The
55
+ * captured settles jump the last 0.33 pt onto the page about 0.35 s after
56
+ * a release at rest.
57
+ */
58
+ readonly restDistance: 0.5;
59
+ /**
60
+ * Step velocity (pt per step) below which a settle may end.
61
+ * @source GUESS — the captured settles end at about 0.04 pt per step;
62
+ * the threshold is not observable more finely at 60 fps
63
+ * @measure M-PG12
64
+ */
65
+ readonly restSpeed: 0.05;
66
+ };
67
+ readonly release: {
68
+ /**
69
+ * Released slower than `advanceSpeed`, the scroll view settles on the page
70
+ * nearest the content position: past half a page, the next one.
71
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026. In releases
72
+ * at rest from page 1, content at 48.5 % of the page stays, and 57.5 %
73
+ * goes to the next page. On a second 402 pt pager, 45 % stays and 55 %
74
+ * advances.
75
+ */
76
+ readonly commitFraction: 0.5;
77
+ /**
78
+ * Released at least this fast (pt/s), the scroll view pages in the
79
+ * direction of the velocity, from any content position. A flick from 6 % of
80
+ * the page advances. The speed is UIPanGestureRecognizer's velocity at the
81
+ * last movement, and it never decays. The scroll view's
82
+ * `_horizontalVelocity` equals it at every sample. A drag held still for
83
+ * 397 ms before the lift still pages at the speed it had.
84
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026. Steady
85
+ * releases at 10, 25 and 40 % of a 402 pt page: 292.7, 295.3 and 298.6
86
+ * pt/s stay; 310.7, 316.4 and 329.9 advance. The result is the same at
87
+ * every position: a threshold, not a projection.
88
+ */
89
+ readonly advanceSpeed: 300;
90
+ /**
91
+ * A settle velocity slower than this (pt/s) is zeroed, so the settle starts
92
+ * at rest. It is paging's own tuning on the one release velocity that every
93
+ * gesture reads.
94
+ * @source GUESS — the middle of the measured (200, 249] bracket. In the
95
+ * UIKit lab (iOS 26.2 simulator, Oct 23 2026),
96
+ * `scrollViewWillEndDragging` reads 0 for steady releases at 175 and 200
97
+ * pt/s. It reads 0.249 pt/ms for a release at 249 pt/s.
98
+ * @measure M-PG13
99
+ */
100
+ readonly velocityFloor: 225;
101
+ /**
102
+ * Pages a release may travel from the page the drag started on, at any
103
+ * speed and drag distance.
104
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026. A drag of
105
+ * 1.5 pages from page 1 lands on page 2 at release speeds of 0, 600 and
106
+ * 3000 pt/s.
107
+ */
108
+ readonly maxPagesFromStart: 1;
109
+ };
110
+ /**
111
+ * A finger that lands on a settling pager does not stop it at once. The
112
+ * settle runs on for about this long, then the content holds under the
113
+ * finger. Lifted without a move, the content settles again on the nearest
114
+ * page.
115
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026. After
116
+ * touch-downs 60 and 160 ms into a settle, the content moved on for 82.6
117
+ * and 87.5 ms (5 frames), then held.
118
+ */
119
+ readonly catchStopMs: 85;
120
+ /**
121
+ * A horizontal pager's pan begins only for a drag within atan(1 ÷ this) of
122
+ * horizontal (26.6° for 2). A steeper drag goes to the vertical scroll around
123
+ * it. Between 26.6° and 45°, neither moves.
124
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026. A scroll
125
+ * view's directional lock holds the major axis up to 25° and frees it from
126
+ * 30°. An inline calendar pager in a sheet pages at 20° from horizontal. At
127
+ * 35° and 45°, it moves neither itself nor the sheet, and it leaves 55° to
128
+ * the sheet.
129
+ */
130
+ readonly panAxisRatio: 2;
131
+ readonly animatedScroll: {
132
+ /**
133
+ * `setContentOffset(_:animated:)` duration. It is the same for one page and
134
+ * for five, as for a page control's tap.
135
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026.
136
+ * `_contentOffsetAnimationDuration` reads 0.3, and five animated moves of
137
+ * 1 to 5 pages each last 0.30 s.
138
+ */
139
+ readonly duration: 0.3;
140
+ /**
141
+ * Its curve is a sinusoidal ease-in-out: x = from + (to − from) · (1 − cos
142
+ * πu) ÷ 2, for u = t ÷ duration.
143
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026. The five
144
+ * moves fit the sinusoid to 0.14–0.51 pt RMS, and a 2010 pt move fits to
145
+ * 0.20 pt. The curve easeInEaseOut (0.42, 0, 0.58, 1) misses by 7.7 pt.
146
+ */
147
+ readonly curve: "sineInOut";
148
+ };
149
+ /**
150
+ * Past the first or last page, the content follows the finger through the
151
+ * scroll view's rubber band (scroll.rubberBand.coefficient), with d = the
152
+ * page width. It returns on the integrator above.
153
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026. A pan of 90
154
+ * pt past page 0 shows 42.7–45 pt, and 290 pt shows 114.3 pt. The formula
155
+ * gives 44.1 and 114.2, with c 0.55 and d 402. The return replays on the
156
+ * integrator to 0.16–0.33 pt RMS.
157
+ */
158
+ readonly rubberBandDimension: "pageWidth";
159
+ };
160
+ //# sourceMappingURL=paging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paging.d.ts","sourceRoot":"","sources":["../../../src/motion/uikit/paging.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,MAAM;IACjB;;;;;;;;;;;OAWG;;QAED;;;;;;;WAOG;;QAEH;;;;;;WAMG;;QAEH;;;;;;WAMG;;QAEH;;;;;;WAMG;;QAEH;;;;;WAKG;;;;QAIH;;;;;;;WAOG;;QAEH;;;;;;;;;;;WAWG;;QAEH;;;;;;;;;WASG;;QAEH;;;;;;WAMG;;;IAGL;;;;;;;;OAQG;;IAEH;;;;;;;;;OASG;;;QAGD;;;;;;WAMG;;QAEH;;;;;;WAMG;;;IAGL;;;;;;;;OAQG;;CAEK,CAAC"}
@@ -0,0 +1,162 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file paging.ts
5
+ * @input Nothing; data only
6
+ * @output Exports `paging`, the measured constants of a paging UIScrollView
7
+ * @position The paging domain of the UIKit constants table (motion/uikit). Only
8
+ * core reads it, so the `uikit` namespace does not re-export it
9
+ *
10
+ * SYNC: When modified, update:
11
+ * - /packages/core/src/motion/MEASUREMENTS.md (measurement tasks)
12
+ * - /packages/core/src/motion/paging.ts and paging.test.ts
13
+ */
14
+
15
+ export const paging = {
16
+ /**
17
+ * After the lift, one model moves the content: the settle onto the chosen
18
+ * page and the return from an overscroll. Each display frame runs floor(frame
19
+ * interval in ms) steps of 1 ms:
20
+ *
21
+ * v = (v + (target − x) · springPull) · friction; x += v (v: pt per step)
22
+ *
23
+ * A 60 Hz frame runs 16 steps, not 16.67. With these values, the model
24
+ * replays eight captured releases to 0.20 pt RMS. It replays five overscroll
25
+ * returns to 0.16–0.33 pt RMS (402 pt pages, iOS 26.2, 3× screen). Without
26
+ * the floor, the error is 1.0 pt RMS, with a systematic shape.
27
+ */
28
+ integrator: {
29
+ /**
30
+ * Velocity added per 1 ms step, per point of distance to the target page
31
+ * (pt per step²).
32
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026.
33
+ * `_pagingSpringPull` reads the same on a 402 pt paging UIScrollView and
34
+ * on UIPageViewController's scroll view. It replays 8 captured settles to
35
+ * 0.20 pt RMS.
36
+ */
37
+ springPull: 0.000284858,
38
+ /**
39
+ * Velocity kept per step after the pull (`_pagingFriction`, equal to
40
+ * `_defaultPagingFriction`).
41
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026. Both read
42
+ * the same on the two scroll views of `springPull`, and they replay with
43
+ * it.
44
+ */
45
+ friction: 0.970815,
46
+ /**
47
+ * Integration steps per second: floor(16.67 ms) = 16 steps per 60 Hz frame,
48
+ * and floor(8.33 ms) = 8 per 120 Hz frame, so 960.
49
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026. In a 60 fps
50
+ * log of 8 releases at rest, floored stepping fits to 0.20 pt RMS.
51
+ * Unfloored stepping fits to 1.0 pt RMS.
52
+ */
53
+ stepsPerSecond: 960,
54
+ /**
55
+ * A settle ends exactly on the page once the remaining distance is below
56
+ * this many points and the step velocity is below `restSpeed`.
57
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026. The
58
+ * captured settles jump the last 0.33 pt onto the page about 0.35 s after
59
+ * a release at rest.
60
+ */
61
+ restDistance: 0.5,
62
+ /**
63
+ * Step velocity (pt per step) below which a settle may end.
64
+ * @source GUESS — the captured settles end at about 0.04 pt per step;
65
+ * the threshold is not observable more finely at 60 fps
66
+ * @measure M-PG12
67
+ */
68
+ restSpeed: 0.05
69
+ },
70
+ release: {
71
+ /**
72
+ * Released slower than `advanceSpeed`, the scroll view settles on the page
73
+ * nearest the content position: past half a page, the next one.
74
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026. In releases
75
+ * at rest from page 1, content at 48.5 % of the page stays, and 57.5 %
76
+ * goes to the next page. On a second 402 pt pager, 45 % stays and 55 %
77
+ * advances.
78
+ */
79
+ commitFraction: 0.5,
80
+ /**
81
+ * Released at least this fast (pt/s), the scroll view pages in the
82
+ * direction of the velocity, from any content position. A flick from 6 % of
83
+ * the page advances. The speed is UIPanGestureRecognizer's velocity at the
84
+ * last movement, and it never decays. The scroll view's
85
+ * `_horizontalVelocity` equals it at every sample. A drag held still for
86
+ * 397 ms before the lift still pages at the speed it had.
87
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026. Steady
88
+ * releases at 10, 25 and 40 % of a 402 pt page: 292.7, 295.3 and 298.6
89
+ * pt/s stay; 310.7, 316.4 and 329.9 advance. The result is the same at
90
+ * every position: a threshold, not a projection.
91
+ */
92
+ advanceSpeed: 300,
93
+ /**
94
+ * A settle velocity slower than this (pt/s) is zeroed, so the settle starts
95
+ * at rest. It is paging's own tuning on the one release velocity that every
96
+ * gesture reads.
97
+ * @source GUESS — the middle of the measured (200, 249] bracket. In the
98
+ * UIKit lab (iOS 26.2 simulator, Oct 23 2026),
99
+ * `scrollViewWillEndDragging` reads 0 for steady releases at 175 and 200
100
+ * pt/s. It reads 0.249 pt/ms for a release at 249 pt/s.
101
+ * @measure M-PG13
102
+ */
103
+ velocityFloor: 225,
104
+ /**
105
+ * Pages a release may travel from the page the drag started on, at any
106
+ * speed and drag distance.
107
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026. A drag of
108
+ * 1.5 pages from page 1 lands on page 2 at release speeds of 0, 600 and
109
+ * 3000 pt/s.
110
+ */
111
+ maxPagesFromStart: 1
112
+ },
113
+ /**
114
+ * A finger that lands on a settling pager does not stop it at once. The
115
+ * settle runs on for about this long, then the content holds under the
116
+ * finger. Lifted without a move, the content settles again on the nearest
117
+ * page.
118
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026. After
119
+ * touch-downs 60 and 160 ms into a settle, the content moved on for 82.6
120
+ * and 87.5 ms (5 frames), then held.
121
+ */
122
+ catchStopMs: 85,
123
+ /**
124
+ * A horizontal pager's pan begins only for a drag within atan(1 ÷ this) of
125
+ * horizontal (26.6° for 2). A steeper drag goes to the vertical scroll around
126
+ * it. Between 26.6° and 45°, neither moves.
127
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026. A scroll
128
+ * view's directional lock holds the major axis up to 25° and frees it from
129
+ * 30°. An inline calendar pager in a sheet pages at 20° from horizontal. At
130
+ * 35° and 45°, it moves neither itself nor the sheet, and it leaves 55° to
131
+ * the sheet.
132
+ */
133
+ panAxisRatio: 2,
134
+ animatedScroll: {
135
+ /**
136
+ * `setContentOffset(_:animated:)` duration. It is the same for one page and
137
+ * for five, as for a page control's tap.
138
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026.
139
+ * `_contentOffsetAnimationDuration` reads 0.3, and five animated moves of
140
+ * 1 to 5 pages each last 0.30 s.
141
+ */
142
+ duration: 0.3,
143
+ /**
144
+ * Its curve is a sinusoidal ease-in-out: x = from + (to − from) · (1 − cos
145
+ * πu) ÷ 2, for u = t ÷ duration.
146
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026. The five
147
+ * moves fit the sinusoid to 0.14–0.51 pt RMS, and a 2010 pt move fits to
148
+ * 0.20 pt. The curve easeInEaseOut (0.42, 0, 0.58, 1) misses by 7.7 pt.
149
+ */
150
+ curve: 'sineInOut'
151
+ },
152
+ /**
153
+ * Past the first or last page, the content follows the finger through the
154
+ * scroll view's rubber band (scroll.rubberBand.coefficient), with d = the
155
+ * page width. It returns on the integrator above.
156
+ * @source measured: UIKit lab, iOS 26.2 simulator, Oct 23 2026. A pan of 90
157
+ * pt past page 0 shows 42.7–45 pt, and 290 pt shows 114.3 pt. The formula
158
+ * gives 44.1 and 114.2, with c 0.55 and d 402. The return replays on the
159
+ * integrator to 0.16–0.33 pt RMS.
160
+ */
161
+ rubberBandDimension: 'pageWidth'
162
+ };
@@ -0,0 +1,59 @@
1
+ /**
2
+ * UIProgressView's values, for ProgressBar. Two values are motion roles in the
3
+ * generated motion role table: the whole-track duration,
4
+ * `progress.fillTrackMs`, and its curve, `progress.curves.fill`. Every other
5
+ * value is an internal constant.
6
+ */
7
+ export declare const progressBar: {
8
+ /**
9
+ * setProgress(_:animated: true) runs this long for a change of the whole
10
+ * track (0 → 1). A smaller change runs in proportion, measured on the model
11
+ * values: 0.2 → 0.8 takes 0.6 s. A retargeted fill starts from wherever it
12
+ * is drawn.
13
+ * @source measured: UIKit lab (injected host app), iOS 26.2 simulator,
14
+ * iPhone 17 Pro, UIView animation on the fill's frame (duration,
15
+ * beginFromCurrentState) for jumps of 0.6, 0.4 and 0.6, Oct 23 2026
16
+ */
17
+ readonly fillTrackMs: 1000;
18
+ readonly curves: {
19
+ /**
20
+ * That animation's curve: linear, and Reduce Motion leaves it unchanged.
21
+ * @source measured: UIKit lab (injected host app), iOS 26.2 simulator,
22
+ * iPhone 17 Pro, the fill's position animation (timing function
23
+ * linear), with Reduce Motion off and on, Oct 23 2026
24
+ */
25
+ readonly fill: readonly [0, 0, 1, 1];
26
+ };
27
+ readonly progressView: {
28
+ /**
29
+ * The track's height in the `.default` style; the fill is as tall.
30
+ * @source measured: UIKit lab (injected host app), iOS 26.2 simulator,
31
+ * iPhone 17 Pro, intrinsic size of UIProgressView(progressViewStyle:
32
+ * .default), Oct 23 2026
33
+ */
34
+ readonly heightPt: 4;
35
+ /**
36
+ * Above zero progress, the fill is never narrower than this many track
37
+ * heights: 8 pt on the 4 pt track. At 0.005 of a 300 pt track it is 8 pt
38
+ * wide; at 0.05 it is 15 pt.
39
+ * @source measured: UIKit lab (injected host app), iOS 26.2 simulator,
40
+ * iPhone 17 Pro, the fill image view's frame at progress 0, 0.005,
41
+ * 0.01, 0.05, 0.5 and 1, Oct 23 2026
42
+ */
43
+ readonly minimumFillHeights: 2;
44
+ /**
45
+ * At progress 0 the fill is transparent (alpha 0, still at its minimum
46
+ * width).
47
+ * @source measured: UIKit lab (injected host app), iOS 26.2 simulator,
48
+ * iPhone 17 Pro, the fill image view's alpha at progress 0, Oct 23 2026
49
+ */
50
+ readonly emptyFillAlpha: 0;
51
+ };
52
+ };
53
+ /**
54
+ * Registers the table's two roles, for the generated motion role table and its
55
+ * test, which call it. Nothing at runtime reads the registry: `resolveMotion`
56
+ * returns the table value. Idempotent, and nothing runs on import.
57
+ */
58
+ export declare function registerProgressBarTable(): void;
59
+ //# sourceMappingURL=progressBar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progressBar.d.ts","sourceRoot":"","sources":["../../../src/motion/uikit/progressBar.ts"],"names":[],"mappings":"AAmBA;;;;;GAKG;AACH,eAAO,MAAM,WAAW;IACtB;;;;;;;;OAQG;;;QAGD;;;;;WAKG;;;;QAIH;;;;;WAKG;;QAEH;;;;;;;WAOG;;QAEH;;;;;WAKG;;;CAGG,CAAC;AAEX;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAI/C"}
@@ -0,0 +1,82 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file progressBar.ts
5
+ * @input Nothing: data only
6
+ * @output Exports `progressBar` (UIProgressView's fill: the whole-track
7
+ * duration and curve, its minimum length and its empty alpha) and
8
+ * `registerProgressBarTable`
9
+ * @position ProgressBar's rows of the UIKit constants table (motion/uikit).
10
+ * Lengths are in pt (CSS px), durations in ms, alphas in 0..1. Tests check
11
+ * each leaf's `@source`.
12
+ *
13
+ * SYNC: When modified, update
14
+ * /packages/core/src/ProgressBar/ProgressBarTouch.ts and
15
+ * /packages/core/src/ProgressBar/ProgressBar.test.tsx.
16
+ */
17
+
18
+ import { registerMotionTable } from "../roles.js";
19
+
20
+ /**
21
+ * UIProgressView's values, for ProgressBar. Two values are motion roles in the
22
+ * generated motion role table: the whole-track duration,
23
+ * `progress.fillTrackMs`, and its curve, `progress.curves.fill`. Every other
24
+ * value is an internal constant.
25
+ */
26
+ export const progressBar = {
27
+ /**
28
+ * setProgress(_:animated: true) runs this long for a change of the whole
29
+ * track (0 → 1). A smaller change runs in proportion, measured on the model
30
+ * values: 0.2 → 0.8 takes 0.6 s. A retargeted fill starts from wherever it
31
+ * is drawn.
32
+ * @source measured: UIKit lab (injected host app), iOS 26.2 simulator,
33
+ * iPhone 17 Pro, UIView animation on the fill's frame (duration,
34
+ * beginFromCurrentState) for jumps of 0.6, 0.4 and 0.6, Oct 23 2026
35
+ */
36
+ fillTrackMs: 1000,
37
+ curves: {
38
+ /**
39
+ * That animation's curve: linear, and Reduce Motion leaves it unchanged.
40
+ * @source measured: UIKit lab (injected host app), iOS 26.2 simulator,
41
+ * iPhone 17 Pro, the fill's position animation (timing function
42
+ * linear), with Reduce Motion off and on, Oct 23 2026
43
+ */
44
+ fill: [0, 0, 1, 1]
45
+ },
46
+ progressView: {
47
+ /**
48
+ * The track's height in the `.default` style; the fill is as tall.
49
+ * @source measured: UIKit lab (injected host app), iOS 26.2 simulator,
50
+ * iPhone 17 Pro, intrinsic size of UIProgressView(progressViewStyle:
51
+ * .default), Oct 23 2026
52
+ */
53
+ heightPt: 4,
54
+ /**
55
+ * Above zero progress, the fill is never narrower than this many track
56
+ * heights: 8 pt on the 4 pt track. At 0.005 of a 300 pt track it is 8 pt
57
+ * wide; at 0.05 it is 15 pt.
58
+ * @source measured: UIKit lab (injected host app), iOS 26.2 simulator,
59
+ * iPhone 17 Pro, the fill image view's frame at progress 0, 0.005,
60
+ * 0.01, 0.05, 0.5 and 1, Oct 23 2026
61
+ */
62
+ minimumFillHeights: 2,
63
+ /**
64
+ * At progress 0 the fill is transparent (alpha 0, still at its minimum
65
+ * width).
66
+ * @source measured: UIKit lab (injected host app), iOS 26.2 simulator,
67
+ * iPhone 17 Pro, the fill image view's alpha at progress 0, Oct 23 2026
68
+ */
69
+ emptyFillAlpha: 0
70
+ }
71
+ };
72
+
73
+ /**
74
+ * Registers the table's two roles, for the generated motion role table and its
75
+ * test, which call it. Nothing at runtime reads the registry: `resolveMotion`
76
+ * returns the table value. Idempotent, and nothing runs on import.
77
+ */
78
+ export function registerProgressBarTable() {
79
+ registerMotionTable('progress', progressBar, {
80
+ roles: ['fillTrackMs', 'curves.fill']
81
+ });
82
+ }