import type {ReactNodeList} from 'shared/ReactTypes';
import type {FiberRoot} from './ReactInternalTypes';
import type {ViewTransitionInstance} from './ReactFiberConfig';
import {
getWorkInProgressRoot,
getPendingTransitionTypes,
} from './ReactFiberWorkLoop';
import {getIsHydrating} from './ReactFiberHydrationContext';
import {getTreeId} from './ReactFiberTreeContext';
export type ViewTransitionClassPerType = {
[transitionType: 'default' | string]: 'none' | string,
};
export type ViewTransitionClass = 'none' | string | ViewTransitionClassPerType;
export type ViewTransitionProps = {
name?: string,
children?: ReactNodeList,
className?: ViewTransitionClass,
enter?: ViewTransitionClass,
exit?: ViewTransitionClass,
layout?: ViewTransitionClass,
share?: ViewTransitionClass,
update?: ViewTransitionClass,
onEnter?: (instance: ViewTransitionInstance, types: Array<string>) => void,
onExit?: (instance: ViewTransitionInstance, types: Array<string>) => void,
onLayout?: (instance: ViewTransitionInstance, types: Array<string>) => void,
onShare?: (instance: ViewTransitionInstance, types: Array<string>) => void,
onUpdate?: (instance: ViewTransitionInstance, types: Array<string>) => void,
};
export type ViewTransitionState = {
autoName: null | string,
paired: null | ViewTransitionState,
ref: null | ViewTransitionInstance,
};
let globalClientIdCounter: number = 0;
export function assignViewTransitionAutoName(
props: ViewTransitionProps,
instance: ViewTransitionState,
): string {
if (instance.autoName !== null) {
return instance.autoName;
}
const root = ((getWorkInProgressRoot(): any): FiberRoot);
const identifierPrefix = root.identifierPrefix;
let name;
if (getIsHydrating()) {
const treeId = getTreeId();
name = '\u00AB' + identifierPrefix + 'T' + treeId + '\u00BB';
} else {
const globalClientId = globalClientIdCounter++;
name =
'\u00AB' +
identifierPrefix +
't' +
globalClientId.toString(32) +
'\u00BB';
}
instance.autoName = name;
return name;
}
export function getViewTransitionName(
props: ViewTransitionProps,
instance: ViewTransitionState,
): string {
if (props.name != null && props.name !== 'auto') {
return props.name;
}
return (instance.autoName: any);
}
function getClassNameByType(classByType: ?ViewTransitionClass): ?string {
if (classByType == null || typeof classByType === 'string') {
return classByType;
}
let className: ?string = null;
const activeTypes = getPendingTransitionTypes();
if (activeTypes !== null) {
for (let i = 0; i < activeTypes.length; i++) {
const match = classByType[activeTypes[i]];
if (match != null) {
if (match === 'none') {
return 'none';
}
if (className == null) {
className = match;
} else {
className += ' ' + match;
}
}
}
}
if (className == null) {
return classByType.default;
}
return className;
}
export function getViewTransitionClassName(
defaultClass: ?ViewTransitionClass,
eventClass: ?ViewTransitionClass,
): ?string {
const className: ?string = getClassNameByType(defaultClass);
const eventClassName: ?string = getClassNameByType(eventClass);
if (eventClassName == null) {
return className;
}
if (eventClassName === 'none') {
return eventClassName;
}
if (className != null && className !== 'none') {
return className + ' ' + eventClassName;
}
return eventClassName;
}