{"version":3,"sources":["../src/utils/auto-animate-height.tsx"],"sourcesContent":["import { cloneElement, forwardRef, useEffect, useRef, useState } from \"react\";\nimport { useMergeRefs } from \"./utils\";\n\nexport interface AutoAnimateHeightProps extends React.HTMLAttributes<HTMLDivElement> {\n  /**\n   * Time of the animation, using the hedwig animation tokens\n   * quick: 0.1s\n   * normal: 0.3s\n   * slow: 0.7s\n   *\n   * default is \"quick\"\n   */\n  animationDuration?: \"quick\" | \"normal\" | \"slow\";\n\n  /**\n   * Callback fired when animiation transition ends\n   * Use this to do effects after resizing is done, e.g. scrolling to the element\n   * using `element.scrollIntoView()`\n   */\n  onTransitionEnd?: () => void;\n\n  /**\n   * Which hedwig easing function to use, default is \"normal\"\n   */\n  animationEasing?: \"in\" | \"out\" | \"normal\";\n  children: React.ReactNode;\n  style?: React.CSSProperties;\n}\n\n/**\n * Helper component to animate the height of the children when they change\n * It's done by rendering two versions of the passed children,\n * one hidden to measure the height and one visible to only changes after the height is measured.\n *\n * **IMPORTANT** Do not pass any components with effects (like data fetching), as they will trigger twice.\n */\nexport const AutoAnimateHeight = forwardRef<HTMLDivElement, AutoAnimateHeightProps>(\n  (\n    {\n      children,\n      style,\n      animationDuration = \"quick\",\n      animationEasing = \"normal\",\n      onTransitionEnd,\n      ...rest\n    },\n    ref,\n  ) => {\n    const rootRef = useRef<HTMLDivElement>(null);\n    const mergedRef = useMergeRefs([rootRef, ref]);\n    const measurementRef = useRef<HTMLDivElement>(null);\n    const [height, setHeight] = useState<{ height: number; shouldAnimate: boolean } | undefined>(\n      undefined,\n    );\n    const [clonedChildren, setClonedChildren] = useState<React.ReactNode>(() =>\n      cloneElement(<>{children}</>, {}),\n    );\n\n    useEffect(() => {\n      if (!rootRef.current) return;\n      if (!measurementRef.current) return;\n      if (document.body.scrollHeight === 0) return;\n      const currentMeasurement = measurementRef.current;\n      const { height: newHeight } = currentMeasurement.getBoundingClientRect();\n\n      // Listen for resize events on the measurement element\n      // Keep the children in sync with the height\n      // But don't animate it.\n      let previouslyObservedHeight = newHeight;\n      const resizeObserver = new ResizeObserver(() => {\n        const { height: resizedHeight } = currentMeasurement.getBoundingClientRect();\n        if (resizedHeight === previouslyObservedHeight) return;\n        previouslyObservedHeight = resizedHeight;\n        setHeight({ height: resizedHeight, shouldAnimate: false });\n      });\n      resizeObserver.observe(currentMeasurement); // This is cleaned up down below in the return functions\n\n      // Set the new height when children changes\n      setHeight({ height: newHeight, shouldAnimate: true });\n\n      // Update children\n      const nextClonedChildren = cloneElement(<>{children}</>, {});\n\n      // When increasing in height update immediately so the new content is shown during the animation\n      if (newHeight >= (height?.height ?? 0)) {\n        setClonedChildren(nextClonedChildren);\n        return () => {\n          resizeObserver.disconnect();\n        };\n      }\n\n      // When decreasing in height, wait until the animation is done so that we don't get a sudden flash of empty content\n      const currentRoot = rootRef.current;\n      function onTransitionEndHandler(e: TransitionEvent) {\n        if (e.propertyName !== \"height\") return;\n        setClonedChildren(nextClonedChildren);\n      }\n      currentRoot.addEventListener(\"transitionend\", onTransitionEndHandler);\n      return () => {\n        resizeObserver.disconnect();\n        currentRoot.removeEventListener(\"transitionend\", onTransitionEndHandler);\n      };\n\n      // eslint-disable-next-line react-hooks/exhaustive-deps -- I know better\n    }, [children]);\n\n    return (\n      <div\n        ref={mergedRef}\n        onTransitionEnd={onTransitionEnd}\n        style={{\n          position: \"relative\",\n          overflow: \"hidden\",\n          height: height?.height ?? measurementRef.current?.getBoundingClientRect().height,\n          transitionProperty: height?.shouldAnimate ? \"height\" : \"none\",\n          transitionDuration: `var(--hds-micro-animation-duration-${animationDuration})`,\n          transitionTimingFunction: `var(--hds-micro-animation-easing-${animationEasing})`,\n          willChange: \"height\",\n          ...style,\n        }}\n        {...rest}\n      >\n        <div\n          aria-hidden\n          ref={measurementRef}\n          style={{\n            position: \"absolute\",\n            visibility: \"hidden\",\n            pointerEvents: \"none\",\n          }}\n        >\n          {children}\n        </div>\n        {clonedChildren}\n      </div>\n    );\n  },\n);\nAutoAnimateHeight.displayName = \"AutoAnimateHeight\";\n"],"mappings":";;;;;;;;;;AAAA,SAAS,cAAc,YAAY,WAAW,QAAQ,gBAAgB;AAuDnD,wBAoDb,YApDa;AAnBZ,IAAM,oBAAoB;AAAA,EAC/B,CACE,IAQA,QACG;AATH,iBACE;AAAA;AAAA,MACA;AAAA,MACA,oBAAoB;AAAA,MACpB,kBAAkB;AAAA,MAClB;AAAA,IA3CN,IAsCI,IAMK,iBANL,IAMK;AAAA,MALH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AA3CN,QAAAA,KAAAC;AAgDI,UAAM,UAAU,OAAuB,IAAI;AAC3C,UAAM,YAAY,aAAa,CAAC,SAAS,GAAG,CAAC;AAC7C,UAAM,iBAAiB,OAAuB,IAAI;AAClD,UAAM,CAAC,QAAQ,SAAS,IAAI;AAAA,MAC1B;AAAA,IACF;AACA,UAAM,CAAC,gBAAgB,iBAAiB,IAAI;AAAA,MAA0B,MACpE,aAAa,gCAAG,UAAS,GAAK,CAAC,CAAC;AAAA,IAClC;AAEA,cAAU,MAAM;AA1DpB,UAAAD;AA2DM,UAAI,CAAC,QAAQ,QAAS;AACtB,UAAI,CAAC,eAAe,QAAS;AAC7B,UAAI,SAAS,KAAK,iBAAiB,EAAG;AACtC,YAAM,qBAAqB,eAAe;AAC1C,YAAM,EAAE,QAAQ,UAAU,IAAI,mBAAmB,sBAAsB;AAKvE,UAAI,2BAA2B;AAC/B,YAAM,iBAAiB,IAAI,eAAe,MAAM;AAC9C,cAAM,EAAE,QAAQ,cAAc,IAAI,mBAAmB,sBAAsB;AAC3E,YAAI,kBAAkB,yBAA0B;AAChD,mCAA2B;AAC3B,kBAAU,EAAE,QAAQ,eAAe,eAAe,MAAM,CAAC;AAAA,MAC3D,CAAC;AACD,qBAAe,QAAQ,kBAAkB;AAGzC,gBAAU,EAAE,QAAQ,WAAW,eAAe,KAAK,CAAC;AAGpD,YAAM,qBAAqB,aAAa,gCAAG,UAAS,GAAK,CAAC,CAAC;AAG3D,UAAI,eAAcA,MAAA,iCAAQ,WAAR,OAAAA,MAAkB,IAAI;AACtC,0BAAkB,kBAAkB;AACpC,eAAO,MAAM;AACX,yBAAe,WAAW;AAAA,QAC5B;AAAA,MACF;AAGA,YAAM,cAAc,QAAQ;AAC5B,eAAS,uBAAuB,GAAoB;AAClD,YAAI,EAAE,iBAAiB,SAAU;AACjC,0BAAkB,kBAAkB;AAAA,MACtC;AACA,kBAAY,iBAAiB,iBAAiB,sBAAsB;AACpE,aAAO,MAAM;AACX,uBAAe,WAAW;AAC1B,oBAAY,oBAAoB,iBAAiB,sBAAsB;AAAA,MACzE;AAAA,IAGF,GAAG,CAAC,QAAQ,CAAC;AAEb,WACE;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL;AAAA,QACA,OAAO;AAAA,UACL,UAAU;AAAA,UACV,UAAU;AAAA,UACV,SAAQC,MAAA,iCAAQ,WAAR,OAAAA,OAAkBD,MAAA,eAAe,YAAf,gBAAAA,IAAwB,wBAAwB;AAAA,UAC1E,qBAAoB,iCAAQ,iBAAgB,WAAW;AAAA,UACvD,oBAAoB,sCAAsC,iBAAiB;AAAA,UAC3E,0BAA0B,oCAAoC,eAAe;AAAA,UAC7E,YAAY;AAAA,WACT;AAAA,SAED,OAbL;AAAA,QAeC;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,eAAW;AAAA,cACX,KAAK;AAAA,cACL,OAAO;AAAA,gBACL,UAAU;AAAA,gBACV,YAAY;AAAA,gBACZ,eAAe;AAAA,cACjB;AAAA,cAEC;AAAA;AAAA,UACH;AAAA,UACC;AAAA;AAAA;AAAA,IACH;AAAA,EAEJ;AACF;AACA,kBAAkB,cAAc;","names":["_a","_b"]}