Skip to content

chore(core): the motion and gesture internals that Lab's refresh pull reads - #9807

Merged
cixzhang merged 1 commit into
meta:mainfrom
vjeux:uikit/c28-rc-core
Nov 4, 2026
Merged

cixzhang merged 1 commit into
meta:mainfrom
vjeux:uikit/c28-rc-core

Conversation

@vjeux

@vjeux vjeux commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

RefreshControl's Core part: internal re-exports only. Supersedes #8086. It lands right before its first user, Lab's pull to refresh.

Stack: #9807 → #9865

Maintainer impact

Lab's useRefreshControl reads Core's pan recognizer, its hook and the motion engine through the internal touch entry. Lab reaches Core internals only through such entries.

Intended invariant

No behavior change in Core: named re-exports only, with no gathering object, root re-export or docs. Lint allows the entry only in Core and Lab.

Change

internal/touch.ts re-exports exactly the 18 names that Lab's hook imports from it at #9865's head d511e52. Importing files are under packages/lab/src/RefreshControl/:

Symbol From Imported by
PanGestureRecognizer gestures/PanGestureRecognizer RefreshPullRecognizer.ts
type PanGestureRecognizerOptions gestures/PanGestureRecognizer RefreshPullRecognizer.ts
type GestureEventContext gestures/types RefreshPullRecognizer.ts
type GestureTouch gestures/types RefreshPullRecognizer.ts
type PointerKind gestures/types RefreshPullRecognizer.ts, refreshTouchController.ts
useGestureRecognizer gestures/useGestureRecognizer refreshTouchController.ts
createMotionAnimator motion/animator useMotionAnimator.ts
type MotionAnimator motion/animator useMotionAnimator.ts
type MotionAnimatorOptions motion/animator useMotionAnimator.ts
type MotionCurve motion/animator refreshTouchController.ts
cubicBezier motion/bezier refreshPull.ts, refreshTouchController.ts
mapProgress motion/progress refreshTouchController.ts
parseCssEasing motion/roles refreshPull.ts
parseMotionRoleValue motion/roles refreshPull.ts
rubberBand motion/rubberBand refreshPull.ts
rubberBandInverse motion/rubberBand refreshPull.ts
rubberBandSlope motion/rubberBand refreshPull.ts
scroll motion/uikit/scroll refreshTouchController.ts

Check: I parsed the export names of internal/touch.ts at main 9a4627b and at this head. The 18 names it gains equal the 18 those files import; it drops none, and none was on main's entry. observeResize is public (utils).

Evidence

  • Failure before the change: the new identity test in touch.test.ts fails against main's entry.
  • Success after the change: each re-export is the same value as its module's export. A bundle test builds both entries with esbuild: all 11 values are in the internal one and none in the root (Button is the control).
  • Product/runtime behavior verified unchanged: re-exports only; no Core module imports it.

Scope

  • No intended public API, product behavior, visual direction, or policy change.
  • Product changes discovered during the work were removed or split.
  • Public text and artifacts contain no internal Meta context.

Testing

Gates at this head, on main 9a4627b: typecheck, lint and review:pre clean; 1,795 unit tests pass. The bundle test passes, and its mutant fails.

Overlap: #9669, #9696 and #9699 add some of these names; the later merge drops its duplicates. If #9754 lands first, the createMotionAnimator export here takes its name, createMotionEngine.

@vercel

vercel Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astryx Ready Ready Preview Nov 4, 2026 9:31pm UTC

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Nov 3, 2026
@astracat-bot

astracat-bot Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

AI review status for this pull request.

Review status Updated
❓ Needs maintainer input (for maintainers only) Nov 4, 2026, 10:14 PM UTC

@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

🔎 Preview · aaeeced

Storybook · Sandbox · built from this PR's head

Package size: @astryxdesign/core 6.43 MB packed (+937 B); no new dependencies.

API changes: none in this pull request

Committed API report behind this build: cli 8 rows, core 2 rows; run pnpm api:report.

Not run on this PR: add ci:run-visual, ci:run-a11y or ci:run-rtl to run them.


Generated by PR Enrichment workflow | View full report

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested for one fix in the table-imports guard. The internal-entry re-exports, the refreshControl table and the new catalog key match the current specs.

  • isInternalEntry in packages/core/src/motion/uikit/tableImports.test.ts (lines 60–62) exempts every .ts file under internal/, including indicatorPress.stylex.ts, sheetDraft.ts and useDismissSearchOnTouchDrag.ts, which CheckboxInput, TokenizerBottomSheet and PowerSearchBottomSheet import; please exempt only internal files no Core source imports (or internal/touch.ts alone) and correct the JSDoc that says no Core source imports one.

