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           11875x         2375x     2375x 2375x     2375x               2375x 2315x         2315x 5x 5x       2310x 2310x   2310x   1430x 1430x 1430x     1430x     1277x 880x 3x     3x   877x       2375x 1168x           1207x 6x 1201x 2x     2375x 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)
    }
}