Transition: Tiny updates
This commit is contained in:
parent
01cf273b92
commit
c467da8680
@ -1,9 +1,12 @@
|
||||
.Transition {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
> .Transition__slide {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
animation-fill-mode: forwards !important;
|
||||
|
||||
&.from,
|
||||
@ -25,9 +28,6 @@
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
/*
|
||||
* slide
|
||||
*/
|
||||
&.slide-optimized,
|
||||
&.slide-optimized-rtl {
|
||||
contain: strict;
|
||||
@ -40,8 +40,9 @@
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
transition: transform var(--slide-transition);
|
||||
transform: scale(0);
|
||||
|
||||
transition: transform var(--slide-transition);
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,10 +110,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* slide-vertical
|
||||
*/
|
||||
|
||||
&.slide-vertical {
|
||||
> .to {
|
||||
transform: translateY(100%);
|
||||
@ -145,10 +142,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* slide-vertical-fade
|
||||
*/
|
||||
|
||||
&.slide-vertical-fade {
|
||||
> .to {
|
||||
transform: translateY(100%);
|
||||
@ -181,10 +174,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* mv-slide
|
||||
*/
|
||||
|
||||
&.mv-slide {
|
||||
> .Transition__slide > div {
|
||||
animation-fill-mode: forwards !important;
|
||||
@ -221,19 +210,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* slide-fade
|
||||
*/
|
||||
&.slide-fade {
|
||||
> .from {
|
||||
transform-origin: left;
|
||||
transform: translateX(0);
|
||||
transform-origin: left;
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
> .to {
|
||||
transform-origin: left;
|
||||
transform: translateX(1.5rem);
|
||||
transform-origin: left;
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@ -251,39 +239,40 @@
|
||||
&.slide-fade.backwards {
|
||||
> .from {
|
||||
transform: translateX(0);
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
> .to {
|
||||
transform: translateX(-1.5rem);
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&.animating {
|
||||
> .from {
|
||||
animation: fade-in-backwards-opacity var(--slide-transition),
|
||||
slide-fade-in-backwards-move var(--slide-transition);
|
||||
slide-fade-in-backwards-move var(--slide-transition);
|
||||
}
|
||||
|
||||
> .to {
|
||||
animation: fade-out-backwards-opacity var(--slide-transition),
|
||||
slide-fade-out-backwards-move var(--slide-transition);
|
||||
slide-fade-out-backwards-move var(--slide-transition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* zoom-fade
|
||||
*/
|
||||
&.zoom-fade {
|
||||
> .from {
|
||||
transform-origin: center;
|
||||
transform: scale(1);
|
||||
transform-origin: center;
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
> .to {
|
||||
transform-origin: center;
|
||||
|
||||
opacity: 0;
|
||||
// We can omit `transform: scale(1.1);` here because `opacity` is 0.
|
||||
// We need to for proper position calculation in `InfiniteScroll`.
|
||||
@ -320,9 +309,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* fade
|
||||
*/
|
||||
&.fade {
|
||||
> .from {
|
||||
opacity: 1;
|
||||
@ -343,12 +329,49 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* slide-layers
|
||||
*/
|
||||
&.semi-fade {
|
||||
> .Transition__slide {
|
||||
isolation: isolate;
|
||||
}
|
||||
|
||||
> .from {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
> .to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&.animating {
|
||||
> .to {
|
||||
animation: fade-in-opacity 250ms ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.semi-fade.backwards {
|
||||
> .from {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
> .to {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.animating {
|
||||
> .from {
|
||||
animation: fade-in-backwards-opacity 250ms ease;
|
||||
}
|
||||
|
||||
> .to {
|
||||
animation: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.slide-layers {
|
||||
--background-color: var(--color-background);
|
||||
|
||||
background: black !important;
|
||||
|
||||
> .Transition__slide {
|
||||
@ -373,6 +396,7 @@
|
||||
&.slide-layers.backwards {
|
||||
> .to {
|
||||
transform: translateX(-20%);
|
||||
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
@ -387,18 +411,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* push-slide
|
||||
*/
|
||||
|
||||
&.push-slide {
|
||||
> .Transition__slide {
|
||||
background: var(--color-background);
|
||||
}
|
||||
|
||||
> .from {
|
||||
transform-origin: center;
|
||||
transform: scale(1);
|
||||
transform-origin: center;
|
||||
|
||||
opacity: 1;
|
||||
|
||||
.custom-scroll {
|
||||
@ -428,6 +449,7 @@
|
||||
&.push-slide.backwards {
|
||||
> .to {
|
||||
transform: scale(0.7);
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@ -442,9 +464,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* slide-fade
|
||||
*/
|
||||
&.reveal {
|
||||
> .to {
|
||||
clip-path: inset(0 100% 0 0);
|
||||
@ -478,9 +497,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* common
|
||||
*/
|
||||
@keyframes fade-in-opacity {
|
||||
0% {
|
||||
opacity: 0;
|
||||
@ -517,9 +533,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* slide
|
||||
*/
|
||||
@keyframes slide-in {
|
||||
0% {
|
||||
transform: translateX(100%);
|
||||
@ -556,9 +569,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* slide-vertical
|
||||
*/
|
||||
@keyframes slide-vertical-in {
|
||||
0% {
|
||||
transform: translateY(100%);
|
||||
@ -595,17 +605,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* slide-vertical-fade
|
||||
*/
|
||||
|
||||
@keyframes slide-vertical-fade-in {
|
||||
0% {
|
||||
transform: translateY(100%);
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@ -613,10 +621,12 @@
|
||||
@keyframes slide-vertical-fade-out {
|
||||
0% {
|
||||
transform: translateY(0);
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(-100%);
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@ -624,10 +634,12 @@
|
||||
@keyframes slide-vertical-fade-in-backwards {
|
||||
0% {
|
||||
transform: translateY(0);
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(100%);
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@ -635,18 +647,16 @@
|
||||
@keyframes slide-vertical-fade-out-backwards {
|
||||
0% {
|
||||
transform: translateY(-100%);
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* mv-slide
|
||||
*/
|
||||
@keyframes mv-slide-in {
|
||||
0% {
|
||||
transform: translateX(100vw);
|
||||
@ -683,9 +693,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* slide-fade
|
||||
*/
|
||||
@keyframes slide-fade-in-move {
|
||||
0% {
|
||||
transform: translateX(1.5rem);
|
||||
@ -722,9 +729,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* zoom-fade
|
||||
*/
|
||||
@keyframes zoom-fade-in-move {
|
||||
0% {
|
||||
transform: scale(1.1);
|
||||
@ -752,16 +756,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* slide-layers
|
||||
*/
|
||||
@keyframes slide-layers-out {
|
||||
0% {
|
||||
transform: translateX(0);
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: translateX(-20%);
|
||||
|
||||
opacity: calc(1 - var(--layer-blackout-opacity));
|
||||
}
|
||||
}
|
||||
@ -769,25 +772,25 @@
|
||||
@keyframes slide-layers-out-backwards {
|
||||
0% {
|
||||
transform: translateX(-20%);
|
||||
|
||||
opacity: calc(1 - var(--layer-blackout-opacity));
|
||||
}
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* push-slide
|
||||
*/
|
||||
|
||||
@keyframes push-out {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: scale(0.7);
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@ -795,17 +798,16 @@
|
||||
@keyframes push-out-backwards {
|
||||
0% {
|
||||
transform: scale(0.7);
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* slide
|
||||
*/
|
||||
@keyframes slide-in-200 {
|
||||
0% {
|
||||
transform: translateX(200%);
|
||||
@ -824,9 +826,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* slide
|
||||
*/
|
||||
@keyframes reveal-in {
|
||||
0% {
|
||||
clip-path: inset(0 100% 0 0);
|
||||
@ -836,9 +835,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* slide
|
||||
*/
|
||||
@keyframes reveal-in-backwards {
|
||||
0% {
|
||||
clip-path: inset(0 0 0 0);
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import type { RefObject } from 'react';
|
||||
import type { FC } from '../../lib/teact/teact';
|
||||
import React, { useLayoutEffect, useRef } from '../../lib/teact/teact';
|
||||
import { addExtraClass, removeExtraClass, toggleExtraClass } from '../../lib/teact/teact-dom';
|
||||
import { getGlobal } from '../../global';
|
||||
@ -19,10 +18,11 @@ export type ChildrenFn = (isActive: boolean, isFrom: boolean, currentKey: number
|
||||
export type TransitionProps = {
|
||||
ref?: RefObject<HTMLDivElement>;
|
||||
activeKey: number;
|
||||
nextKey?: number;
|
||||
name: (
|
||||
'none' | 'slide' | 'slide-rtl' | 'mv-slide' | 'slide-fade' | 'zoom-fade' | 'slide-layers'
|
||||
| 'fade' | 'push-slide' | 'reveal' | 'slide-optimized' | 'slide-optimized-rtl' | 'slide-vertical'
|
||||
| 'slide-vertical-fade'
|
||||
| 'fade' | 'push-slide' | 'reveal' | 'slide-optimized' | 'slide-optimized-rtl' | 'semi-fade'
|
||||
| 'slide-vertical' | 'slide-vertical-fade'
|
||||
);
|
||||
direction?: 'auto' | 'inverse' | 1 | -1;
|
||||
renderCount?: number;
|
||||
@ -32,9 +32,9 @@ export type TransitionProps = {
|
||||
// Used by async components which are usually remounted during first animation
|
||||
shouldWrap?: boolean;
|
||||
wrapExceptionKey?: number;
|
||||
isDisabled?: boolean;
|
||||
id?: string;
|
||||
className?: string;
|
||||
slideClassName?: string;
|
||||
onStart?: NoneToVoidFunction;
|
||||
onStop?: NoneToVoidFunction;
|
||||
children: React.ReactNode | ChildrenFn;
|
||||
@ -48,9 +48,10 @@ const CLASSES = {
|
||||
afterSlides: 'Transition__after-slides',
|
||||
};
|
||||
|
||||
const Transition: FC<TransitionProps> = ({
|
||||
function Transition({
|
||||
ref,
|
||||
activeKey,
|
||||
nextKey,
|
||||
name,
|
||||
direction = 'auto',
|
||||
renderCount,
|
||||
@ -61,11 +62,12 @@ const Transition: FC<TransitionProps> = ({
|
||||
wrapExceptionKey,
|
||||
id,
|
||||
className,
|
||||
slideClassName,
|
||||
onStart,
|
||||
onStop,
|
||||
children,
|
||||
afterChildren,
|
||||
}) => {
|
||||
}: TransitionProps) {
|
||||
// No need for a container to update on change
|
||||
const { animationLevel } = getGlobal().settings.byKey;
|
||||
const currentKeyRef = useRef<number>();
|
||||
@ -87,6 +89,9 @@ const Transition: FC<TransitionProps> = ({
|
||||
}
|
||||
|
||||
rendersRef.current[activeKey] = children;
|
||||
if (nextKey) {
|
||||
rendersRef.current[nextKey] = children;
|
||||
}
|
||||
|
||||
useLayoutEffect(() => {
|
||||
function cleanup() {
|
||||
@ -102,30 +107,38 @@ const Transition: FC<TransitionProps> = ({
|
||||
}
|
||||
|
||||
const container = containerRef.current!;
|
||||
const childElements = (Array.from(container.children) as HTMLElement[])
|
||||
.filter((el) => !el.classList.contains(CLASSES.afterSlides));
|
||||
|
||||
childElements.forEach((el) => {
|
||||
addExtraClass(el, CLASSES.slide);
|
||||
});
|
||||
|
||||
if (childElements.length === 1 && !activeKeyChanged) {
|
||||
const firstChild = childElements[0];
|
||||
|
||||
if (name.startsWith('slide-optimized')) {
|
||||
firstChild.style.transition = 'none';
|
||||
firstChild.style.transform = 'translate3d(0, 0, 0)';
|
||||
}
|
||||
|
||||
addExtraClass(firstChild, CLASSES.active);
|
||||
|
||||
return;
|
||||
}
|
||||
const keys = Object.keys(rendersRef.current).map(Number);
|
||||
const prevActiveIndex = renderCount ? prevActiveKey : keys.indexOf(prevActiveKey);
|
||||
const activeIndex = renderCount ? activeKey : keys.indexOf(activeKey);
|
||||
|
||||
const childNodes = Array.from(container.childNodes)
|
||||
.filter((el) => !(el instanceof HTMLElement && el.classList.contains(CLASSES.afterSlides)));
|
||||
if (!childNodes.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const childElements = (Array.from(container.children) as HTMLElement[])
|
||||
.filter((el) => !el.classList.contains(CLASSES.afterSlides));
|
||||
childElements.forEach((el) => {
|
||||
addExtraClass(el, CLASSES.slide);
|
||||
|
||||
if (slideClassName) {
|
||||
addExtraClass(el, slideClassName);
|
||||
}
|
||||
});
|
||||
|
||||
if (!activeKeyChanged) {
|
||||
if (childElements.length === 1 || (nextKey !== undefined && childElements.length === 2)) {
|
||||
const firstChild = childNodes[activeIndex] as HTMLElement;
|
||||
|
||||
if (name.startsWith('slide-optimized')) {
|
||||
firstChild.style.transition = 'none';
|
||||
firstChild.style.transform = 'translate3d(0, 0, 0)';
|
||||
}
|
||||
|
||||
addExtraClass(firstChild, CLASSES.active);
|
||||
}
|
||||
|
||||
if (!activeKeyChanged || !childNodes.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -137,10 +150,6 @@ const Transition: FC<TransitionProps> = ({
|
||||
|| (direction === 'inverse' && prevActiveKey < activeKey)
|
||||
);
|
||||
|
||||
const keys = Object.keys(rendersRef.current).map(Number);
|
||||
const prevActiveIndex = renderCount ? prevActiveKey : keys.indexOf(prevActiveKey);
|
||||
const activeIndex = renderCount ? activeKey : keys.indexOf(activeKey);
|
||||
|
||||
if (name === 'slide-optimized' || name === 'slide-optimized-rtl') {
|
||||
performSlideOptimized(
|
||||
animationLevel,
|
||||
@ -243,6 +252,7 @@ const Transition: FC<TransitionProps> = ({
|
||||
});
|
||||
}, [
|
||||
activeKey,
|
||||
nextKey,
|
||||
prevActiveKey,
|
||||
activeKeyChanged,
|
||||
direction,
|
||||
@ -252,6 +262,7 @@ const Transition: FC<TransitionProps> = ({
|
||||
renderCount,
|
||||
shouldRestoreHeight,
|
||||
shouldCleanup,
|
||||
slideClassName,
|
||||
cleanupExceptionKey,
|
||||
animationLevel,
|
||||
forceUpdate,
|
||||
@ -307,7 +318,7 @@ const Transition: FC<TransitionProps> = ({
|
||||
{contents}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export default Transition;
|
||||
|
||||
|
||||
@ -700,7 +700,18 @@ function updateClassName(element: HTMLElement, value: string) {
|
||||
element.className = extraArray.join(' ');
|
||||
}
|
||||
|
||||
export function addExtraClass(element: HTMLElement, className: string) {
|
||||
export function addExtraClass(element: HTMLElement, className: string, forceSingle = false) {
|
||||
if (!forceSingle) {
|
||||
const classNames = className.split(' ');
|
||||
if (className.length > 1) {
|
||||
classNames.forEach((cn) => {
|
||||
addExtraClass(element, cn, true);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
element.classList.add(className);
|
||||
|
||||
const classList = extraClasses.get(element);
|
||||
@ -711,7 +722,18 @@ export function addExtraClass(element: HTMLElement, className: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export function removeExtraClass(element: HTMLElement, className: string) {
|
||||
export function removeExtraClass(element: HTMLElement, className: string, forceSingle = false) {
|
||||
if (!forceSingle) {
|
||||
const classNames = className.split(' ');
|
||||
if (className.length > 1) {
|
||||
classNames.forEach((cn) => {
|
||||
removeExtraClass(element, cn, true);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
element.classList.remove(className);
|
||||
|
||||
const classList = extraClasses.get(element);
|
||||
@ -724,7 +746,18 @@ export function removeExtraClass(element: HTMLElement, className: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export function toggleExtraClass(element: HTMLElement, className: string, force?: boolean) {
|
||||
export function toggleExtraClass(element: HTMLElement, className: string, force?: boolean, forceSingle = false) {
|
||||
if (!forceSingle) {
|
||||
const classNames = className.split(' ');
|
||||
if (className.length > 1) {
|
||||
classNames.forEach((cn) => {
|
||||
toggleExtraClass(element, cn, force, true);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
element.classList.toggle(className, force);
|
||||
|
||||
if (element.classList.contains(className)) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user