From 392b2d53cbc45a74e9975161a7085cf7963e6885 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Wed, 5 Jul 2023 13:16:11 +0200 Subject: [PATCH] Teact: Introduce `setExtraStyles` --- src/components/ui/Transition.tsx | 70 ++++++++++++++++++++------------ src/lib/teact/teact-dom.ts | 36 +++++++++++++++- src/lib/teact/teact.ts | 7 +++- 3 files changed, 85 insertions(+), 28 deletions(-) diff --git a/src/components/ui/Transition.tsx b/src/components/ui/Transition.tsx index 09c73713b..1d92d427f 100644 --- a/src/components/ui/Transition.tsx +++ b/src/components/ui/Transition.tsx @@ -1,7 +1,9 @@ import type { RefObject } from 'react'; import React, { useEffect, useLayoutEffect, useRef } from '../../lib/teact/teact'; -import { addExtraClass, removeExtraClass, toggleExtraClass } from '../../lib/teact/teact-dom'; -import { requestMutation, requestForcedReflow } from '../../lib/fasterdom/fasterdom'; +import { + addExtraClass, removeExtraClass, setExtraStyles, toggleExtraClass, +} from '../../lib/teact/teact-dom'; +import { requestForcedReflow, requestMutation } from '../../lib/fasterdom/fasterdom'; import { getGlobal } from '../../global'; @@ -146,8 +148,10 @@ function Transition({ addExtraClass(activeChild, CLASSES.active); if (isSlideOptimized) { - activeChild.style.transition = 'none'; - activeChild.style.transform = 'translate3d(0, 0, 0)'; + setExtraStyles(activeChild, { + transition: 'none', + transform: 'translate3d(0, 0, 0)', + }); } } @@ -233,8 +237,8 @@ function Transition({ if (shouldRestoreHeight) { if (activeElement) { - activeElement.style.height = 'auto'; - container.style.height = `${clientHeight}px`; + setExtraStyles(activeElement, { height: 'auto' }); + setExtraStyles(container, { height: `${clientHeight}px` }); } } @@ -290,9 +294,11 @@ function Transition({ } requestMutation(() => { - activeElement.style.height = 'auto'; - container.style.height = `${clientHeight}px`; - container.style.flexBasis = `${clientHeight}px`; + setExtraStyles(activeElement, { height: 'auto' }); + setExtraStyles(container, { + height: `${clientHeight}px`, + flexBasis: `${clientHeight}px`, + }); }); }, [shouldRestoreHeight, children]); @@ -347,15 +353,19 @@ function performSlideOptimized( toggleExtraClass(container, `Transition-${name}Backwards`, isBackwards); if (fromSlide instanceof HTMLElement) { - fromSlide.style.transition = 'none'; - fromSlide.style.transform = ''; removeExtraClass(fromSlide, CLASSES.active); + setExtraStyles(fromSlide, { + transition: 'none', + transform: '', + }); } if (toSlide instanceof HTMLElement) { - toSlide.style.transition = 'none'; - toSlide.style.transform = 'translate3d(0, 0, 0)'; addExtraClass(toSlide, CLASSES.active); + setExtraStyles(toSlide, { + transition: 'none', + transform: 'translate3d(0, 0, 0)', + }); } cleanup(); @@ -375,13 +385,17 @@ function performSlideOptimized( toggleExtraClass(container, `Transition-${name}Backwards`, isBackwards); if (fromSlide instanceof HTMLElement) { - fromSlide.style.transition = 'none'; - fromSlide.style.transform = 'translate3d(0, 0, 0)'; + setExtraStyles(fromSlide, { + transition: 'none', + transform: 'translate3d(0, 0, 0)', + }); } if (toSlide instanceof HTMLElement) { - toSlide.style.transition = 'none'; - toSlide.style.transform = `translate3d(${isBackwards ? '-' : ''}100%, 0, 0)`; + setExtraStyles(toSlide, { + transition: 'none', + transform: `translate3d(${isBackwards ? '-' : ''}100%, 0, 0)`, + }); } requestForcedReflow(() => { @@ -391,15 +405,19 @@ function performSlideOptimized( return () => { if (fromSlide instanceof HTMLElement) { - fromSlide.style.transition = ''; - fromSlide.style.transform = `translate3d(${isBackwards ? '' : '-'}100%, 0, 0)`; removeExtraClass(fromSlide, CLASSES.active); + setExtraStyles(fromSlide, { + transition: '', + transform: `translate3d(${isBackwards ? '' : '-'}100%, 0, 0)`, + }); } if (toSlide instanceof HTMLElement) { - toSlide.style.transition = ''; - toSlide.style.transform = 'translate3d(0, 0, 0)'; addExtraClass(toSlide, CLASSES.active); + setExtraStyles(toSlide, { + transition: '', + transform: 'translate3d(0, 0, 0)', + }); } }; }); @@ -413,13 +431,15 @@ function performSlideOptimized( } if (fromSlide instanceof HTMLElement) { - fromSlide.style.transition = 'none'; - fromSlide.style.transform = ''; + setExtraStyles(fromSlide, { + transition: 'none', + transform: '', + }); } if (shouldRestoreHeight && clientHeight && toSlide instanceof HTMLElement) { - toSlide.style.height = 'auto'; - container.style.height = `${clientHeight}px`; + setExtraStyles(toSlide, { height: 'auto' }); + setExtraStyles(container, { height: `${clientHeight}px` }); } onStop?.(); diff --git a/src/lib/teact/teact-dom.ts b/src/lib/teact/teact-dom.ts index 0d3a67677..be1327346 100644 --- a/src/lib/teact/teact-dom.ts +++ b/src/lib/teact/teact-dom.ts @@ -46,6 +46,7 @@ const INDEX_KEY_PREFIX = '__indexKey#'; const headsByElement = new WeakMap(); const extraClasses = new WeakMap>(); +const extraStyles = new WeakMap>(); // eslint-disable-next-line @typescript-eslint/naming-convention let DEBUG_virtualTreeSize = 1; @@ -669,7 +670,7 @@ function setAttribute(element: HTMLElement, key: string, value: any) { } } } else if (key === 'style') { - element.style.cssText = value; + updateStyle(element, value); } else if (key === 'dangerouslySetInnerHTML') { // eslint-disable-next-line no-underscore-dangle element.innerHTML = value.__html; @@ -688,7 +689,7 @@ function removeAttribute(element: HTMLElement, key: string, value: any) { } else if (key === 'value') { (element as HTMLInputElement).value = ''; } else if (key === 'style') { - element.style.cssText = ''; + updateStyle(element, ''); } else if (key === 'dangerouslySetInnerHTML') { element.innerHTML = ''; } else if (key.startsWith('on')) { @@ -713,6 +714,15 @@ function updateClassName(element: HTMLElement, value: string) { element.className = extraArray.join(' '); } +function updateStyle(element: HTMLElement, value: string) { + element.style.cssText = value; + + const extraObject = extraStyles.get(element); + if (extraObject) { + applyExtraStyles(element); + } +} + export function addExtraClass(element: Element, className: string, forceSingle = false) { if (!forceSingle) { const classNames = className.split(' '); @@ -780,6 +790,28 @@ export function toggleExtraClass(element: Element, className: string, force?: bo } } +export function setExtraStyles(element: HTMLElement, styles: Partial & AnyLiteral) { + extraStyles.set(element, styles); + applyExtraStyles(element); +} + +function applyExtraStyles(element: HTMLElement) { + const standardStyles = Object.entries(extraStyles.get(element)!).reduce>( + (acc, [prop, value]) => { + if (prop.startsWith('--')) { + element.style.setProperty(prop, value); + } else { + acc[prop] = value; + } + + return acc; + }, + {}, + ); + + Object.assign(element.style, standardStyles); +} + // eslint-disable-next-line @typescript-eslint/naming-convention function DEBUG_addToVirtualTreeSize($current: VirtualElementParent | VirtualDomHead) { DEBUG_virtualTreeSize += $current.children.length; diff --git a/src/lib/teact/teact.ts b/src/lib/teact/teact.ts index e4a04cc0d..6c3ac85bd 100644 --- a/src/lib/teact/teact.ts +++ b/src/lib/teact/teact.ts @@ -745,7 +745,12 @@ function useEffectBase( }; function setupSignals() { - const cleanups = dependencies?.filter(isSignal).map((signal) => signal.subscribe(() => { + const cleanups = dependencies?.filter(isSignal).map((signal, i) => signal.subscribe(() => { + if (debugKey) { + // eslint-disable-next-line no-console + console.log(`[Teact] Effect "${debugKey}" caused by signal #${i} new value:`, signal()); + } + byCursor[cursor].schedule(); }));