All files / src/render/html/utils build-styles.ts

100% Statements 38/38
100% Branches 24/24
100% Functions 1/1
100% Lines 36/36

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90        37x 37x 37x 37x 37x   37x           11880x         2376x     2376x 2376x     2376x               2376x 2322x         2322x 5x 5x       2317x 2317x   2317x   1436x 1436x 1436x     1436x     1277x 881x 3x     3x   878x       2376x 1167x           1209x 6x 1203x 2x     2376x 1x      
import { MotionProps } from "../../../motion/types"
import { HTMLRenderState } from "../types"
import { ResolvedValues } from "../../types"
import { DOMVisualElementOptions } from "../../dom/types"
import { buildTransform, buildTransformOrigin } from "./build-transform"
import { isCSSVariable } from "../../dom/utils/is-css-variable"
import { isTransformOriginProp, isTransformProp } from "./transform"
import { getValueAsType } from "../../dom/value-types/get-as-type"
import { numberValueTypes } from "../../dom/value-types/number"
 
export function buildHTMLStyles(
    state: HTMLRenderState,
    latestValues: ResolvedValues,
    options: DOMVisualElementOptions,
    transformTemplate?: MotionProps["transformTemplate"]
) {
    const { style, vars, transform, transformKeys, transformOrigin } = state
 
    // Empty the transformKeys array. As we're throwing out refs to its items
    // this might not be as cheap as suspected. Maybe using the array as a buffer
    // with a manual incrementation would be better.
    transformKeys.length = 0
 
    // Track whether we encounter any transform or transformOrigin values.
    let hasTransform = false
    let hasTransformOrigin = false
 
    // Does the calculated transform essentially equal "none"?
    let transformIsNone = true
 
    /**
     * Loop over all our latest animated values and decide whether to handle them
     * as a style or CSS variable.
     *
     * Transforms and transform origins are kept seperately for further processing.
     */
    for (const key in latestValues) {
        const value = latestValues[key]
 
        /**
         * If this is a CSS variable we don't do any further processing.
         */
        if (isCSSVariable(key)) {
            vars[key] = value
            continue
        }
 
        // Convert the value to its default value type, ie 0 -> "0px"
        const valueType = numberValueTypes[key]
        const valueAsType = getValueAsType(value, valueType)
 
        if (isTransformProp(key)) {
            // If this is a transform, flag to enable further transform processing
            hasTransform = true
            transform[key] = valueAsType
            transformKeys.push(key)
 
            // If we already know we have a non-default transform, early return
            if (!transformIsNone) continue
 
            // Otherwise check to see if this is a default transform
            if (value !== (valueType.default ?? 0)) transformIsNone = false
        } else if (isTransformOriginProp(key)) {
            transformOrigin[key] = valueAsType
 
            // If this is a transform origin, flag and enable further transform-origin processing
            hasTransformOrigin = true
        } else {
            style[key] = valueAsType
        }
    }
 
    if (hasTransform) {
        style.transform = buildTransform(
            state,
            options,
            transformIsNone,
            transformTemplate
        )
    } else if (transformTemplate) {
        style.transform = transformTemplate({}, "")
    } else if (!latestValues.transform && style.transform) {
        style.transform = "none"
    }
 
    if (hasTransformOrigin) {
        style.transformOrigin = buildTransformOrigin(transformOrigin)
    }
}