Skip to content

chore(core): Lab reaches Core's pan recognizer, gesture types, touch presentation and motion through internal entries - #8562

Closed
vjeux wants to merge 37 commits into
meta:mainfrom
vjeux:uikit/core-internal-entries
Closed

vjeux wants to merge 37 commits into
meta:mainfrom
vjeux:uikit/core-internal-entries

Conversation

@vjeux

@vjeux vjeux commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Review only this PR's change: vjeux/astryx@39ed04d...cd3ad72 (on main).

Why

A Lab component's registry build fails once it installs Core: Lab imports Core's pan recognizer, gesture types, touch presentation queries and motion modules through paths that resolve inside the repository but not from Core's published entries. The registry-contract (preview) check on the pull-to-refresh pull requests shows it.

What led to it

This comes from the work to make Astryx's touch components behave as native iOS ones do (sheets, menus, gestures and their motion). The touch-model decision on #8465: "Lab components reach the same modules through Core's internal subpaths (@astryxdesign/core/internal/touch and similar)". These entries are undocumented, outside the compatibility promise, and allowed by lint only in Core and Lab (architecture:react-component-runtime INV13).

Options and tradeoffs

Why this choice

The decision on #8465 picks internal entries. Named re-exports keep each component's bundle to what it imports, and a tuning table to the rows it reads (architecture:component-style-authoring INV6).

What changes

  • @astryxdesign/core/internal/touch also re-exports the pan recognizer, the gesture types, the default environment, and the touch presentation queries and hooks.
  • A new @astryxdesign/core/internal/motion re-exports the animator, the bezier and spring math, the rubber band and the UIKit tuning tables.
  • Both entries are listed in scripts/sync-exports.js; modules not yet on main join as their pull requests land.
  • This push also merges main and narrows main's check that resolveSnapPoint stays internal to the public entries.

How to check it

  1. Build Core, then in a project that installs it, import the pan recognizer from @astryxdesign/core/internal/touch and the animator from @astryxdesign/core/internal/motion: both resolve.
  2. Bundle a file that imports one name from either entry: the output contains only that module.
  3. Lint a file outside Core and Lab that imports either entry: lint rejects it.

Evidence

  • The resolveSnapPoint export test: public entries only, and internal/motion re-exports no resolveSnapPoint.
  • The build, type check, lint and unit suites pass; no component changes.

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.

vjeux and others added 16 commits October 25, 2026 16:38
A build that defines __ASTRYX_TOUCH__ as false presents every component the pointer way and leaves out each touch layer imported through the guard touchLayers.ts documents. Without the define nothing changes. The browser support guide covers the build settings, device routing and the Next.js caveat.
…aved draft

The section's last sentence ended on "saves", which matches "saved" in the main searcher's "toast notice for a saved draft" query. The section took the 20th result from a shorter doc and grew that answer past the lexical ranker's, which the main searcher's byte check rejects. The sentence now ends on "is worth"; a guard test pins that the guide is found for its own topic and not for that query.
…ind it through one internal hook