Optional: the comment at internal/touch.ts:45 can drop its first sentence, which restates the export list (suggestion inline). When RefreshControl leaves Lab, its springs, reveal curve and durations will need motion roles under the touch-presentations spec (FR4).

[Automated review]

Comment thread packages/core/src/internal/touch.ts Resolved

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ready to approve. The internal-entry re-exports, the refreshControl table and the new catalog key match the current specs, and the table-imports guard now exempts only internal files no Core source imports, which resolves the earlier comment on isInternalEntry.

  • Optional: the internal/touch.ts header is now 21 lines, and its @output still describes only the gesture core's primitives; moving the new @input text into @output keeps it accurate (suggestion inline).
  • When RefreshControl leaves Lab, its springs, reveal curve and durations need motion roles named in its component record (touch-presentations FR4).

[Automated review]

* @input The gesture core: the arena, the recognizers, and their geometry;
* the motion math and UIKit tables that Lab's RefreshControl reads; the
* page's scroll-style claims
* @output `@astryxdesign/core/internal/touch`: the gesture core's primitives

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional (comment style): @output still describes only the gesture core's primitives, while the entry now also serves the motion math, UIKit tables, touch presentation hook and scroll-style claims, and the header is now 21 lines. Moving the new @input text here and keeping @input to what the file reads keeps the header accurate and shorter.

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved pending CI: CI has not run on this head yet. The pull request is a draft from a fork, so once it is marked ready for review, a maintainer adds the ci:run label so CI runs.

The internal-entry re-exports, the refreshControl table and the new catalog key match the current specs, and the table-imports guard exempts only internal files that no Core source imports.

  • Optional: the internal/touch.ts header is 21 lines, and its @output still describes only the gesture core's primitives; moving the new @input text into @output keeps it accurate (see the earlier inline suggestion).
  • When RefreshControl leaves Lab, its springs, reveal curve and durations need motion roles named in its component record (touch-presentations FR4).

[Automated review]

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved pending CI: CI has not run on this head yet. The pull request is a draft from a fork, so once it is marked ready for review, a maintainer adds the ci:run label so CI runs.

The internal-entry re-exports (now including startsOnSelectableText), the refreshControl table and the new catalog key match the current specs, and the table-imports guard exempts only internal files that no Core source imports.

  • Optional: the internal/touch.ts header is 21 lines, and its @output still describes only the gesture core's primitives; moving the new @input text into @output keeps it accurate (see the earlier inline suggestion).
  • When RefreshControl leaves Lab, its springs, reveal curve and durations need motion roles named in its component record (touch-presentations FR4).

[Automated review]

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved pending CI: CI has not run on this head yet. The pull request is a draft from a fork, so once it is marked ready for review, a maintainer adds the ci:run label so CI runs.

The internal-entry re-exports (now including lockDragSelection and selectionRangesOf), the refreshControl table and the new catalog key match the current specs, and the table-imports guard exempts only internal files that no Core source imports.

  • Optional: the internal/touch.ts header is 22 lines, and its @output still describes only the gesture core's primitives; moving the new @input text into @output keeps it accurate (see the earlier inline suggestion).
  • When RefreshControl leaves Lab, its springs, reveal curve and durations need motion roles named in its component record (touch-presentations FR4).

[Automated review]

@vjeux vjeux changed the title chore(core): what Lab's RefreshControl reads from Core, and UIRefreshControl's values chore(core): the motion and gesture internals that Lab's refresh pull reads Nov 4, 2026
@vjeux
vjeux force-pushed the uikit/c28-rc-core branch from 5a45b8d to 4a3074b Compare November 4, 2026 08:25
@cixzhang

cixzhang commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

/approve-spec 4a3074b

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved pending CI: CI has not run on this head yet. This is a draft from a fork, so a maintainer adds the ci:run label, and marking it ready for review then starts CI.

The new names on Core's internal touch entry match the current specs for internal subpaths, and the new tests show that none of them reaches the public entry.

  • Optional: two comments in packages/core/src/internal/touch.ts (lines 45–47 and 56–57) restate the exports or a name, and the header's @output still describes only the gesture core's primitives; suggestions are inline.

[Automated review]

