Skip to content

Commit 78747fa

Browse files
committed
Add Transition Types (facebook#32105)
This adds an isomorphic API to add Transition Types, which represent the cause, to the current Transition. This is currently mainly for View Transitions but as a concept it's broader and we might expand it to more features and object types in the future. ```js import { unstable_addTransitionType as addTransitionType } from 'react'; startTransition(() => { addTransitionType('my-transition-type'); setState(...); }); ``` If multiple transitions get entangled this is additive and all Transition Types are collected. You can also add more than one type to a Transition (hence the `add` prefix). Transition Types are reset after each commit. Meaning that `<Suspense>` revealing after a `startTransition` does not get any View Transition types associated with it. Note that the scoping rules for this is a little "wrong" in this implementation. Ideally it would be scoped to the nearest outer `startTransition` and grouped with any `setState` inside of it. Including Actions. However, since we currently don't have AsyncContext on the client, it would be too easy to drop a Transition Type if there were no other `setState` in the same `await` task. Multiple Transitions are entangled together anyway right now as a result. So this just tracks a global of all pending Transition Types for the next Transition. An inherent tricky bit with this API is that you could update multiple roots. In that case it should ideally be associated with each root. Transition Tracing solves this by associating a Transition with any updates that are later collected but this suffers from the problem mentioned above. Therefore, I just associate Transition Types with one root - the first one to commit. Since the View Transitions across roots are sequential anyway it kind of makes sense that only one really is the cause and the other one is subsequent. Transition Types can be used to apply different animations based on what caused the Transition. You have three different ways to choose from for how to use them: ## CSS It integrates with [View Transition Types](https://www.w3.org/TR/css-view-transitions-2/#active-view-transition-pseudo-examples) so you can match different animations based on CSS scopes: ```css :root:active-view-transition-type(my-transition-type) { &::view-transition-...(...) { ... } } ``` This is kind of a PITA to write though and if you have a CSS library that provide View Transition Classes it's difficult to import those into these scopes. ## Class per Type This PR also adds an object-as-map form that can be passed to all `className` properties: ```js <ViewTransition className={{ 'my-navigation-type': 'hello', 'default': 'world', }}> ``` If multiple types match, then they're joined together. If no types match then the special `"default"` entry is used instead. If any type has the value `"none"` then that wins and the ViewTransition is disabled (not assigned a name). These can be combined with `enter`/`exit`/`update`/`layout`/`share` props to match based on kind of trigger and Transition Type. ```js <ViewTransition enter={{ 'navigation-back': 'enter-right', 'navigation-forward': 'enter-left', }} exit={{ 'navigation-back': 'exit-right', 'navigation-forward': 'exit-left', }}> ``` ## Events In addition, you can also observe the types in the View Transition Event callbacks as the second argument. That way you can pick different imperative Animations based on the cause. ```js <ViewTransition onUpdate={(inst, types) => { if (types.includes('navigation-back')) { ... } else if (types.includes('navigation-forward')) { ... } else { ... } }}> ``` ## Future In the future we might expose types to `useEffect` for more general purpose usage. This would also allow non-View Transition based Animations such as existing libraries to use this same feature to coordinate the same concept. We might also allow richer objects to be passed along here. Only the strings would apply to View Transitions but the imperative code and effects could do something else with them. DiffTrain build for [028c8e6](facebook@028c8e6)
1 parent a64ab3a commit 78747fa

23 files changed

+89
-88
lines changed

compiled-rn/VERSION_NATIVE_FB

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
19.1.0-native-fb-77656c55-20250117
1+
19.1.0-native-fb-028c8e6c-20250121

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-dom/cjs/ReactDOM-dev.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<40913246f8742871bf2cf17d38a4325e>>
10+
* @generated SignedSource<<196643d457b7976a620753cc80271271>>
1111
*/
1212

1313
"use strict";
@@ -428,5 +428,5 @@ __DEV__ &&
428428
exports.useFormStatus = function () {
429429
return resolveDispatcher().useHostTransitionStatus();
430430
};
431-
exports.version = "19.1.0-native-fb-77656c55-20250117";
431+
exports.version = "19.1.0-native-fb-028c8e6c-20250121";
432432
})();

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-dom/cjs/ReactDOM-prod.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<f0851de072b690ed4f2444d8e70b027a>>
10+
* @generated SignedSource<<00d882adfafb6d1a9627beb598263fa8>>
1111
*/
1212

