Repository navigation
chore(core): Core's internal touch entry names, for Lab, the screen-edge pan, spring solver, motion resolver, UIKit navigation springs and focus helpers - #9696
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
AI review status for this pull request.
|
PR Analysis Report🔎 Preview ·
|
| Package | Where | Signature | Usage | |
|---|---|---|---|---|
| + | cli |
./api · Types · type SearchResultEntry |
deprecated?: ComponentDeprecation | undefined |
import type {SearchResultEntry} from '@astryxdesign/cli/api'; const x: SearchResultEntry = {deprecated: …} |
| + | cli |
./authoring · Types · interface ComponentDeprecation |
interface ComponentDeprecation |
import type {ComponentDeprecation} from '@astryxdesign/cli/authoring' |
| + | cli |
./authoring · Types · interface ComponentIconSlotDoc |
interface ComponentIconSlotDoc |
import type {ComponentIconSlotDoc} from '@astryxdesign/cli/authoring' |
| + | cli |
./authoring · Types · interface ComponentIconSlotStateDoc |
interface ComponentIconSlotStateDoc |
import type {ComponentIconSlotStateDoc} from '@astryxdesign/cli/authoring' |
| + | cli |
./authoring · Types · interface MultiComponentDoc |
deprecated?: ComponentDeprecation |
import type {MultiComponentDoc} from '@astryxdesign/cli/authoring'; const x: MultiComponentDoc = {deprecated: …} |
| + | cli |
./authoring · Types · interface SingleComponentDoc |
deprecated?: ComponentDeprecation |
import type {SingleComponentDoc} from '@astryxdesign/cli/authoring'; const x: SingleComponentDoc = {deprecated: …} |
| + | cli |
./doc · Types · interface ComponentBaseDoc |
deprecated?: ComponentDeprecation |
import type {ComponentBaseDoc} from '@astryxdesign/cli/doc'; const x: ComponentBaseDoc = {deprecated: …} |
| + | cli |
./doc · Types · interface SubComponentDoc |
deprecated?: ComponentDeprecation |
import type {SubComponentDoc} from '@astryxdesign/cli/doc'; const x: SubComponentDoc = {deprecated: …} |
| + | cli |
./doc · Also exported from an earlier entry point · ComponentDeprecation |
ComponentDeprecation (./authoring) |
import {ComponentDeprecation} from '@astryxdesign/cli/doc' |
| + | cli |
./doc · Also exported from an earlier entry point · ComponentIconSlotDoc |
ComponentIconSlotDoc (./authoring) |
import {ComponentIconSlotDoc} from '@astryxdesign/cli/doc' |
| + | cli |
./doc · Also exported from an earlier entry point · ComponentIconSlotStateDoc |
ComponentIconSlotStateDoc (./authoring) |
import {ComponentIconSlotStateDoc} from '@astryxdesign/cli/doc' |
| + | cli |
./template · Also exported from an earlier entry point · ComponentDeprecation |
ComponentDeprecation (./authoring) |
import {ComponentDeprecation} from '@astryxdesign/cli/template' |
| + | cli |
./template · Also exported from an earlier entry point · ComponentIconSlotDoc |
ComponentIconSlotDoc (./authoring) |
import {ComponentIconSlotDoc} from '@astryxdesign/cli/template' |
| + | cli |
./template · Also exported from an earlier entry point · ComponentIconSlotStateDoc |
ComponentIconSlotStateDoc (./authoring) |
import {ComponentIconSlotStateDoc} from '@astryxdesign/cli/template' |
| ~ | cli |
./api · Functions · function search |
function search: (query: string, options?: { cwd?: string | undefined; type?: "template" | "component" | "hook" | "theme" | "doc" | undefined; limit?: number | undefined }) => Promise<SearchResponse> → function search: (query: string, options?: { cwd?: string | undefined; type?: "template" | "component" | "doc" | "theme" | "hook" | undefined; limit?: number | undefined }) => Promise<SearchResponse> |
import {search} from '@astryxdesign/cli/api'; search(…) |
| ~ | cli |
./authoring · Types · interface MultiComponentDoc |
theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[] } → theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[]; componentIcons?: ComponentIconSlotDoc[] } |
import type {MultiComponentDoc} from '@astryxdesign/cli/authoring'; const x: MultiComponentDoc = {theming: …} |
| ~ | cli |
./authoring · Types · interface SingleComponentDoc |
theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[] } → theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[]; componentIcons?: ComponentIconSlotDoc[] } |
import type {SingleComponentDoc} from '@astryxdesign/cli/authoring'; const x: SingleComponentDoc = {theming: …} |
| ~ | cli |
./doc · Types · interface ComponentBaseDoc |
theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[] } → theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[]; componentIcons?: ComponentIconSlotDoc[] } |
import type {ComponentBaseDoc} from '@astryxdesign/cli/doc'; const x: ComponentBaseDoc = {theming: …} |
| ~ | cli |
./doc · Types · interface SubComponentDoc |
theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[] } → theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[]; componentIcons?: ComponentIconSlotDoc[] } |
import type {SubComponentDoc} from '@astryxdesign/cli/doc'; const x: SubComponentDoc = {theming: …} |
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
There was a problem hiding this comment.
This needs an engineering owner's decision before it can be approved, plus three fixes.
Because the branch is stacked on #9399, the diff includes Lab's SearchField, which has no governing spec, and the pull request also changes Core, so the Lab exemption does not apply. An engineering owner records the decision on SearchField's direction as it stands (its stacked, bottom and tab placements, its motion, and its placement, lift, isActive and handleRef API) by commenting /approve-spec <full head SHA> on this pull request, or asks for its own spec first; the author may do so if they are an engineering owner.
Blocking:
SearchFieldTouch.tsadds its own document-level swallower for a claimed tap's late mouse events beside Core's shared click guard; extend the guard to drop the latemousedown/mouseupand remove the local copy.- The NavigationStack changeset says Lab's NavigationStack reaches these names, but no NavigationStack exists at this head; describe what the internal entry and the catalog gain instead.
- The bottom and tab placements' keyboard behaviour needs iOS Simulator evidence recorded from this code, which the mobile keyboard spec requires before keyboard work merges.
The Core re-exports and the catalog key match the existing spec, and the new entry test proves them.
[Automated review]
| // lets go (its click, the next press, or its window), the late events are | ||
| // over, and this swallow lets go too. | ||
| const disarmRef = useRef<(() => void) | null>(null); | ||
| const armSwallow = useCallback((doc: Document) => { |
There was a problem hiding this comment.
Blocking: this adds a second swallower for a claimed tap's late mouse events beside Core's shared click guard (utils/clickGuard.ts), which the gesture host already arms at the claimed lift; its document listeners also stay after the press until the next input. Extend the click guard (or the host's claimed-lift path) to drop the late mousedown/mouseup under the same disarm rules, and delete armSwallow, disarmRef and the unmount Effect, so every claimed tap gets the fix.
| '@astryxdesign/core': patch | ||
| --- | ||
|
|
||
| [experimental] Lab's experimental NavigationStack reaches Core's pan and screen-edge pan recognizers, spring solver, rubber band, motion resolver, UIKit tables and coarse-pointer query through Core's internal `@astryxdesign/core/internal/touch` entry. That entry stays outside the public API and its compatibility promise. Its back button's fallback name joins Core's message catalog. |
There was a problem hiding this comment.
Blocking: no NavigationStack exists at this head, so this release note would describe a component the release may not contain. Suggested wording: "[experimental] Core's internal @astryxdesign/core/internal/touch entry also names the pan and screen-edge pan recognizers, spring solver, rubber band, motion resolver, UIKit navigation, springs and gesture tables and the coarse-pointer query, for Lab. The entry stays outside the public API and its compatibility promise. Core's English catalog gains @astryx.navigationStack.back."
| // Inactive, the close button is transparent (the animator holds its | ||
| // opacity at 0) and takes no taps. |
There was a problem hiding this comment.
Non-blocking: these two lines describe closeInert, which has its own comment below; here they sit above beforePlacement. Delete them.
5a378ba to
6efca9f
Compare
There was a problem hiding this comment.
This needs an engineering owner's decision on SearchField's direction before it can be approved, plus two fixes.
Because the branch is stacked on #9399, the diff includes Lab's SearchField, which has no governing spec, and the pull request also changes Core, so it is not a Lab-only change. An engineering owner records a decision on SearchField as it stands (its stacked, bottom and tab placements, its activation and cancel motion, the claimed tap at the bottom, and its placement, lift, isActive/onActiveChange and handleRef API) by commenting /approve-spec <full head SHA> on this pull request, or asks for a spec record first; the author may do so if they are an engineering owner.
Blocking:
- The title says Lab's NavigationStack reaches Core's names, but no NavigationStack exists at this head, so retitle it to what the change does, for example "chore(core): Core's internal touch entry names the pan recognizers, spring solver, rubber band and UIKit tables for Lab".
spec:AST-099DEC-3 makes iOS Simulator evidence in a top-level document a merge gate for keyboard work, and SearchField's only iOS evidence comes from the drafts this code replaced, so add an iOS Simulator run of the Bottom and InTabBar stories at this head.
SearchField's second late-click swallower is gone and the changeset no longer names NavigationStack.
[Automated review]
|
|
||
| const storybook = withStorybook(test); | ||
|
|
||
| /** UIKit's search activation on iOS 26.2 (uikit/search.ts). */ |
There was a problem hiding this comment.
Non-blocking: uikit/search.ts does not exist; the search table is packages/lab/src/internal/searchMotion.ts.
| const storybook = withStorybook(test); | ||
|
|
||
| // The bottom placement's measurements, as in the UIKit table | ||
| // (`search.bottom`, motion/uikit/search.ts, which search.test.ts holds |
There was a problem hiding this comment.
Non-blocking: motion/uikit/search.ts and search.test.ts do not exist; the table is packages/lab/src/internal/searchMotion.ts, checked by searchMotion.test.ts.
| // The field box hosts the leading end (::before) and the middle | ||
| // (::after); the trailing part hosts the trailing end's cap (::before). |
There was a problem hiding this comment.
Non-blocking: this restates the merged refs on the next line and the SearchFieldMotion JSDoc. Delete it.
| // The rounded ends and the middle are pseudo-elements, being decoration: | ||
| // the field's ::before and ::after, and the trailing part's ::before. |
There was a problem hiding this comment.
Non-blocking: this restates the pseudoElement options below. Delete it, or keep only: "The rounded ends and the middle are decoration, so they are pseudo-elements."
6efca9f to
570f836
Compare
There was a problem hiding this comment.
Changes requested: two fixes before this can merge.
packages/core/src/internal/touch.ts:49re-exportscreateAnimator as createMotionAnimator, butmainalready renamed that factory tocreateMotionAnimator(#8653), so once merged Core's typecheck fails, the entry'screateMotionAnimatorisundefinedanduseMotionAnimatorthrows; re-exportcreateMotionAnimatordirectly, compare withanimator.createMotionAnimatorintouch.test.ts:44, and rebase onmain.- The title says Lab's NavigationStack reaches these modules, but no NavigationStack exists in this pull request or on
main; retitle it to what it does, for example "chore(core): Core's internal touch entry names the screen-edge pan recognizer, spring solver, rubber band inverse and UIKit navigation and springs tables for Lab".
The first fix belongs in #9754's commit, which this branch carries. The identity checks in touch.test.ts pass when both sides are undefined, so asserting that each entry name is defined would catch a rename like this one. Otherwise the new entry names, the internal hook and the catalog key fit the existing rules for internal entries and the English catalog.
[Automated review]
| export {isRtlElement} from '../hooks/isRtlElement'; | ||
| // The animator's internal factory, under a name no public factory has: the | ||
| // public animator factory is `createAnimator`. | ||
| export {createAnimator as createMotionAnimator} from '../motion/animator'; |
There was a problem hiding this comment.
Blocking: main already renamed this factory to createMotionAnimator (#8653), and this file merges without a conflict, so after the merge Core's typecheck reports TS2305 here and the entry's createMotionAnimator is undefined. Re-export it under its own name, export {createMotionAnimator} from '../motion/animator';, and delete the comment above, which then only restates the name.
| expect(entry.useGestureRecognizer).toBe(hook.useGestureRecognizer); | ||
| expect(entry.useTouchPresentation).toBe(presentation.useTouchPresentation); | ||
| expect(entry.isRtlElement).toBe(direction.isRtlElement); | ||
| expect(entry.createMotionAnimator).toBe(animator.createAnimator); |
There was a problem hiding this comment.
Blocking (same fix): on main both sides of this check are undefined, so it passes while the entry is broken. Compare with animator.createMotionAnimator, and assert that each entry name is defined so a rename on the module side fails here.
There was a problem hiding this comment.
Fixed: the identity checks compare with the renamed export, and every name this pull request adds also sits in the base's defined-checks (typeof … === 'function' or toBeDefined), so a rename on the module side fails here.
570f836 to
7723b7f
Compare
There was a problem hiding this comment.
Changes requested: one fix before this can merge.
.changeset/core-internal-entries-lab-navigationstack.mdfiles this internal-entry change as[experimental], so Core's changelog would list it under "Experimental APIs" although the entry stays outside the public API; file it as[chore] Internal: …, as #9754's changeset for the same entry already does.
The earlier alias break and title are fixed: the entry re-exports createMotionEngine directly, the identity checks also assert that each name is defined, and the title names only what the entry adds. Two optional comment fixes are inline.
[Automated review]
| '@astryxdesign/core': patch | ||
| --- | ||
|
|
||
| [experimental] Core's internal `@astryxdesign/core/internal/touch` entry also names, for Lab, the screen-edge pan recognizer, the spring solver, the rubber band's inverse and the motion resolver. It also names UIKit's navigation and springs tables. The entry stays outside the public API and its compatibility promise. Core's English catalog gains `@astryx.navigationStack.back`. |
There was a problem hiding this comment.
Blocking: [experimental] puts this note under "Experimental APIs" in Core's changelog, but the internal entry is outside the public API and carries no experimental surface. Suggested, matching #9754's changeset:
[chore] Internal: Core's internal touch entry also names, for Lab, the screen-edge pan recognizer, the spring solver, the rubber band's inverse and the motion resolver, and UIKit's navigation and springs tables. Core's English catalog gains `@astryx.navigationStack.back`. Apps import nothing new.
| * @output `@astryxdesign/core/internal/touch`: the gesture core's primitives | ||
| * for Lab components, re-exported by name |
There was a problem hiding this comment.
Optional: @input now names the motion, touch and direction modules, but @output still says "the gesture core's primitives". Suggested:
* @output `@astryxdesign/core/internal/touch`: the gesture, motion,
* touch-presentation and direction modules Lab uses, re-exported by name|
|
||
| /** | ||
| * Options of `createMotionAnimator`. | ||
| * Options of `createMotionEngine`. |
There was a problem hiding this comment.
Optional: this comment sits above SetOptions' own comment and documents nothing. Move it above export interface AnimatorOptions, which the internal entry now re-exports as MotionEngineOptions, or delete it.
7723b7f to
c8a5d47
Compare
There was a problem hiding this comment.
No blocking findings: every change stays inside Core's internal touch entry, Core's English catalog and Lab's internals, each matches the current records, and the changeset is now filed as [chore] Internal:.
Two optional comment fixes:
packages/core/src/internal/touch.ts:7-8:@outputstill says "the gesture core's primitives", but the entry now also re-exports motion, touch-presentation and direction modules.packages/core/src/motion/animator.ts:300-302: "Options ofcreateMotionEngine." sits aboveSetOptionsand documents nothing; move it aboveAnimatorOptionsor delete it.
[Automated review]
c8a5d47 to
96b09a8
Compare
There was a problem hiding this comment.
Changes requested: one fix before this can merge.
- Miss:
packages/core/src/internal/touch.ts:90re-exports the whole 35-rowspringstable for Lab's NavigationStack, so that component's import would carry spring rows only other components read, againstarchitecture:component-style-authoringINV6; re-export the four rows it plays (NAVIGATION_PUSH_SPRING,NAVIGATION_POP_SPRING,NAVIGATION_INTERACTIVE_POP_FINISH_SPRING,NAVIGATION_BAR_ELEMENTS_SPRING) in place ofsprings, and updatetouch.test.tsandLAB_ONLY_NAMESto match.
The other names stay inside Core's internal entry as spec:AST-017 FR21 and architecture:react-component-runtime INV13 allow, and the catalog key follows the English source contract. #9697 does not yet carry the same Stack: line or sit on this head, so this pull request was reviewed on its own.
[Automated review]
| export {solveSpring, toSpring} from '../motion/spring'; | ||
| export type {SpringDescription} from '../motion/spring'; | ||
| export {navigation, registerNavigationTable} from '../motion/uikit/navigation'; | ||
| export {registerSpringsTable, springs} from '../motion/uikit/springs'; |
There was a problem hiding this comment.
Miss (blocking): springs is the table of all 35 UIKit spring rows, so a Lab component that reads it through this entry carries the sheet, alert, keyboard, banner and switch rows too, against architecture:component-style-authoring INV6 ("ships to a component only the rows that component uses"). Re-export the rows NavigationStack plays instead:
export {
NAVIGATION_BAR_ELEMENTS_SPRING,
NAVIGATION_INTERACTIVE_POP_FINISH_SPRING,
NAVIGATION_POP_SPRING,
NAVIGATION_PUSH_SPRING,
registerSpringsTable,
} from '../motion/uikit/springs';Then update touch.test.ts and LAB_ONLY_NAMES in scripts/touch-support-bundle.test.mjs to match.
Lab's NavigationStack, which follows in its own pull request, reads the screen-edge pan recognizer, the spring solver, the motion resolver, UIKit's navigation table and its four navigation springs. It also reads Core's focus helpers that follow the last input. Core's internal `@astryxdesign/core/internal/touch` entry now names them: named re-exports only, outside the public API. The entry test checks each runtime name is the value Core imports by path. The touch-support bundle test checks each is in the internal entry and not in the root entry. The stack's back button falls back to one catalog key, `@astryx.navigationStack.back`, added to Core's English catalog as the Comments family's Lab keys are.
96b09a8 to
66e6c3b
Compare
There was a problem hiding this comment.
Approved pending CI: CI has not run on this head yet. It runs once the pull request leaves draft and, because the branch is in a fork, a maintainer adds the ci:run label.
Every new name stays inside Core's internal touch entry, which now re-exports the four navigation spring rows instead of the whole springs table, and the new key follows the English catalog contract. The new tests fail against main's entry and pass here.
- #9697 does not yet carry the same
Stack:line and is not based on this head: it still importssprings,registerNavigationTableandregisterSpringsTable, which this head no longer exports, so it needs a rebase onto this head before the two can land.
[Automated review]
|
/approve-spec 66e6c3b |
|
/approve-spec e3168e3 |
There was a problem hiding this comment.
Approved pending CI: CI has not finished on this head yet.
Every new name stays inside Core's internal touch entry, with only the four navigation spring rows rather than the whole springs table, and the new English key follows the catalog contract. The new tests fail against main's entry and pass here, and the merge from main leaves the pull request's own change as it was.
- #9697 still sits on this branch's commit from before
mainwas merged in; rebasing it onto this head keeps the declared stack consistent.
[Automated review]
Stack: #9696 → #9697
The Core part of NavigationStack, split out so the Lab pull request that follows touches no Core file.
Maintainer impact
Lab's NavigationStack (the Lab pull request that follows) reads Core's screen-edge pan recognizer, spring solver and motion resolver, UIKit's navigation table and four navigation springs, and Core's focus helpers that follow the last input. Lab reaches Core modules outside the public API only through Core's internal entries, so
@astryxdesign/core/internal/touchnames them. The back button's fallback name needs one catalog key.Intended invariant
No behavior change. The entry gains named re-exports only: no new module, no gathering object, no root re-export, no docs. Internal entries stay outside the public API and its compatibility promise, and the lint boundary allows them in Core and Lab only.
Authority:
architecture:react-component-runtimeINV13 (the internal entry, its lint boundary, and the Lab needs it serves),spec:AST-017FR21,architecture:component-style-authoringINV6,spec:AST-094FR19 and FR24 (nothing attaches on import), andarchitecture:internationalizationINV6 (the catalog key).Change
packages/core/src/internal/touch.tsre-exportsScreenEdgePanGestureRecognizer,resolveMotion,solveSpring,toSpring,navigation, the four rows NavigationStack plays (NAVIGATION_PUSH_SPRING,NAVIGATION_POP_SPRING,NAVIGATION_INTERACTIVE_POP_FINISH_SPRING,NAVIGATION_BAR_ELEMENTS_SPRING, not the wholespringstable),focusForLastInput,isFocusLostanduseInteractionModalityTracking, with the typeSpringDescription. None is a public factory's name.scripts/touch-support-bundle.test.mjslists the twelve runtime names among those only Lab reads, so its check proves each is in the internal entry and not in the root entry.packages/core/locales/en.jsongains@astryx.navigationStack.back("Back"), as the Comments family's Lab keys are.Evidence
touch.test.tsfail against main's entry, which lacks the names (expected undefined to be [Function: ScreenEdgePanGestureRecognizer]).touch.test.tsand the touch-support bundle test pass;check:i18n-catalogandcheck:i18n-runtimepass with the new key.Scope
Testing
Local gates at this head (66e6c3b, on main 9e559e9), after a frozen install (exit 0): the internal-entry units 20/20 (5 files); the touch-support bundle test 11/11; Core typecheck exit 0; strict lint clean on the changed files; Prettier clean;
check:i18n-catalog,check:i18n-runtime,check:changesets, changeset coverage,check:knowledgeandcheck:repopass;pnpm review:prereports no findings (97 authored lines). Red-first on a committed arm, main's entry under this head's tests (e239256, not for landing): the entry test fails (expected undefined to be [Function: ScreenEdgePanGestureRecognizer]), and so does the bundle test's Lab-names check (expected [ …(12) ] to deeply equal []); at this head both pass.