improve code

This commit is contained in:
Rene
2021-03-30 22:36:18 +02:00
parent fd09d377eb
commit 2fc3a2fb1d
5 changed files with 89 additions and 77 deletions
@@ -124,7 +124,7 @@ const createEnvironment = (): Environment => {
const onChangedListener: Set<OnEnvironmentChanged> = new Set(); const onChangedListener: Set<OnEnvironmentChanged> = new Set();
const nativeScrollbarSize = getNativeScrollbarSize(body, envElm); const nativeScrollbarSize = getNativeScrollbarSize(body, envElm);
const nativeScrollbarStyling = false; //getNativeScrollbarStyling(envElm); TODO: Re - enable; const nativeScrollbarStyling = false; //getNativeScrollbarStyling(envElm); //TODO: Re - enable;
const nativeScrollbarIsOverlaid = { const nativeScrollbarIsOverlaid = {
x: nativeScrollbarSize.x === 0, x: nativeScrollbarSize.x === 0,
y: nativeScrollbarSize.y === 0, y: nativeScrollbarSize.y === 0,
@@ -22,12 +22,12 @@ import { OverflowBehavior } from 'options';
import { StyleObject } from 'typings'; import { StyleObject } from 'typings';
import { classNameViewportScrollbarStyling } from 'classnames'; import { classNameViewportScrollbarStyling } from 'classnames';
const overlaidScrollbarsHideOffset = 42;
const overlaidScrollbarsHideBorderStyle = `${overlaidScrollbarsHideOffset}px solid transparent`;
interface ContentScrollSizeCacheContext { interface ContentScrollSizeCacheContext {
_viewportSize: WH<number>; _viewportRect: DOMRect;
_viewportOffsetSize: WH<number>;
_viewportScrollSize: WH<number>; _viewportScrollSize: WH<number>;
} }
interface OverflowAmountCacheContext { interface OverflowAmountCacheContext {
_contentScrollSize: WH<number>; _contentScrollSize: WH<number>;
_viewportSize: WH<number>; _viewportSize: WH<number>;
@@ -36,7 +36,6 @@ interface OverflowAmountCacheContext {
interface ViewportOverflowState { interface ViewportOverflowState {
_scrollbarsHideOffset: XY<number>; _scrollbarsHideOffset: XY<number>;
_overflowScroll: XY<boolean>; _overflowScroll: XY<boolean>;
_overlaidHideOffset: number;
} }
interface OverflowOption { interface OverflowOption {
@@ -44,6 +43,9 @@ interface OverflowOption {
y: OverflowBehavior; y: OverflowBehavior;
} }
const overlaidScrollbarsHideOffset = 42;
const overlaidScrollbarsHideBorderStyle = `${overlaidScrollbarsHideOffset}px solid transparent`;
export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle => { export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle => {
const { _structureSetup, _getPaddingStyle } = lifecycleHub; const { _structureSetup, _getPaddingStyle } = lifecycleHub;
const { _host, _padding, _viewport, _content, _contentArrange } = _structureSetup._targetObj; const { _host, _padding, _viewport, _content, _contentArrange } = _structureSetup._targetObj;
@@ -52,10 +54,9 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
ContentScrollSizeCacheContext ContentScrollSizeCacheContext
>( >(
(ctx) => { (ctx) => {
const { _viewportSize, _viewportScrollSize } = ctx; const { _viewportOffsetSize, _viewportScrollSize, _viewportRect } = ctx;
const contentViewportScrollSize = scrollSize(_content || _viewport); const contentViewportScrollSize = _content ? scrollSize(_content) : _viewportScrollSize;
return fixScrollSizeRounding(contentViewportScrollSize, _viewportOffsetSize, _viewportRect);
return _content ? fixScrollSizeRounding(contentViewportScrollSize, _viewportSize, _viewportScrollSize) : contentViewportScrollSize;
}, },
{ _equal: equalWH } { _equal: equalWH }
); );
@@ -67,22 +68,10 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
{ _equal: equalXY, _initialValue: { x: 0, y: 0 } } { _equal: equalXY, _initialValue: { x: 0, y: 0 } }
); );
const fixScrollSizeRounding = (contentScrollSize: WH<number>, viewportSize: WH<number>, viewportScrollSize: WH<number>): WH<number> => { const fixScrollSizeRounding = (scrollSize: WH<number>, viewportOffsetSize: WH<number>, viewportRect: DOMRect): WH<number> => ({
const equalViewportSizes = viewportSize.w === viewportScrollSize.w || viewportSize.h === viewportScrollSize.h; w: scrollSize.w - Math.ceil(Math.max(0, viewportRect.width - viewportOffsetSize.w)),
const contentViewportScrollSizeOverflow = contentScrollSize.w > viewportScrollSize.w || contentScrollSize.h > viewportScrollSize.h; h: scrollSize.h - Math.ceil(Math.max(0, viewportRect.height - viewportOffsetSize.h)),
});
if (equalViewportSizes && contentViewportScrollSizeOverflow) {
const viewportRect = getBoundingClientRect(_viewport);
const viewportOffsetSize = offsetSize(_viewport);
return {
w: contentScrollSize.w - Math.ceil(Math.max(0, viewportRect.width - viewportOffsetSize.w)),
h: contentScrollSize.h - Math.ceil(Math.max(0, viewportRect.height - viewportOffsetSize.h)),
};
}
return contentScrollSize;
};
const fixFlexboxGlue = (viewportOverflowState: ViewportOverflowState, heightIntrinsic: boolean) => { const fixFlexboxGlue = (viewportOverflowState: ViewportOverflowState, heightIntrinsic: boolean) => {
const offsetLeft = scrollLeft(_viewport); const offsetLeft = scrollLeft(_viewport);
@@ -95,6 +84,8 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
if (heightIntrinsic) { if (heightIntrinsic) {
const { _overflowScroll, _scrollbarsHideOffset } = viewportOverflowState; const { _overflowScroll, _scrollbarsHideOffset } = viewportOverflowState;
const hostBCR = getBoundingClientRect(_host); const hostBCR = getBoundingClientRect(_host);
// TODO: change to offset size - client size calculation.
const border = topRightBottomLeft(_host, 'border', 'width'); const border = topRightBottomLeft(_host, 'border', 'width');
style(_viewport, { style(_viewport, {
@@ -110,20 +101,19 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
const { _nativeScrollbarSize, _nativeScrollbarIsOverlaid, _nativeScrollbarStyling } = getEnvironment(); const { _nativeScrollbarSize, _nativeScrollbarIsOverlaid, _nativeScrollbarStyling } = getEnvironment();
const { x: overlaidX, y: overlaidY } = _nativeScrollbarIsOverlaid; const { x: overlaidX, y: overlaidY } = _nativeScrollbarIsOverlaid;
const determineOverflow = !viewportStyleObj; const determineOverflow = !viewportStyleObj;
const overlaidHideOffset = _content && !_nativeScrollbarStyling && !showNativeOverlaidScrollbars ? overlaidScrollbarsHideOffset : 0; const arrangeHideOffset = _content && !_nativeScrollbarStyling && !showNativeOverlaidScrollbars ? overlaidScrollbarsHideOffset : 0;
const scroll = { const scroll = {
x: (determineOverflow ? style(_viewport, 'overflow-x') : viewportStyleObj!.overflowX) === 'scroll', x: (determineOverflow ? style(_viewport, 'overflow-x') : viewportStyleObj!.overflowX) === 'scroll',
y: (determineOverflow ? style(_viewport, 'overflow-y') : viewportStyleObj!.overflowY) === 'scroll', y: (determineOverflow ? style(_viewport, 'overflow-y') : viewportStyleObj!.overflowY) === 'scroll',
}; };
const scrollbarsHideOffset = { const scrollbarsHideOffset = {
x: scroll.x && !_nativeScrollbarStyling ? (overlaidX ? overlaidHideOffset : _nativeScrollbarSize.x) : 0, x: scroll.x && !_nativeScrollbarStyling ? (overlaidX ? arrangeHideOffset : _nativeScrollbarSize.x) : 0,
y: scroll.y && !_nativeScrollbarStyling ? (overlaidY ? overlaidHideOffset : _nativeScrollbarSize.y) : 0, y: scroll.y && !_nativeScrollbarStyling ? (overlaidY ? arrangeHideOffset : _nativeScrollbarSize.y) : 0,
}; };
return { return {
_overflowScroll: scroll, _overflowScroll: scroll,
_scrollbarsHideOffset: scrollbarsHideOffset, _scrollbarsHideOffset: scrollbarsHideOffset,
_overlaidHideOffset: overlaidHideOffset,
}; };
}; };
@@ -162,39 +152,45 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
return getViewportOverflowState(showNativeOverlaidScrollbars, viewportStyleObj); return getViewportOverflowState(showNativeOverlaidScrollbars, viewportStyleObj);
}; };
const setContentArrange = (viewportOverflowState: ViewportOverflowState, contentScrollSize: WH<number>, showNativeOverlaidScrollbars: boolean) => { const setContentArrange = (
const { _overflowScroll, _overlaidHideOffset } = viewportOverflowState; viewportOverflowState: ViewportOverflowState,
contentScrollSize: WH<number>,
directionIsRTL: boolean,
contentStyleObj?: StyleObject
) => {
const { _scrollbarsHideOffset } = viewportOverflowState;
const { x: hideOffsetX, y: hideOffsetY } = _scrollbarsHideOffset;
const horizontalBorderKey = directionIsRTL ? 'borderLeft' : 'borderRight';
if (_contentArrange && contentStyleObj) {
// horizontal
contentStyleObj[horizontalBorderKey] = hideOffsetY ? overlaidScrollbarsHideBorderStyle : '';
// vertical
contentStyleObj.borderBottom = hideOffsetX ? overlaidScrollbarsHideBorderStyle : '';
}
// adjust content arrange (content arrange doesn't exist if its not needed) // adjust content arrange (content arrange doesn't exist if its not needed)
style(_contentArrange, { style(_contentArrange, {
width: _overflowScroll.y && !showNativeOverlaidScrollbars ? _overlaidHideOffset + contentScrollSize.w : '', width: hideOffsetY ? hideOffsetY + contentScrollSize.w : '',
height: _overflowScroll.x && !showNativeOverlaidScrollbars ? _overlaidHideOffset + contentScrollSize.h : '', height: hideOffsetX ? hideOffsetX + contentScrollSize.h : '',
}); });
}; };
const hideNativeScrollbars = ( const hideNativeScrollbars = (viewportOverflowState: ViewportOverflowState, directionIsRTL: boolean, viewportStyleObj: StyleObject) => {
viewportOverflowState: ViewportOverflowState, const { _nativeScrollbarStyling } = getEnvironment();
directionIsRTL: boolean, const { _overflowScroll, _scrollbarsHideOffset } = viewportOverflowState;
viewportStyleObj: StyleObject,
contentStyleObj: StyleObject
) => {
const { _nativeScrollbarIsOverlaid, _nativeScrollbarStyling } = getEnvironment();
const { _overflowScroll, _scrollbarsHideOffset, _overlaidHideOffset } = viewportOverflowState;
const { x: scrollX, y: scrollY } = _overflowScroll; const { x: scrollX, y: scrollY } = _overflowScroll;
const { x: overlaidX, y: overlaidY } = _nativeScrollbarIsOverlaid;
const paddingStyle = _getPaddingStyle(); const paddingStyle = _getPaddingStyle();
const horizontalMarginKey = directionIsRTL ? 'marginLeft' : 'marginRight'; const horizontalMarginKey = directionIsRTL ? 'marginLeft' : 'marginRight';
const horizontalBorderKey = directionIsRTL ? 'borderLeft' : 'borderRight';
const horizontalPaddingValue = paddingStyle[horizontalMarginKey] as number; const horizontalPaddingValue = paddingStyle[horizontalMarginKey] as number;
// vertical
viewportStyleObj.marginBottom = -_scrollbarsHideOffset.x + (paddingStyle.marginBottom as number);
contentStyleObj.borderBottom = scrollX && overlaidX && _overlaidHideOffset ? overlaidScrollbarsHideBorderStyle : '';
// horizontal // horizontal
viewportStyleObj.maxWidth = `calc(100% + ${_scrollbarsHideOffset.y + horizontalPaddingValue * -1}px)`; viewportStyleObj.maxWidth = `calc(100% + ${_scrollbarsHideOffset.y + horizontalPaddingValue * -1}px)`;
viewportStyleObj[horizontalMarginKey] = -_scrollbarsHideOffset.y + horizontalPaddingValue; viewportStyleObj[horizontalMarginKey] = -_scrollbarsHideOffset.y + horizontalPaddingValue;
contentStyleObj[horizontalBorderKey] = scrollY && overlaidY && _overlaidHideOffset ? overlaidScrollbarsHideBorderStyle : '';
// vertical
viewportStyleObj.marginBottom = -_scrollbarsHideOffset.x + (paddingStyle.marginBottom as number);
// hide overflowing scrollbars if there are any // hide overflowing scrollbars if there are any
if (!_nativeScrollbarStyling) { if (!_nativeScrollbarStyling) {
@@ -208,6 +204,7 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
const { _directionIsRTL, _heightIntrinsic, _sizeChanged, _hostMutation, _contentMutation, _paddingStyleChanged } = updateHints; const { _directionIsRTL, _heightIntrinsic, _sizeChanged, _hostMutation, _contentMutation, _paddingStyleChanged } = updateHints;
const { _flexboxGlue, _nativeScrollbarStyling, _nativeScrollbarIsOverlaid } = getEnvironment(); const { _flexboxGlue, _nativeScrollbarStyling, _nativeScrollbarIsOverlaid } = getEnvironment();
const { _value: heightIntrinsic, _changed: heightIntrinsicChanged } = _heightIntrinsic; const { _value: heightIntrinsic, _changed: heightIntrinsicChanged } = _heightIntrinsic;
const { _value: directionIsRTL, _changed: directionChanged } = _directionIsRTL;
const { _value: showNativeOverlaidScrollbarsOption, _changed: showNativeOverlaidScrollbarsChanged } = checkOption<boolean>( const { _value: showNativeOverlaidScrollbarsOption, _changed: showNativeOverlaidScrollbarsChanged } = checkOption<boolean>(
'nativeScrollbarsOverlaid.show' 'nativeScrollbarsOverlaid.show'
); );
@@ -216,6 +213,7 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
const showNativeOverlaidScrollbars = showNativeOverlaidScrollbarsOption && _nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y; const showNativeOverlaidScrollbars = showNativeOverlaidScrollbarsOption && _nativeScrollbarIsOverlaid.x && _nativeScrollbarIsOverlaid.y;
let overflowAmuntCache: CacheValues<XY<number>> = getCurrentOverflowAmountCache(force); let overflowAmuntCache: CacheValues<XY<number>> = getCurrentOverflowAmountCache(force);
let contentScrollSizeCache: CacheValues<WH<number>> = getCurrentContentScrollSizeCache(force); let contentScrollSizeCache: CacheValues<WH<number>> = getCurrentContentScrollSizeCache(force);
let preMeasureViewportOverflowState: ViewportOverflowState | undefined;
if (showNativeOverlaidScrollbarsChanged && _nativeScrollbarStyling) { if (showNativeOverlaidScrollbarsChanged && _nativeScrollbarStyling) {
if (showNativeOverlaidScrollbars) { if (showNativeOverlaidScrollbars) {
@@ -226,39 +224,52 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
} }
if (adjustFlexboxGlue) { if (adjustFlexboxGlue) {
fixFlexboxGlue(getViewportOverflowState(showNativeOverlaidScrollbars), !!heightIntrinsic); preMeasureViewportOverflowState = getViewportOverflowState(showNativeOverlaidScrollbars);
fixFlexboxGlue(preMeasureViewportOverflowState, !!heightIntrinsic);
} }
if (_sizeChanged || _contentMutation) { if (_sizeChanged || _contentMutation) {
const viewportSize = clientSize(_viewport); // needs to be client Size because possible scrollbar offset const viewportRect = getBoundingClientRect(_viewport);
const viewportScrollSize = scrollSize(_viewport); const viewportOffsetSize = offsetSize(_viewport);
const contentClientSize = clientSize(_content || _viewport); // needs to be client Size because applied border for content arrange on content const contentClientSize = clientSize(_content || _viewport); // needs to be client Size because applied border for content arrange on content
const contentArrangeOffsetSize = clientSize(_contentArrange); // can be offset size aswell let viewportScrollSize = fixScrollSizeRounding(scrollSize(_viewport), viewportOffsetSize, viewportRect);
let viewportClientSize = clientSize(_viewport);
contentScrollSizeCache = updateContentScrollSizeCache(force, { const { _value: contentScrollSize, _changed: contentScrollSizeChanged } = (contentScrollSizeCache = updateContentScrollSizeCache(force, {
_viewportSize: viewportSize, _viewportRect: viewportRect,
_viewportOffsetSize: viewportOffsetSize,
_viewportScrollSize: viewportScrollSize, _viewportScrollSize: viewportScrollSize,
}); }));
// re measure is only required if we rely on content arrange to hide native scrollbars (no native scrollbar styling and overlaid scrollbars)
const reMeasureRequired = contentScrollSizeChanged && !showNativeOverlaidScrollbars && _contentArrange;
const { _value: contentScrollSize } = contentScrollSizeCache; if (reMeasureRequired) {
setContentArrange(
preMeasureViewportOverflowState || getViewportOverflowState(showNativeOverlaidScrollbars),
contentScrollSize!,
directionIsRTL!
);
viewportClientSize = clientSize(_viewport);
viewportScrollSize = fixScrollSizeRounding(scrollSize(_viewport), offsetSize(_viewport), getBoundingClientRect(_viewport));
}
const contentArrangeOffsetSize = clientSize(_contentArrange);
overflowAmuntCache = updateOverflowAmountCache(force, { overflowAmuntCache = updateOverflowAmountCache(force, {
_contentScrollSize: { _contentScrollSize: {
w: Math.max(contentScrollSize!.w, contentArrangeOffsetSize.w), w: Math.max(contentScrollSize!.w, viewportScrollSize.w, contentArrangeOffsetSize.w),
h: Math.max(contentScrollSize!.h, contentArrangeOffsetSize.h), h: Math.max(contentScrollSize!.h, viewportScrollSize.h, contentArrangeOffsetSize.h),
}, },
_viewportSize: { _viewportSize: {
w: viewportSize.w + Math.max(0, contentClientSize.w - contentScrollSize!.w), w: viewportClientSize.w + Math.max(0, contentClientSize.w - contentScrollSize!.w),
h: viewportSize.h + Math.max(0, contentClientSize.h - contentScrollSize!.h), h: viewportClientSize.h + Math.max(0, contentClientSize.h - contentScrollSize!.h),
}, },
}); });
} }
const { _value: overflow, _changed: overflowChanged } = checkOption<OverflowOption>('overflow'); const { _value: overflow, _changed: overflowChanged } = checkOption<OverflowOption>('overflow');
const { _value: directionIsRTL, _changed: directionChanged } = _directionIsRTL;
const { _value: contentScrollSize, _changed: contentScrollSizeChanged } = contentScrollSizeCache; const { _value: contentScrollSize, _changed: contentScrollSizeChanged } = contentScrollSizeCache;
const { _value: overflowAmount, _changed: overflowAmountChanged } = overflowAmuntCache; const { _value: overflowAmount, _changed: overflowAmountChanged } = overflowAmuntCache;
const adjustDirection = directionChanged && !_nativeScrollbarStyling;
if ( if (
_paddingStyleChanged || _paddingStyleChanged ||
@@ -266,7 +277,7 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
overflowAmountChanged || overflowAmountChanged ||
overflowChanged || overflowChanged ||
showNativeOverlaidScrollbarsChanged || showNativeOverlaidScrollbarsChanged ||
adjustDirection || directionChanged ||
adjustFlexboxGlue adjustFlexboxGlue
) { ) {
const viewportStyle: StyleObject = { const viewportStyle: StyleObject = {
@@ -286,8 +297,8 @@ export const createOverflowLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =
}; };
const viewportOverflowState = setViewportOverflowState(showNativeOverlaidScrollbars, overflowAmount!, overflow, viewportStyle); const viewportOverflowState = setViewportOverflowState(showNativeOverlaidScrollbars, overflowAmount!, overflow, viewportStyle);
hideNativeScrollbars(viewportOverflowState, directionIsRTL!, viewportStyle, contentStyle); hideNativeScrollbars(viewportOverflowState, directionIsRTL!, viewportStyle);
setContentArrange(viewportOverflowState, contentScrollSize!, showNativeOverlaidScrollbars); setContentArrange(viewportOverflowState, contentScrollSize!, directionIsRTL!, contentStyle);
if (adjustFlexboxGlue) { if (adjustFlexboxGlue) {
fixFlexboxGlue(viewportOverflowState, !!heightIntrinsic); fixFlexboxGlue(viewportOverflowState, !!heightIntrinsic);
@@ -20,17 +20,16 @@ export const createPaddingLifecycle = (lifecycleHub: LifecycleHub): Lifecycle =>
return (updateHints, checkOption, force) => { return (updateHints, checkOption, force) => {
let { _value: padding, _changed: paddingChanged } = currentPaddingCache(force); let { _value: padding, _changed: paddingChanged } = currentPaddingCache(force);
const { _nativeScrollbarStyling, _flexboxGlue } = getEnvironment(); const { _nativeScrollbarStyling } = getEnvironment();
const { _sizeChanged, _directionIsRTL, _heightIntrinsic } = updateHints; const { _sizeChanged, _directionIsRTL } = updateHints;
const { _value: directionIsRTL, _changed: directionRTLChanged } = _directionIsRTL; const { _value: directionIsRTL, _changed: directionChanged } = _directionIsRTL;
const { _value: paddingAbsolute, _changed: paddingAbsoluteChanged } = checkOption('paddingAbsolute'); const { _value: paddingAbsolute, _changed: paddingAbsoluteChanged } = checkOption('paddingAbsolute');
const { _value: heightIntrinsic } = _heightIntrinsic;
if (_sizeChanged || paddingChanged) { if (_sizeChanged || paddingChanged) {
({ _value: padding, _changed: paddingChanged } = updatePaddingCache(force)); ({ _value: padding, _changed: paddingChanged } = updatePaddingCache(force));
} }
const paddingStyleChanged = paddingAbsoluteChanged || directionRTLChanged || paddingChanged; const paddingStyleChanged = paddingAbsoluteChanged || directionChanged || paddingChanged;
if (paddingStyleChanged) { if (paddingStyleChanged) {
// if there is no padding element and no scrollbar styling padding absolute isn't supported // if there is no padding element and no scrollbar styling padding absolute isn't supported
@@ -86,7 +86,9 @@
} }
.os-content-arrange { .os-content-arrange {
position: absolute; min-width: 1px;
min-height: 1px;
z-index: -1; z-index: -1;
position: absolute;
pointer-events: none; pointer-events: none;
} }
@@ -93,12 +93,12 @@ export const show = (elm: HTMLElement | null | undefined): void => {
* @param property * @param property
*/ */
export const topRightBottomLeft = (elm: HTMLElement | null | undefined, propertyPrefix?: string, propertySuffix?: string): TRBL => { export const topRightBottomLeft = (elm: HTMLElement | null | undefined, propertyPrefix?: string, propertySuffix?: string): TRBL => {
const finalPrefix = propertyPrefix || ''; const finalPrefix = propertyPrefix ? `${propertyPrefix}-` : '';
const finalSuffix = propertySuffix || ''; const finalSuffix = propertySuffix ? `-${propertySuffix}` : '';
const top = `${finalPrefix}-top-${finalSuffix}`; const top = `${finalPrefix}top${finalSuffix}`;
const right = `${finalPrefix}-right-${finalSuffix}`; const right = `${finalPrefix}right${finalSuffix}`;
const bottom = `${finalPrefix}-bottom-${finalSuffix}`; const bottom = `${finalPrefix}bottom${finalSuffix}`;
const left = `${finalPrefix}-left-${finalSuffix}`; const left = `${finalPrefix}left${finalSuffix}`;
const result = style(elm, [top, right, bottom, left]); const result = style(elm, [top, right, bottom, left]);
return { return {
t: parseToZeroOrNumber(result[top]), t: parseToZeroOrNumber(result[top]),