| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- "use client";
- import { jsx } from 'react/jsx-runtime';
- import * as React from 'react';
- import { useId, useRef, useContext, useInsertionEffect } from 'react';
- import { MotionConfigContext } from '../../context/MotionConfigContext.mjs';
- /**
- * Measurement functionality has to be within a separate component
- * to leverage snapshot lifecycle.
- */
- class PopChildMeasure extends React.Component {
- getSnapshotBeforeUpdate(prevProps) {
- const element = this.props.childRef.current;
- if (element && prevProps.isPresent && !this.props.isPresent) {
- const parent = element.offsetParent;
- const parentWidth = parent instanceof HTMLElement ? parent.offsetWidth || 0 : 0;
- const size = this.props.sizeRef.current;
- size.height = element.offsetHeight || 0;
- size.width = element.offsetWidth || 0;
- size.top = element.offsetTop;
- size.left = element.offsetLeft;
- size.right = parentWidth - size.width - size.left;
- }
- return null;
- }
- /**
- * Required with getSnapshotBeforeUpdate to stop React complaining.
- */
- componentDidUpdate() { }
- render() {
- return this.props.children;
- }
- }
- function PopChild({ children, isPresent, anchorX }) {
- const id = useId();
- const ref = useRef(null);
- const size = useRef({
- width: 0,
- height: 0,
- top: 0,
- left: 0,
- right: 0,
- });
- const { nonce } = useContext(MotionConfigContext);
- /**
- * We create and inject a style block so we can apply this explicit
- * sizing in a non-destructive manner by just deleting the style block.
- *
- * We can't apply size via render as the measurement happens
- * in getSnapshotBeforeUpdate (post-render), likewise if we apply the
- * styles directly on the DOM node, we might be overwriting
- * styles set via the style prop.
- */
- useInsertionEffect(() => {
- const { width, height, top, left, right } = size.current;
- if (isPresent || !ref.current || !width || !height)
- return;
- const x = anchorX === "left" ? `left: ${left}` : `right: ${right}`;
- ref.current.dataset.motionPopId = id;
- const style = document.createElement("style");
- if (nonce)
- style.nonce = nonce;
- document.head.appendChild(style);
- if (style.sheet) {
- style.sheet.insertRule(`
- [data-motion-pop-id="${id}"] {
- position: absolute !important;
- width: ${width}px !important;
- height: ${height}px !important;
- ${x}px !important;
- top: ${top}px !important;
- }
- `);
- }
- return () => {
- document.head.removeChild(style);
- };
- }, [isPresent]);
- return (jsx(PopChildMeasure, { isPresent: isPresent, childRef: ref, sizeRef: size, children: React.cloneElement(children, { ref }) }));
- }
- export { PopChild };
|