Comment thread packages/core/src/internal/touch.ts Outdated
Comment on lines +45 to +47
// Lab's useRefreshControl reads these: its pull's pan and the hook that
// starts it. It also reads the motion animator, math and UIKit tables of its
// pull, settle and end.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional (comment style): after the colon, the comment lists the exports below it again. A version that keeps only the reason:

// Lab's useRefreshControl reads these.

Comment on lines +56 to +57
// The animator's internal factory. The public one, `createAnimator`, plays
// only the theme's state-change motion.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Miss: optional (comment style): "The animator's internal factory." restates the name createMotionAnimator. A version that keeps only the reason:

// The public `createAnimator` plays only the theme's state-change motion.

@cixzhang

cixzhang commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

/approve-spec 263234f

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved pending CI: CI has not run on this head yet. This is a draft from a fork, so a maintainer adds the ci:run label so CI runs; marking it ready for review then starts the run.

The new names on Core's internal touch entry, including the two motion-role parsers, match the current specs for internal subpaths, and the new tests show that none of them reaches the public entry.

  • Optional: in packages/core/src/internal/touch.ts, the comments at lines 45–48 and 57–58 restate the exports or a name, and the header's @output still describes only the gesture core's primitives.

[Automated review]

Comment thread packages/core/src/internal/touch.ts Outdated
Comment on lines +45 to +48
// Lab's useRefreshControl reads these: its pull's pan and the hook that
// starts it. It also reads the motion animator and math, and the scroll
// view's bounce spring, for its pull, settle and end. The motion-role
// parsers read the theme's tokens for its end.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional (comment style): after its first clause, this comment lists the exports below it again, and the new last sentence does the same for the parsers. A version that keeps only the reason:

// Lab's useRefreshControl reads these.

@vjeux
vjeux force-pushed the uikit/c28-rc-core branch from 263234f to 8db95c8 Compare November 4, 2026 17:06
@cixzhang

cixzhang commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

/approve-spec 8db95c8

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pull request is reviewed as part of its stack; see the review on #9865.

@vjeux
vjeux marked this pull request as ready for review November 4, 2026 18:16
@cixzhang cixzhang added the ci:run A maintainer lets this outside contributor's pull request run CI (AST-030 FR17) label Nov 4, 2026
@cixzhang
cixzhang marked this pull request as draft November 4, 2026 18:32
@cixzhang
cixzhang marked this pull request as ready for review November 4, 2026 18:33
@vjeux
vjeux marked this pull request as draft November 4, 2026 19:19
@vjeux
vjeux force-pushed the uikit/c28-rc-core branch from 8db95c8 to bbd153f Compare November 4, 2026 19:34

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pull request is reviewed as part of its stack; see the review on #9865.

@cixzhang

cixzhang commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

/approve-spec bbd153f

… reads

Core's internal touch entry re-exports, by name, what Lab's
useRefreshControl imports: the pan recognizer, its hook and the gesture
types; the motion animator; the cubic Bézier, the rubber band with its
inverse and slope, and the map of a companion curve; the UIKit scroll
table; and the motion-role parsers. Each one is an existing internal,
and Core's behavior does not change. A bundle test checks that the
public entry exports none of them.
@vjeux
vjeux force-pushed the uikit/c28-rc-core branch from bbd153f to aaeeced Compare November 4, 2026 21:19
@cixzhang

cixzhang commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

/approve-spec aaeeced

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pull request is reviewed as part of its stack; see the review on #9865.