@astryxdesign/core/touch-support exports TouchSupport: install() (idempotent, a no-op on the server, adds no listeners) and isInstalled(), nothing else. The module (main's gesture core; the animator joins it) sits in one module-level registry that components read only through the internal useTouchSupport hook, null on the server and until installed. Lint keeps the internals to Core and Lab, and the exports map holds only the public entry. A bundle test pins that core's root, hooks and utils entries and a component reading the hook carry none of the module, and that an install carries it. Replaces this branch's __ASTRYX_TOUCH__ define, resolver change and guide section, which the install makes unnecessary.
CI-Rerun: one RTL story navigation timed out in pr-rtl (core 2/3) of run 40273227303; it does not reproduce at this tree.
…ere a coarse pointer is present

install() registers the module now where some input is a coarse pointer (any-pointer: coarse), and otherwise waits on that query's change event, registering once a coarse pointer appears (a tablet attached to a laptop), so a page used only with a mouse registers nothing. isInstalled() reports whether install() ran. The doc comment says layout and presence motion works without it. Tests cover a fine-pointer page and one that gains a coarse pointer later.
…sture core

Core's root, hooks and utils entries are checked to carry none of the touch module (touch-support/touchModule.ts) until an app installs TouchSupport: an entry that imports the module, directly or through TouchSupport, still fails. Whether an entry carries the gesture core itself is a separate check, held until components have moved onto the module, so this check does not fail a component that still imports a recognizer directly. Glue on useTouchSupport is still checked to carry neither the module nor the gesture core.
CI-Rerun: Vercel's deployment of 1a0c61d failed on Vercel's side; that head changed only a test file, and the branches pushed in the same second deployed.
The module holds the gesture core and no component uses it yet; the module's code ships with the entry, so a page that imports it sends that code to every visitor, and only registration waits for a coarse pointer. The doc no longer promises an animator, components' touch behavior or Reduce Motion handling, which arrive in later releases.
…ntry

@astryxdesign/core/internal/touch exports useTouchSupport and the touch module's type, so a Lab component reaches the module the way a Core component does. Like every internal entry, it is undocumented, outside the public API, and allowed by lint only in Core and Lab, which now refuses @astryxdesign/core/internal/* elsewhere in place of the old touch-support/* ban. sync-exports lists it with the other file subpaths. A component that reads the module through it still carries none of the gesture core.
…install step

The touch and gesture module is one shared internal module that Core components import directly and Lab components reach through @astryxdesign/core/internal/touch; a bundler keeps one copy per page. The public touch-support entry, TouchSupport.install() and isInstalled(), the registry and useTouchSupport go away. Importing the module attaches no listeners, so a page with only a fine pointer runs none. Tests: two components importing it share one copy in a split bundle, and the module loads without listeners.
…presentation and motion through internal entries

@astryxdesign/core/internal/touch now also re-exports PanGestureRecognizer, the gesture types and the touch presentation queries, and the new @astryxdesign/core/internal/motion re-exports the animator, the bezier and spring math, the rubber band and the UIKit tuning tables: the modules on main that Lab components import today by unexported paths. Named re-exports only, so a component ships only what it imports. A guard test fails a Lab import of a covered module that does not go through an internal entry.
Core is about to export a few undocumented modules under
`@astryxdesign/core/internal/<name>`, so Lab can build on machinery with
no public API of its own (the reorder engine behind createReorderable
first). They are reserved for Astryx's own packages and sit outside the
compatibility promise (spec:AST-017 FR21).

A new rule, @astryx/no-core-internal-import, reports any import, re-export
or dynamic import of `@astryxdesign/core/internal` or a path under it. The
repo config turns it on for every file outside packages/core and
packages/lab. It is a custom rule rather than a repo-wide
`no-restricted-imports` block, because flat config overrides a same-named
rule per file and would undo the layer blocks that already use it. The
plugin README records the convention each internal subpath follows: an
explicit `./internal/<name>` exports entry, never a wildcard, and a header
saying it is reserved, undocumented and outside the promise.

Lint-only; nothing ships, so no changeset.
The previous commit's formatter pass reflowed three unrelated selectors.
The previous commit emptied the file by mistake. This puts back main's
config with only the internal-subpath block added.
@vercel

vercel Bot commented Oct 26, 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 Oct 27, 2026 11:22am UTC

Request Review

@astracat-bot

astracat-bot Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
❓ Needs maintainer input (for maintainers only) Oct 29, 2026, 10:44 PM UTC

cixzhang and others added 2 commits October 26, 2026 10:42
…rule

Core's internal subpaths share one convention (meta#8561): an explicit
./internal/<name> exports entry, a header saying it is reserved for
Astryx's own packages, undocumented and outside the compatibility promise
(spec:AST-017 FR21), and the custom @astryx/no-core-internal-import rule
for files outside Core and Lab. This drops the touch module's own
repo-wide no-restricted-imports block, which flat config would let
override the layer blocks that already use that rule, and points the
entry's header and the lint test at the shared rule.

Co-authored-by: Christopher Chedeau <vjeuxx@gmail.com>
@vjeux vjeux mentioned this pull request Oct 26, 2026
4 tasks done
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 26, 2026
…ort(); README settles the layout

From review: the rule missed `require('@astryxdesign/core/internal/…')`
(the config applies it to .cjs) and TypeScript's
`typeof import('@astryxdesign/core/internal/…')`; both are reported now,
with a test each, and the tests parse with typescript-eslint.

The README describes one layout: an internal subpath is a single file,
`packages/core/src/internal/<name>.ts`, with an explicit
`./internal/<name>` exports entry listed in scripts/sync-exports.js's
STATIC_EXPORTS, and no longer names a module that does not exist yet.
…(); one internal-entry layout) into the touch module
@cixzhang

Copy link
Copy Markdown
Contributor

Posted by Cindy's agent on her behalf.

Thanks, this matches Cindy's decision that Lab may use Core's internals through @astryxdesign/core/internal/*. One change, so there's a single lint rule: please drop this PR's no-restricted-imports block. The shared @astryx/no-core-internal-import rule in #8561 already enforces the Core-and-Lab limit, and it'll be extended to cover the gesture, motion and core source paths this block lists. It also catches .js/.cjs files, require() and typeof import(), and it avoids flat config's same-name override. Everything else here lines up: the single-file entries, and the citations of AST-017 FR21 and react-component-runtime INV13. If this stays idle, we'll make the change after about 30 minutes, keeping your authorship.

vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
… named re-exports) into the Lab reorder base
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
…d the list stack's re-fold; meta#8562 598be90) under TransferList's reorder
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
… named re-exports, the export check on public keys) into the Lab reorder base
vjeux added a commit to vjeux/astryx that referenced this pull request Oct 27, 2026
@vjeux

vjeux commented Oct 30, 2026

Copy link
Copy Markdown
Contributor Author

Folded into #8076 with its commits credited: Core's internal entries for Lab ship there, with the touch foundation they expose. Closing in favor of #8076.

@vjeux

vjeux commented Oct 30, 2026

Copy link
Copy Markdown
Contributor Author

A correction to the note above: the internal entry points no longer ship in #8076. Under the maintainers' rule that internal code lands with its first user, they move to the first Lab component that uses them.

This branch was successfully deployed

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

Labels

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