1313
"use strict";
@@ -203,4 +203,4 @@ exports.useFormState = function (action, initialState, permalink) {
203203
exports.useFormStatus = function () {
204204
return ReactSharedInternals.H.useHostTransitionStatus();
205205
};
206-
exports.version = "19.1.0-native-fb-77656c55-20250117";
206+
exports.version = "19.1.0-native-fb-028c8e6c-20250121";

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-dom/cjs/ReactDOM-profiling.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<f0851de072b690ed4f2444d8e70b027a>>
10+
* @generated SignedSource<<00d882adfafb6d1a9627beb598263fa8>>
1111
*/
1212

1313
"use strict";
@@ -203,4 +203,4 @@ exports.useFormState = function (action, initialState, permalink) {
203203
exports.useFormStatus = function () {
204204
return ReactSharedInternals.H.useHostTransitionStatus();
205205
};
206-
exports.version = "19.1.0-native-fb-77656c55-20250117";
206+
exports.version = "19.1.0-native-fb-028c8e6c-20250121";

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-dom/cjs/ReactDOMClient-dev.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<f261aa5045ef5ea02ca743a4804c9089>>
10+
* @generated SignedSource<<7e27dad790bbcabadfdb7af782fa0c42>>
1111
*/
1212

1313
/*
@@ -25957,11 +25957,11 @@ __DEV__ &&
2595725957
};
2595825958
(function () {
2595925959
var isomorphicReactPackageVersion = React.version;
25960-
if ("19.1.0-native-fb-77656c55-20250117" !== isomorphicReactPackageVersion)
25960+
if ("19.1.0-native-fb-028c8e6c-20250121" !== isomorphicReactPackageVersion)
2596125961
throw Error(
2596225962
'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' +
2596325963
(isomorphicReactPackageVersion +
25964-
"\n - react-dom: 19.1.0-native-fb-77656c55-20250117\nLearn more: https://react.dev/warnings/version-mismatch")
25964+
"\n - react-dom: 19.1.0-native-fb-028c8e6c-20250121\nLearn more: https://react.dev/warnings/version-mismatch")
2596525965
);
2596625966
})();
2596725967
("function" === typeof Map &&
@@ -25998,10 +25998,10 @@ __DEV__ &&
2599825998
!(function () {
2599925999
var internals = {
2600026000
bundleType: 1,
26001-
version: "19.1.0-native-fb-77656c55-20250117",
26001+
version: "19.1.0-native-fb-028c8e6c-20250121",
2600226002
rendererPackageName: "react-dom",
2600326003
currentDispatcherRef: ReactSharedInternals,
26004-
reconcilerVersion: "19.1.0-native-fb-77656c55-20250117"
26004+
reconcilerVersion: "19.1.0-native-fb-028c8e6c-20250121"
2600526005
};
2600626006
internals.overrideHookState = overrideHookState;
2600726007
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
@@ -26147,5 +26147,5 @@ __DEV__ &&
2614726147
listenToAllSupportedEvents(container);
2614826148
return new ReactDOMHydrationRoot(initialChildren);
2614926149
};
26150-
exports.version = "19.1.0-native-fb-77656c55-20250117";
26150+
exports.version = "19.1.0-native-fb-028c8e6c-20250121";
2615126151
})();

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-dom/cjs/ReactDOMClient-prod.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<86671b3d7a7ad04eb53f4c5a5728e3b4>>
10+
* @generated SignedSource<<b58e5efc1912dfa86b64057623e9bd9b>>
1111
*/
1212

1313
/*
@@ -15968,14 +15968,14 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) {
1596815968
};
1596915969
var isomorphicReactPackageVersion$jscomp$inline_1785 = React.version;
1597015970
if (
15971-
"19.1.0-native-fb-77656c55-20250117" !==
15971+
"19.1.0-native-fb-028c8e6c-20250121" !==
1597215972
isomorphicReactPackageVersion$jscomp$inline_1785
1597315973
)
1597415974
throw Error(
1597515975
formatProdErrorMessage(
1597615976
527,
1597715977
isomorphicReactPackageVersion$jscomp$inline_1785,
15978-
"19.1.0-native-fb-77656c55-20250117"
15978+
"19.1.0-native-fb-028c8e6c-20250121"
1597915979
)
1598015980
);
1598115981
ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
@@ -15997,10 +15997,10 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
1599715997
};
1599815998
var internals$jscomp$inline_2241 = {
1599915999
bundleType: 0,
16000-
version: "19.1.0-native-fb-77656c55-20250117",
16000+
version: "19.1.0-native-fb-028c8e6c-20250121",
1600116001
rendererPackageName: "react-dom",
1600216002
currentDispatcherRef: ReactSharedInternals,
16003-
reconcilerVersion: "19.1.0-native-fb-77656c55-20250117"
16003+
reconcilerVersion: "19.1.0-native-fb-028c8e6c-20250121"
1600416004
};
1600516005
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
1600616006
var hook$jscomp$inline_2242 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
@@ -16106,4 +16106,4 @@ exports.hydrateRoot = function (container, initialChildren, options) {
1610616106
listenToAllSupportedEvents(container);
1610716107
return new ReactDOMHydrationRoot(initialChildren);
1610816108
};
16109-
exports.version = "19.1.0-native-fb-77656c55-20250117";
16109+
exports.version = "19.1.0-native-fb-028c8e6c-20250121";

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-dom/cjs/ReactDOMClient-profiling.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<eaf039e8e9b58bf6ba6f5080de850b7f>>
10+
* @generated SignedSource<<26c5c9bcaf4f9c963a355c567fee66e7>>
1111
*/
1212

1313
/*
@@ -16617,14 +16617,14 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) {
1661716617
};
1661816618
var isomorphicReactPackageVersion$jscomp$inline_1880 = React.version;
1661916619
if (
16620-
"19.1.0-native-fb-77656c55-20250117" !==
16620+
"19.1.0-native-fb-028c8e6c-20250121" !==
1662116621
isomorphicReactPackageVersion$jscomp$inline_1880
1662216622
)
1662316623
throw Error(
1662416624
formatProdErrorMessage(
1662516625
527,
1662616626
isomorphicReactPackageVersion$jscomp$inline_1880,
16627-
"19.1.0-native-fb-77656c55-20250117"
16627+
"19.1.0-native-fb-028c8e6c-20250121"
1662816628
)
1662916629
);
1663016630
ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
@@ -16646,10 +16646,10 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
1664616646
};
1664716647
var internals$jscomp$inline_1887 = {
1664816648
bundleType: 0,
16649-
version: "19.1.0-native-fb-77656c55-20250117",
16649+
version: "19.1.0-native-fb-028c8e6c-20250121",
1665016650
rendererPackageName: "react-dom",
1665116651
currentDispatcherRef: ReactSharedInternals,
16652-
reconcilerVersion: "19.1.0-native-fb-77656c55-20250117",
16652+
reconcilerVersion: "19.1.0-native-fb-028c8e6c-20250121",
1665316653
getLaneLabelMap: function () {
1665416654
for (
1665516655
var map = new Map(), lane = 1, index$292 = 0;
@@ -16770,4 +16770,4 @@ exports.hydrateRoot = function (container, initialChildren, options) {
1677016770
listenToAllSupportedEvents(container);
1677116771
return new ReactDOMHydrationRoot(initialChildren);
1677216772
};
16773-
exports.version = "19.1.0-native-fb-77656c55-20250117";
16773+
exports.version = "19.1.0-native-fb-028c8e6c-20250121";

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-dom/cjs/ReactDOMProfiling-dev.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<1d626001b01e89794ae9a18ea2988f96>>
10+
* @generated SignedSource<<00a5a33095096e7adddb3fdaeea26c8d>>
1111
*/
1212

1313
/*
@@ -26018,11 +26018,11 @@ __DEV__ &&
2601826018
};
2601926019
(function () {
2602026020
var isomorphicReactPackageVersion = React.version;
26021-
if ("19.1.0-native-fb-77656c55-20250117" !== isomorphicReactPackageVersion)
26021+
if ("19.1.0-native-fb-028c8e6c-20250121" !== isomorphicReactPackageVersion)
2602226022
throw Error(
2602326023
'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' +
2602426024
(isomorphicReactPackageVersion +
26025-
"\n - react-dom: 19.1.0-native-fb-77656c55-20250117\nLearn more: https://react.dev/warnings/version-mismatch")
26025+
"\n - react-dom: 19.1.0-native-fb-028c8e6c-20250121\nLearn more: https://react.dev/warnings/version-mismatch")
2602626026
);
2602726027
})();
2602826028
("function" === typeof Map &&
@@ -26059,10 +26059,10 @@ __DEV__ &&
2605926059
!(function () {
2606026060
var internals = {
2606126061
bundleType: 1,
26062-
version: "19.1.0-native-fb-77656c55-20250117",
26062+
version: "19.1.0-native-fb-028c8e6c-20250121",
2606326063
rendererPackageName: "react-dom",
2606426064
currentDispatcherRef: ReactSharedInternals,
26065-
reconcilerVersion: "19.1.0-native-fb-77656c55-20250117"
26065+
reconcilerVersion: "19.1.0-native-fb-028c8e6c-20250121"
2606626066
};
2606726067
internals.overrideHookState = overrideHookState;
2606826068
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
@@ -26524,7 +26524,7 @@ __DEV__ &&
2652426524
exports.useFormStatus = function () {
2652526525
return resolveDispatcher().useHostTransitionStatus();
2652626526
};
26527-
exports.version = "19.1.0-native-fb-77656c55-20250117";
26527+
exports.version = "19.1.0-native-fb-028c8e6c-20250121";
2652826528
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
2652926529
"function" ===
2653026530
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-dom/cjs/ReactDOMProfiling-prod.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<785be054b88e8ad69ff2ecc5784c72e4>>
10+
* @generated SignedSource<<20122955dd5629d8d1ab88d6929c9020>>
1111
*/
1212

1313
/*
@@ -15979,14 +15979,14 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) {
1597915979
};
1598015980
var isomorphicReactPackageVersion$jscomp$inline_1786 = React.version;
1598115981
if (
15982-
"19.1.0-native-fb-77656c55-20250117" !==
15982+
"19.1.0-native-fb-028c8e6c-20250121" !==
1598315983
isomorphicReactPackageVersion$jscomp$inline_1786
1598415984
)
1598515985
throw Error(
1598615986
formatProdErrorMessage(
1598715987
527,
1598815988
isomorphicReactPackageVersion$jscomp$inline_1786,
15989-
"19.1.0-native-fb-77656c55-20250117"
15989+
"19.1.0-native-fb-028c8e6c-20250121"
1599015990
)
1599115991
);
1599215992
ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
@@ -16008,10 +16008,10 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
1600816008
};
1600916009
var internals$jscomp$inline_2244 = {
1601016010
bundleType: 0,
16011-
version: "19.1.0-native-fb-77656c55-20250117",
16011+
version: "19.1.0-native-fb-028c8e6c-20250121",
1601216012
rendererPackageName: "react-dom",
1601316013
currentDispatcherRef: ReactSharedInternals,
16014-
reconcilerVersion: "19.1.0-native-fb-77656c55-20250117"
16014+
reconcilerVersion: "19.1.0-native-fb-028c8e6c-20250121"
1601516015
};
1601616016
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
1601716017
var hook$jscomp$inline_2245 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
@@ -16271,4 +16271,4 @@ exports.useFormState = function (action, initialState, permalink) {
1627116271
exports.useFormStatus = function () {
1627216272
return ReactSharedInternals.H.useHostTransitionStatus();
1627316273
};
16274-
exports.version = "19.1.0-native-fb-77656c55-20250117";
16274+
exports.version = "19.1.0-native-fb-028c8e6c-20250121";

compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/react-dom/cjs/ReactDOMProfiling-profiling.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @noflow
88
* @nolint
99
* @preventMunge
10-
* @generated SignedSource<<1172ce9471f7bcff3dfedc84f55d15b5>>
10+
* @generated SignedSource<<cf448d1f28418996d1b2d128e2cfb847>>
1111
*/
1212

1313
/*
@@ -16632,14 +16632,14 @@ ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) {
1663216632
};
1663316633
var isomorphicReactPackageVersion$jscomp$inline_1881 = React.version;
1663416634
if (
16635-
"19.1.0-native-fb-77656c55-20250117" !==
16635+
"19.1.0-native-fb-028c8e6c-20250121" !==
1663616636
isomorphicReactPackageVersion$jscomp$inline_1881
1663716637
)
1663816638
throw Error(
1663916639
formatProdErrorMessage(
1664016640
527,
1664116641
isomorphicReactPackageVersion$jscomp$inline_1881,
16642-
"19.1.0-native-fb-77656c55-20250117"
16642+
"19.1.0-native-fb-028c8e6c-20250121"
1664316643
)
1664416644
);
1664516645
ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
@@ -16661,10 +16661,10 @@ ReactDOMSharedInternals.findDOMNode = function (componentOrElement) {
1666116661
};
1666216662
var internals$jscomp$inline_1888 = {
1666316663
bundleType: 0,
16664-
version: "19.1.0-native-fb-77656c55-20250117",
16664+
version: "19.1.0-native-fb-028c8e6c-20250121",
1666516665
rendererPackageName: "react-dom",
1666616666
currentDispatcherRef: ReactSharedInternals,
16667-
reconcilerVersion: "19.1.0-native-fb-77656c55-20250117",
16667+
reconcilerVersion: "19.1.0-native-fb-028c8e6c-20250121",
1666816668
getLaneLabelMap: function () {
1666916669
for (
1667016670
var map = new Map(), lane = 1, index$292 = 0;
@@ -16939,7 +16939,7 @@ exports.useFormState = function (action, initialState, permalink) {
1693916939
exports.useFormStatus = function () {
1694016940
return ReactSharedInternals.H.useHostTransitionStatus();
1694116941
};
16942-
exports.version = "19.1.0-native-fb-77656c55-20250117";
16942+
exports.version = "19.1.0-native-fb-028c8e6c-20250121";
1694316943
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
1694416944
"function" ===
1694516945
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

0 commit comments

Comments
 (0)