@vjeux
vjeux marked this pull request as ready for review November 4, 2026 21:55
@cixzhang
cixzhang marked this pull request as draft November 4, 2026 21:57
@cixzhang
cixzhang marked this pull request as ready for review November 4, 2026 21:57
@cixzhang
cixzhang merged commit 2ea8f68 into meta:main Nov 4, 2026
133 of 167 checks passed
@vjeux
vjeux deleted the uikit/c28-rc-core branch November 4, 2026 22:39
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 4, 2026
Internal entries land with their first user, per meta#8562. Lab's
PageControl, NavigationStack and TabBar animate with Core's motion
engine and read the touch presentation and the writing direction as
Core does. `@astryxdesign/core/internal/touch`, which already carries the
pan recognizer, its hook, the engine and the rubber band for Lab's
refresh control (meta#9807), gains by name:

- `useTouchPresentation` and `TOUCH_QUERY`, the finger-or-mouse decision
  in render and outside it;
- `isRtlElement`, the writing direction a pan mirrors by;
- UIKit's `UIKIT_GESTURES` table.

The engine's factory is renamed from `createMotionAnimator` to
`createMotionEngine` at its source and in every internal caller, with its
types `MotionEngine` and `MotionEngineOptions` (the engine's `Animator`
and `AnimatorOptions`), so the engine and the public `createAnimator`
differ by more than one word (architecture:react-component-runtime INV13).

Named re-exports of code already on main, plus that rename: no behavior
changes, no public docs, no root re-export, and the
`@astryx/no-core-internal-import` lint rule already limits the entry to
Core and Lab. The entry's tests check it re-exports the same values Core
imports by path and carries no public factory's name; the touch-support
bundle test keeps every Lab-only name out of the root entry.

One Lab module those components share comes with them:
`internal/useMotionEngine`, a stable motion engine bound to an element
through a callback ref. Lab's refresh control now uses it in place of its
own identical `RefreshControl/useMotionAnimator.ts`.
vjeux added a commit to vjeux/astryx that referenced this pull request Nov 5, 2026
Internal entries land with their first user, per meta#8562. Lab's
PageControl, NavigationStack and TabBar animate with Core's motion
engine and read the touch presentation and the writing direction as
Core does. `@astryxdesign/core/internal/touch`, which already carries the
pan recognizer, its hook, the engine and the rubber band for Lab's
refresh control (meta#9807), gains by name:

- `useTouchPresentation` and `TOUCH_QUERY`, the finger-or-mouse decision
  in render and outside it;
- `isRtlElement`, the writing direction a pan mirrors by;
- UIKit's `UIKIT_GESTURES` table.

The engine's factory is renamed from `createMotionAnimator` to
`createMotionEngine` at its source and in every internal caller, with its
types `MotionEngine` and `MotionEngineOptions` (the engine's `Animator`
and `AnimatorOptions`), so the engine and the public `createAnimator`
differ by more than one word (architecture:react-component-runtime INV13).

Named re-exports of code already on main, plus that rename: no behavior
changes, no public docs, no root re-export, and the
`@astryx/no-core-internal-import` lint rule already limits the entry to
Core and Lab. The entry's tests check it re-exports the same values Core
imports by path and carries no public factory's name; the touch-support
bundle test keeps every Lab-only name out of the root entry.

One Lab module those components share comes with them:
`internal/useMotionEngine`, a stable motion engine bound to an element
through a callback ref. Lab's refresh control now uses it in place of its
own identical `RefreshControl/useMotionAnimator.ts`.
cixzhang added a commit that referenced this pull request Nov 5, 2026
)

* chore(lab): Lab's animator hook, over Core's internal touch entry

Internal entries land with their first user, per #8562. Lab
components, TabBar first, animate with Core's motion engine and read
the touch presentation and the writing direction as Core does.
`@astryxdesign/core/internal/touch`, which already carries the pan
recognizer, its hook, the engine and the rubber band for Lab's refresh
control (#9807), gains by name:

- `useTouchPresentation` and `TOUCH_QUERY`, the finger-or-mouse decision
  in render and outside it;
- `isRtlElement`, the writing direction a pan mirrors by;
- UIKit's `UIKIT_GESTURES` table.

The engine's factory is renamed from `createMotionAnimator` to
`createMotionEngine` at its source and in every internal caller, with its
types `MotionEngine` and `MotionEngineOptions` (the engine's `Animator`
and `AnimatorOptions`), so the engine and the public `createAnimator`
differ by more than one word (architecture:react-component-runtime INV13).

Named re-exports of code already on main, plus that rename: no behavior
changes, no public docs, no root re-export, and the
`@astryx/no-core-internal-import` lint rule already limits the entry to
Core and Lab. The entry's tests check it re-exports the same values Core
imports by path and carries no public factory's name; the touch-support
bundle test keeps every Lab-only name out of the root entry.

One Lab module those components share comes with them:
`internal/useMotionEngine`, a stable motion engine bound to an element
through a callback ref. Lab's refresh control now uses it in place of its
own identical `RefreshControl/useMotionAnimator.ts`.

* Merge branch 'main' into c09/core-touch-entry-lab-animator

Co-authored-by: Cindy Zhang <cindyxz@meta.com>

This branch was successfully deployed

1 active deployment
Preview — aaeeced3 Deployed Nov 4, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:run A maintainer lets this outside contributor's pull request run CI (AST-030 FR17) CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants