'use strict';

var react = require('motion/react');
var React4 = require('react');
var reactDom = require('react-dom');
var useMeasure = require('react-use-measure');
var motion = require('motion');

function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }

var React4__default = /*#__PURE__*/_interopDefault(React4);
var useMeasure__default = /*#__PURE__*/_interopDefault(useMeasure);

// src/SheetBackdrop.tsx
var SheetContext = React4.createContext(
  void 0
);
function useSheetContext() {
  const context = React4.useContext(SheetContext);
  if (!context) throw new Error("Sheet context error");
  return context;
}

// src/styles.ts
var styles = {
  root: {
    base: {
      position: "fixed",
      top: 0,
      bottom: 0,
      left: 0,
      right: 0,
      overflow: "hidden",
      pointerEvents: "none"
    },
    decorative: {}
  },
  backdrop: {
    base: {
      zIndex: 1,
      position: "fixed",
      top: 0,
      left: 0,
      width: "100%",
      height: "100%",
      touchAction: "none",
      userSelect: "none"
    },
    decorative: {
      backgroundColor: "rgba(0, 0, 0, 0.2)",
      border: "none",
      WebkitTapHighlightColor: "transparent"
    }
  },
  container: {
    base: {
      zIndex: 2,
      position: "absolute",
      left: 0,
      bottom: 0,
      width: "100%",
      pointerEvents: "auto",
      display: "flex",
      flexDirection: "column"
    },
    decorative: {
      backgroundColor: "#fff",
      borderTopRightRadius: "8px",
      borderTopLeftRadius: "8px",
      boxShadow: "0px -2px 16px rgba(0, 0, 0, 0.3)"
    }
  },
  headerWrapper: {
    base: {
      width: "100%"
    },
    decorative: {}
  },
  header: {
    base: {
      width: "100%",
      position: "relative"
    },
    decorative: {
      height: "40px",
      display: "flex",
      alignItems: "center",
      justifyContent: "center"
    }
  },
  indicatorWrapper: {
    base: {
      display: "flex"
    },
    decorative: {}
  },
  indicator: {
    base: {
      display: "inline-block"
    },
    decorative: {
      width: "18px",
      height: "4px",
      borderRadius: "99px",
      backgroundColor: "#ddd"
    }
  },
  content: {
    base: {
      minHeight: "0px",
      position: "relative",
      flexGrow: 1,
      display: "flex",
      flexDirection: "column"
    },
    decorative: {}
  },
  scroller: {
    base: {
      height: "100%",
      overflowY: "auto",
      overscrollBehaviorY: "none"
    },
    decorative: {}
  }
};

// src/constants.ts
var DEFAULT_HEIGHT = "calc(100% - env(safe-area-inset-top) - 34px)";
var IS_SSR = typeof window === "undefined";
var DEFAULT_TWEEN_CONFIG = {
  ease: "easeOut",
  duration: 0.2
};
var REDUCED_MOTION_TWEEN_CONFIG = {
  ease: "linear",
  duration: 0.01
};
var DEFAULT_DRAG_CLOSE_THRESHOLD = 0.6;
var DEFAULT_DRAG_VELOCITY_THRESHOLD = 500;

// src/utils.ts
function applyStyles(styles2, unstyled) {
  return unstyled ? styles2.base : { ...styles2.base, ...styles2.decorative };
}
function isAscendingOrder(arr) {
  for (let i = 0; i < arr.length; i++) {
    if (arr[i + 1] < arr[i]) return false;
  }
  return true;
}
function mergeRefs(refs) {
  return (value) => {
    refs.forEach((ref) => {
      if (typeof ref === "function") {
        ref(value);
      } else if (ref) {
        ref.current = value;
      }
    });
  };
}
function testPlatform(re) {
  var _a;
  return typeof window !== "undefined" && window.navigator != null ? re.test(
    // @ts-expect-error
    ((_a = window.navigator.userAgentData) == null ? void 0 : _a.platform) || window.navigator.platform
  ) : false;
}
function cached(fn) {
  let res = null;
  return () => {
    if (res == null) {
      res = fn();
    }
    return res;
  };
}
var isMac = cached(function() {
  return testPlatform(/^Mac/i);
});
var isIPhone = cached(function() {
  return testPlatform(/^iPhone/i);
});
var isIPad = cached(function() {
  return testPlatform(/^iPad/i) || isMac() && navigator.maxTouchPoints > 1;
});
var isIOS = cached(function() {
  return isIPhone() || isIPad();
});
function waitForElement(className, interval = 50, maxAttempts = 20) {
  return new Promise((resolve) => {
    let attempts = 0;
    const timer = setInterval(() => {
      const element = document.getElementsByClassName(
        className
      )[0];
      attempts++;
      if (element || attempts >= maxAttempts) {
        clearInterval(timer);
        resolve(element);
      }
    }, interval);
  });
}

// src/SheetBackdrop.tsx
var isClickable = (props) => !!props.onClick || !!props.onTap;
var SheetBackdrop = React4.forwardRef(
  ({ style, className = "", unstyled, ...rest }, ref) => {
    const sheetContext = useSheetContext();
    const clickable = isClickable(rest);
    const Comp = clickable ? react.motion.button : react.motion.div;
    const pointerEvents = clickable ? "auto" : "none";
    const isUnstyled = unstyled ?? sheetContext.unstyled;
    const backdropStyle = {
      ...applyStyles(styles.backdrop, isUnstyled),
      ...style,
      pointerEvents
    };
    return /* @__PURE__ */ React4__default.default.createElement(
      Comp,
      {
        initial: { opacity: 0 },
        animate: { opacity: 1 },
        exit: { opacity: 0 },
        transition: { duration: 1 },
        ...rest,
        ref,
        className: `react-modal-sheet-backdrop ${className}`,
        style: backdropStyle
      }
    );
  }
);
SheetBackdrop.displayName = "SheetBackdrop";
var SheetContainer = React4.forwardRef(
  ({ children, style, className = "", unstyled, ...rest }, ref) => {
    const sheetContext = useSheetContext();
    const isUnstyled = unstyled ?? sheetContext.unstyled;
    const containerStyle = {
      ...applyStyles(styles.container, isUnstyled),
      ...style,
      y: sheetContext.y
    };
    if (sheetContext.detent === "default") {
      containerStyle.height = DEFAULT_HEIGHT;
    }
    if (sheetContext.detent === "full") {
      containerStyle.height = "100%";
      containerStyle.maxHeight = "100%";
    }
    if (sheetContext.detent === "content") {
      containerStyle.height = "auto";
      containerStyle.maxHeight = DEFAULT_HEIGHT;
    }
    return /* @__PURE__ */ React4__default.default.createElement(
      react.motion.div,
      {
        ...rest,
        ref: mergeRefs([
          ref,
          sheetContext.sheetRef,
          sheetContext.sheetBoundsRef
        ]),
        className: `react-modal-sheet-container ${className}`,
        style: containerStyle
      },
      children
    );
  }
);
SheetContainer.displayName = "SheetContainer";
var constraints = { bottom: 0, top: 0, left: 0, right: 0 };
function useDragConstraints() {
  const ref = React4.useRef(null);
  const onMeasure = React4.useCallback(() => constraints, []);
  return { ref, onMeasure };
}
var useIsomorphicLayoutEffect = IS_SSR ? React4.useEffect : React4.useLayoutEffect;

// src/hooks/use-stable-callback.ts
function useStableCallback(handler) {
  const handlerRef = React4.useRef(void 0);
  useIsomorphicLayoutEffect(() => {
    handlerRef.current = handler;
  });
  return React4.useCallback((...args) => {
    const fn = handlerRef.current;
    return fn == null ? void 0 : fn(...args);
  }, []);
}

// src/hooks/use-scroll-position.ts
function useScrollPosition(options = {}) {
  const { debounceDelay = 32, isEnabled = true } = options;
  const scrollTimeoutRef = React4.useRef(null);
  const [element, setElement] = React4.useState(null);
  const [scrollPosition, setScrollPosition] = React4.useState(void 0);
  const scrollRef = React4.useMemo(
    () => (element2) => {
      setElement(element2);
    },
    []
  );
  const determineScrollPosition = useStableCallback((element2) => {
    const { scrollTop, scrollHeight, clientHeight } = element2;
    const isScrollable2 = scrollHeight > clientHeight;
    if (!isScrollable2) {
      if (scrollPosition) setScrollPosition(void 0);
      return;
    }
    const isAtTop = scrollTop <= 0;
    const isAtBottom = Math.ceil(scrollHeight) - Math.ceil(scrollTop) === Math.ceil(clientHeight);
    let position;
    if (isAtTop) {
      position = "top";
    } else if (isAtBottom) {
      position = "bottom";
    } else {
      position = "middle";
    }
    element2.style.touchAction = isAtTop ? "pan-down" : "";
    if (position === scrollPosition) return;
    setScrollPosition(position);
  });
  const onScroll = useStableCallback((event) => {
    if (event.currentTarget instanceof HTMLElement) {
      const el = event.currentTarget;
      if (scrollTimeoutRef.current) clearTimeout(scrollTimeoutRef.current);
      if (debounceDelay === 0) {
        determineScrollPosition(el);
      } else {
        scrollTimeoutRef.current = setTimeout(
          () => determineScrollPosition(el),
          debounceDelay
        );
      }
    }
  });
  const onTouchStart = useStableCallback((event) => {
    if (event.currentTarget instanceof HTMLElement) {
      const element2 = event.currentTarget;
      requestAnimationFrame(() => {
        determineScrollPosition(element2);
      });
    }
  });
  React4.useEffect(() => {
    if (!element || !isEnabled) return;
    determineScrollPosition(element);
    element.addEventListener("scroll", onScroll);
    element.addEventListener("touchstart", onTouchStart);
    return () => {
      if (scrollTimeoutRef.current) clearTimeout(scrollTimeoutRef.current);
      element.removeEventListener("scroll", onScroll);
      element.removeEventListener("touchstart", onTouchStart);
    };
  }, [element, isEnabled]);
  return {
    scrollRef,
    scrollPosition
  };
}

// src/SheetContent.tsx
var SheetContent = React4.forwardRef(
  ({
    disableScroll: disableScrollProp,
    disableDrag: disableDragProp,
    children,
    style: styleProp,
    className = "",
    scrollClassName = "",
    scrollStyle: scrollStyleProp,
    scrollRef: scrollRefProp = null,
    unstyled,
    ...rest
  }, ref) => {
    const sheetContext = useSheetContext();
    const dragConstraints = useDragConstraints();
    const scroll = useScrollPosition({
      isEnabled: typeof disableScrollProp === "function" ? true : !disableScrollProp
    });
    const disableScroll = typeof disableScrollProp === "function" ? disableScrollProp({
      scrollPosition: scroll.scrollPosition,
      currentSnap: sheetContext.currentSnap
    }) : Boolean(disableScrollProp);
    const disableDragDueToScroll = !disableScroll && scroll.scrollPosition && scroll.scrollPosition !== "top";
    const disableDragDueToProp = typeof disableDragProp === "function" ? disableDragProp({
      scrollPosition: scroll.scrollPosition,
      currentSnap: sheetContext.currentSnap
    }) : Boolean(disableDragProp);
    const disableDrag = disableDragDueToProp || disableDragDueToScroll || sheetContext.disableDrag;
    const dragProps = disableDrag || sheetContext.disableDrag ? void 0 : sheetContext.dragProps;
    const isUnstyled = unstyled ?? sheetContext.unstyled;
    const contentStyle = {
      ...applyStyles(styles.content, isUnstyled),
      ...styleProp
    };
    const scrollStyle = applyStyles(styles.scroller, isUnstyled);
    if (sheetContext.avoidKeyboard) {
      scrollStyle.paddingBottom = "env(keyboard-inset-height, var(--keyboard-inset-height, 0px))";
    }
    if (disableScroll) {
      scrollStyle.overflowY = "hidden";
    }
    if (dragProps !== void 0) {
      scrollStyle.touchAction = "pan-down";
    }
    return /* @__PURE__ */ React4__default.default.createElement(
      react.motion.div,
      {
        ...rest,
        ref: mergeRefs([ref, dragConstraints.ref]),
        className: `react-modal-sheet-content ${className}`,
        style: contentStyle,
        ...dragProps,
        dragConstraints: dragConstraints.ref,
        onMeasureDragConstraints: dragConstraints.onMeasure
      },
      /* @__PURE__ */ React4__default.default.createElement(
        react.motion.div,
        {
          ref: mergeRefs([scroll.scrollRef, scrollRefProp]),
          style: { ...scrollStyle, ...scrollStyleProp },
          className: `react-modal-sheet-content-scroller ${scrollClassName}`
        },
        children
      )
    );
  }
);
SheetContent.displayName = "SheetContent";
function SheetDragIndicator({
  style,
  className = "",
  unstyled,
  ...rest
}) {
  const sheetContext = useSheetContext();
  const indicator1Transform = react.useTransform(
    sheetContext.indicatorRotation,
    (r) => `translateX(2px) rotate(${r}deg)`
  );
  const indicator2Transform = react.useTransform(
    sheetContext.indicatorRotation,
    (r) => `translateX(-2px) rotate(${ -1 * r}deg)`
  );
  const isUnstyled = unstyled ?? sheetContext.unstyled;
  const indicatorWrapperStyle = {
    ...applyStyles(styles.indicatorWrapper, isUnstyled),
    ...style
  };
  const indicatorStyle = applyStyles(styles.indicator, isUnstyled);
  return /* @__PURE__ */ React4__default.default.createElement(
    "div",
    {
      className: `react-modal-sheet-drag-indicator-container ${className}`,
      style: indicatorWrapperStyle,
      ...rest
    },
    /* @__PURE__ */ React4__default.default.createElement(
      react.motion.span,
      {
        className: "react-modal-sheet-drag-indicator",
        style: { ...indicatorStyle, transform: indicator1Transform }
      }
    ),
    /* @__PURE__ */ React4__default.default.createElement(
      react.motion.span,
      {
        className: "react-modal-sheet-drag-indicator",
        style: { ...indicatorStyle, transform: indicator2Transform }
      }
    )
  );
}
var SheetHeader = React4.forwardRef(
  ({ children, style, disableDrag, unstyled, className = "", ...rest }, ref) => {
    const sheetContext = useSheetContext();
    const dragConstraints = useDragConstraints();
    const dragProps = disableDrag || sheetContext.disableDrag ? void 0 : sheetContext.dragProps;
    const isUnstyled = unstyled ?? sheetContext.unstyled;
    const headerWrapperStyle = {
      ...applyStyles(styles.headerWrapper, isUnstyled),
      ...style
    };
    const headerStyle = applyStyles(styles.header, isUnstyled);
    return /* @__PURE__ */ React4__default.default.createElement(
      react.motion.div,
      {
        ...rest,
        ref: mergeRefs([ref, dragConstraints.ref]),
        style: headerWrapperStyle,
        className: `react-modal-sheet-header-container ${className}`,
        ...dragProps,
        dragConstraints: dragConstraints.ref,
        onMeasureDragConstraints: dragConstraints.onMeasure
      },
      children || /* @__PURE__ */ React4__default.default.createElement("div", { className: "react-modal-sheet-header", style: headerStyle }, /* @__PURE__ */ React4__default.default.createElement(SheetDragIndicator, null))
    );
  }
);
SheetHeader.displayName = "SheetHeader";
function useDimensions() {
  const [dimensions, setDimensions] = React4.useState(() => ({
    windowHeight: !IS_SSR ? window.innerHeight : 0,
    windowWidth: !IS_SSR ? window.innerWidth : 0
  }));
  useIsomorphicLayoutEffect(() => {
    function handler() {
      setDimensions({
        windowHeight: window.innerHeight,
        windowWidth: window.innerWidth
      });
    }
    handler();
    window.addEventListener("resize", handler);
    return () => {
      window.removeEventListener("resize", handler);
    };
  }, []);
  return dimensions;
}
function useSafeAreaInsets() {
  const [insets] = React4.useState(() => {
    const fallback = { top: 0, left: 0, right: 0, bottom: 0 };
    if (IS_SSR) return fallback;
    const root = document.querySelector(":root");
    if (!root) return fallback;
    root.style.setProperty("--rms-sat", "env(safe-area-inset-top)");
    root.style.setProperty("--rms-sal", "env(safe-area-inset-left)");
    root.style.setProperty("--rms-sar", "env(safe-area-inset-right)");
    root.style.setProperty("--rms-sab", "env(safe-area-inset-bottom)");
    const computedStyle = getComputedStyle(root);
    const sat = getComputedValue(computedStyle, "--rms-sat");
    const sal = getComputedValue(computedStyle, "--rms-sal");
    const sar = getComputedValue(computedStyle, "--rms-sar");
    const sab = getComputedValue(computedStyle, "--rms-sab");
    root.style.removeProperty("--rms-sat");
    root.style.removeProperty("--rms-sal");
    root.style.removeProperty("--rms-sar");
    root.style.removeProperty("--rms-sab");
    return { top: sat, left: sal, right: sar, bottom: sab };
  });
  return insets;
}
function getComputedValue(computed, property) {
  const strValue = computed.getPropertyValue(property).replace("px", "").trim();
  return parseInt(strValue, 10) || 0;
}

// src/hooks/use-modal-effect.ts
function useModalEffect({
  y,
  detent,
  rootId: _rootId,
  sheetHeight,
  snapPoints,
  startThreshold
}) {
  const insetTop = useSafeAreaInsets().top;
  let rootId = _rootId;
  if (rootId && detent === "full") {
    console.warn('Using "full" detent with modal effect is not supported.');
    rootId = void 0;
  }
  useIsomorphicLayoutEffect(() => {
    return () => {
      if (rootId) cleanupModalEffect(rootId);
    };
  }, []);
  useIsomorphicLayoutEffect(() => {
    if (!rootId) return;
    const root = document.querySelector(`#${rootId}`);
    if (!root) return;
    const removeStartListener = y.on("animationStart", () => {
      setupModalEffect(rootId);
    });
    const removeChangeListener = y.on("change", (yValue) => {
      if (!root) return;
      let progress = Math.max(0, 1 - yValue / sheetHeight);
      const snapThresholdPoint = snapPoints.length > 1 ? snapPoints[snapPoints.length - 2] : void 0;
      if (snapThresholdPoint !== void 0) {
        const snapThresholdValue = snapThresholdPoint.snapValueY;
        if (yValue <= snapThresholdValue) {
          progress = (snapThresholdValue - yValue) / snapThresholdValue;
        } else {
          progress = 0;
        }
      }
      if (startThreshold !== void 0) {
        const startThresholdValue = sheetHeight - Math.min(Math.floor(startThreshold * sheetHeight), sheetHeight);
        if (yValue <= startThresholdValue) {
          progress = (startThresholdValue - yValue) / startThresholdValue;
        } else {
          progress = 0;
        }
      }
      progress = Math.max(0, Math.min(1, progress));
      const pageWidth = window.innerWidth;
      const ty = motion.transform(progress, [0, 1], [0, 24 + insetTop]);
      const s = motion.transform(progress, [0, 1], [1, (pageWidth - 16) / pageWidth]);
      const borderRadius = motion.transform(progress, [0, 1], [0, 10]);
      root.style.transform = `scale(${s}) translate3d(0, ${ty}px, 0)`;
      root.style.borderTopRightRadius = `${borderRadius}px`;
      root.style.borderTopLeftRadius = `${borderRadius}px`;
    });
    function onCompleted() {
      if (y.get() - 5 >= sheetHeight) {
        cleanupModalEffect(rootId);
      }
    }
    const removeCompleteListener = y.on("animationComplete", onCompleted);
    const removeCancelListener = y.on("animationCancel", onCompleted);
    return () => {
      removeStartListener();
      removeChangeListener();
      removeCompleteListener();
      removeCancelListener();
    };
  }, [y, rootId, insetTop, startThreshold, sheetHeight]);
}
function setupModalEffect(rootId) {
  const root = document.querySelector(`#${rootId}`);
  const body = document.querySelector("body");
  if (!root) return;
  body.style.backgroundColor = "#000";
  root.style.overflow = "hidden";
  root.style.transitionTimingFunction = "cubic-bezier(0.32, 0.72, 0, 1)";
  root.style.transitionProperty = "transform, border-radius";
  root.style.transitionDuration = "0.5s";
  root.style.transformOrigin = "center top";
}
function cleanupModalEffect(rootId) {
  const root = document.querySelector(`#${rootId}`);
  const body = document.querySelector("body");
  if (!root) return;
  body.style.removeProperty("background-color");
  root.style.removeProperty("overflow");
  root.style.removeProperty("transition-timing-function");
  root.style.removeProperty("transition-property");
  root.style.removeProperty("transition-duration");
  root.style.removeProperty("transform-origin");
  root.style.removeProperty("transform");
  root.style.removeProperty("border-top-right-radius");
  root.style.removeProperty("border-top-left-radius");
}

// src/hooks/use-prevent-scroll.ts
var KEYBOARD_BUFFER = 24;
function chain(...callbacks) {
  return (...args) => {
    for (const callback of callbacks) {
      if (typeof callback === "function") {
        callback(...args);
      }
    }
  };
}
var visualViewport = typeof document !== "undefined" && window.visualViewport;
function isScrollable(node, checkForOverflow) {
  if (!node) {
    return false;
  }
  const style = window.getComputedStyle(node);
  let isScrollable2 = /(auto|scroll)/.test(
    style.overflow + style.overflowX + style.overflowY
  );
  if (isScrollable2 && checkForOverflow) {
    isScrollable2 = node.scrollHeight !== node.clientHeight || node.scrollWidth !== node.clientWidth;
  }
  return isScrollable2;
}
function getScrollParent(node, checkForOverflow) {
  let scrollableNode = node;
  if (isScrollable(scrollableNode, checkForOverflow)) {
    scrollableNode = scrollableNode.parentElement;
  }
  while (scrollableNode && !isScrollable(scrollableNode, checkForOverflow)) {
    scrollableNode = scrollableNode.parentElement;
  }
  return scrollableNode || document.scrollingElement || document.documentElement;
}
var nonTextInputTypes = /* @__PURE__ */ new Set([
  "checkbox",
  "radio",
  "range",
  "color",
  "file",
  "image",
  "button",
  "submit",
  "reset"
]);
var preventScrollCount = 0;
var restore;
function usePreventScroll(options = {}) {
  const { isDisabled } = options;
  useIsomorphicLayoutEffect(() => {
    if (isDisabled) {
      return;
    }
    preventScrollCount++;
    if (preventScrollCount === 1) {
      if (isIOS()) {
        restore = preventScrollMobileSafari();
      } else {
        restore = preventScrollStandard();
      }
    }
    return () => {
      preventScrollCount--;
      if (preventScrollCount === 0) {
        restore == null ? void 0 : restore();
      }
    };
  }, [isDisabled]);
}
function preventScrollStandard() {
  return chain(
    setStyle(
      document.documentElement,
      "paddingRight",
      `${window.innerWidth - document.documentElement.clientWidth}px`
    ),
    setStyle(document.documentElement, "overflow", "hidden")
  );
}
function preventScrollMobileSafari() {
  let scrollable;
  let lastY = 0;
  const onTouchStart = (e) => {
    var _a;
    const target = (_a = e.composedPath()) == null ? void 0 : _a[0];
    scrollable = getScrollParent(target, true);
    if (scrollable === document.documentElement && scrollable === document.body) {
      return;
    }
    lastY = e.changedTouches[0].pageY;
  };
  const onTouchMove = (e) => {
    if (scrollable === void 0) {
      return;
    }
    if (!scrollable || scrollable === document.documentElement || scrollable === document.body) {
      e.preventDefault();
      return;
    }
    const y = e.changedTouches[0].pageY;
    const scrollTop = scrollable.scrollTop;
    const bottom = scrollable.scrollHeight - scrollable.clientHeight;
    if (bottom === 0) {
      return;
    }
    if (scrollTop <= 0 && y > lastY || scrollTop >= bottom && y < lastY) {
      e.preventDefault();
    }
    lastY = y;
  };
  const onTouchEnd = (e) => {
    var _a;
    const target = (_a = e.composedPath()) == null ? void 0 : _a[0];
    if (willOpenKeyboard(target) && target !== document.activeElement) {
      e.preventDefault();
      target.style.transform = "translateY(-2000px)";
      target.focus();
      requestAnimationFrame(() => {
        target.style.transform = "";
      });
    }
  };
  const onFocus = (e) => {
    var _a;
    const target = (_a = e.composedPath()) == null ? void 0 : _a[0];
    if (willOpenKeyboard(target)) {
      target.style.transform = "translateY(-2000px)";
      requestAnimationFrame(() => {
        target.style.transform = "";
        if (visualViewport) {
          if (visualViewport.height < window.innerHeight) {
            requestAnimationFrame(() => {
              scrollIntoView(target);
            });
          } else {
            visualViewport.addEventListener(
              "resize",
              () => scrollIntoView(target),
              { once: true }
            );
          }
        }
      });
    }
  };
  const onWindowScroll = () => {
    window.scrollTo(0, 0);
  };
  const scrollX = window.pageXOffset;
  const scrollY = window.pageYOffset;
  const restoreStyles = chain(
    setStyle(
      document.documentElement,
      "paddingRight",
      `${window.innerWidth - document.documentElement.clientWidth}px`
    ),
    setStyle(document.documentElement, "overflow", "hidden"),
    setStyle(document.body, "marginTop", `-${scrollY}px`)
  );
  window.scrollTo(0, 0);
  const removeEvents = chain(
    addEvent(document, "touchstart", onTouchStart, {
      passive: false,
      capture: true
    }),
    addEvent(document, "touchmove", onTouchMove, {
      passive: false,
      capture: true
    }),
    addEvent(document, "touchend", onTouchEnd, {
      passive: false,
      capture: true
    }),
    addEvent(document, "focus", onFocus, true),
    addEvent(window, "scroll", onWindowScroll)
  );
  return () => {
    restoreStyles();
    removeEvents();
    window.scrollTo(scrollX, scrollY);
  };
}
function setStyle(element, style, value) {
  const cur = element.style[style];
  element.style[style] = value;
  return () => {
    element.style[style] = cur;
  };
}
function addEvent(target, event, handler, options) {
  target.addEventListener(event, handler, options);
  return () => {
    target.removeEventListener(event, handler, options);
  };
}
function scrollIntoView(target) {
  const root = document.scrollingElement || document.documentElement;
  while (target && target !== root) {
    const scrollable = getScrollParent(target);
    if (scrollable !== document.documentElement && scrollable !== document.body && scrollable !== target) {
      const scrollableTop = scrollable.getBoundingClientRect().top;
      const targetTop = target.getBoundingClientRect().top;
      const targetBottom = target.getBoundingClientRect().bottom;
      const keyboardHeight = scrollable.getBoundingClientRect().bottom + KEYBOARD_BUFFER;
      if (targetBottom > keyboardHeight) {
        scrollable.scrollTop += targetTop - scrollableTop;
      }
    }
    target = scrollable.parentElement;
  }
}
function willOpenKeyboard(target) {
  return target instanceof HTMLInputElement && !nonTextInputTypes.has(target.type) || target instanceof HTMLTextAreaElement || target instanceof HTMLElement && target.isContentEditable;
}
function useSheetState({
  isOpen,
  onClosed: _onClosed,
  onOpening: _onOpening,
  onOpen: _onOpen,
  onClosing: _onClosing
}) {
  const [state, setState] = React4.useState(isOpen ? "opening" : "closed");
  const onClosed = useStableCallback(() => _onClosed == null ? void 0 : _onClosed());
  const onOpening = useStableCallback(() => _onOpening == null ? void 0 : _onOpening());
  const onOpen = useStableCallback(() => _onOpen == null ? void 0 : _onOpen());
  const onClosing = useStableCallback(() => _onClosing == null ? void 0 : _onClosing());
  React4.useEffect(() => {
    if (isOpen && state === "closed") {
      setState("opening");
    } else if (!isOpen && (state === "open" || state === "opening")) {
      setState("closing");
    }
  }, [isOpen, state]);
  React4.useEffect(() => {
    async function handle() {
      switch (state) {
        case "closed":
          await (onClosed == null ? void 0 : onClosed());
          break;
        case "opening":
          await (onOpening == null ? void 0 : onOpening());
          setState("open");
          break;
        case "open":
          await (onOpen == null ? void 0 : onOpen());
          break;
        case "closing":
          await (onClosing == null ? void 0 : onClosing());
          setState("closed");
          break;
      }
    }
    handle().catch((error) => {
      console.error("Internal sheet state error:", error);
    });
  }, [state]);
  return state;
}
function useVirtualKeyboard(options = {}) {
  const {
    containerRef,
    isEnabled = true,
    debounceDelay = 100,
    includeContentEditable = true,
    visualViewportThreshold = 100
  } = options;
  const [state, setState] = React4.useState({
    isVisible: false,
    height: 0
  });
  const focusedElementRef = React4.useRef(null);
  const debounceTimer = React4.useRef(null);
  const isTextInput = useStableCallback((el) => {
    return (el == null ? void 0 : el.tagName) === "INPUT" || (el == null ? void 0 : el.tagName) === "TEXTAREA" || includeContentEditable && el instanceof HTMLElement && el.isContentEditable;
  });
  React4.useEffect(() => {
    if (!isEnabled) return;
    const vv = window.visualViewport;
    const vk = navigator.virtualKeyboard;
    function setKeyboardInsetHeightEnv(height) {
      const element = (containerRef == null ? void 0 : containerRef.current) || document.documentElement;
      if (window.isSecureContext) {
        element.style.setProperty(
          "--keyboard-inset-height",
          `env(keyboard-inset-height, ${height}px)`
        );
      } else {
        element.style.setProperty("--keyboard-inset-height", `${height}px`);
      }
    }
    function handleFocusIn(e) {
      if (e.target instanceof HTMLElement && isTextInput(e.target)) {
        focusedElementRef.current = e.target;
        updateKeyboardState();
      }
    }
    function handleFocusOut() {
      focusedElementRef.current = null;
      updateKeyboardState();
    }
    function updateKeyboardState() {
      if (debounceTimer.current) {
        clearTimeout(debounceTimer.current);
      }
      debounceTimer.current = setTimeout(() => {
        const active = focusedElementRef.current;
        const inputIsFocused = isTextInput(active);
        if (!inputIsFocused) {
          setKeyboardInsetHeightEnv(0);
          setState({ isVisible: false, height: 0 });
          return;
        }
        if (vv) {
          const heightDiff = window.innerHeight - vv.height;
          if (heightDiff > visualViewportThreshold) {
            setKeyboardInsetHeightEnv(heightDiff);
            setState({ isVisible: true, height: heightDiff });
          } else {
            setKeyboardInsetHeightEnv(0);
            setState({ isVisible: false, height: 0 });
          }
        }
      }, debounceDelay);
    }
    window.addEventListener("focusin", handleFocusIn);
    window.addEventListener("focusout", handleFocusOut);
    if (vv) {
      vv.addEventListener("resize", updateKeyboardState);
      vv.addEventListener("scroll", updateKeyboardState);
    }
    let currentOverlaysContent = false;
    if (vk) {
      currentOverlaysContent = vk.overlaysContent;
      vk.overlaysContent = true;
    }
    return () => {
      window.removeEventListener("focusin", handleFocusIn);
      window.removeEventListener("focusout", handleFocusOut);
      if (vv) {
        vv.removeEventListener("resize", updateKeyboardState);
        vv.removeEventListener("scroll", updateKeyboardState);
      }
      if (vk) {
        vk.overlaysContent = currentOverlaysContent;
      }
      if (debounceTimer.current) {
        clearTimeout(debounceTimer.current);
      }
    };
  }, [
    debounceDelay,
    includeContentEditable,
    isEnabled,
    visualViewportThreshold
  ]);
  return {
    keyboardHeight: state.height,
    isKeyboardOpen: state.isVisible
  };
}

// src/snap.ts
function computeSnapPoints({
  snapPointsProp,
  sheetHeight
}) {
  if (snapPointsProp[0] !== 0) {
    console.error(
      `First snap point should be 0 to ensure the sheet can be fully closed. Got: [${snapPointsProp.join(", ")}]`
    );
    snapPointsProp.unshift(0);
  }
  if (snapPointsProp[snapPointsProp.length - 1] !== 1) {
    console.error(
      `Last snap point should be 1 to ensure the sheet can be fully opened. Got: [${snapPointsProp.join(", ")}]`
    );
    snapPointsProp.push(1);
  }
  if (sheetHeight <= 0) {
    console.error(
      `Sheet height is ${sheetHeight}, cannot compute snap points. Make sure the sheet is mounted and has a valid height.`
    );
    return [];
  }
  const snapPointValues = snapPointsProp.map((point) => {
    if (point > 0 && point <= 1) {
      return Math.round(point * sheetHeight);
    }
    return point < 0 ? sheetHeight + point : point;
  });
  console.assert(
    isAscendingOrder(snapPointValues),
    `Snap points need to be in ascending order got: [${snapPointsProp.join(", ")}]`
  );
  snapPointValues.forEach((snap) => {
    if (snap < 0 || snap > sheetHeight) {
      console.warn(
        `Snap point ${snap} is outside of the sheet height ${sheetHeight}. This can cause unexpected behavior. Consider adjusting your snap points.`
      );
    }
  });
  if (!snapPointValues.includes(sheetHeight)) {
    console.warn(
      "Snap points do not include the sheet height.Please include `1` as the last snap point or it will be included automatically.This is to ensure the sheet can be fully opened."
    );
    snapPointValues.push(sheetHeight);
  }
  return snapPointValues.map((snap, index) => ({
    snapIndex: index,
    snapValue: snap,
    // Absolute value from the bottom of the sheet
    snapValueY: sheetHeight - snap
    // Y value is inverted as `y = 0` means sheet is at the top
  }));
}
function findClosestSnapPoint({
  snapPoints,
  currentY
}) {
  return snapPoints.reduce(
    (closest, snap) => Math.abs(snap.snapValueY - currentY) < Math.abs(closest.snapValueY - currentY) ? snap : closest
  );
}
function findNextSnapPointInDirection({
  y,
  snapPoints,
  dragDirection
}) {
  if (dragDirection === "down") {
    return snapPoints.slice().reverse().find((s) => s.snapValueY > y);
  } else {
    return snapPoints.find((s) => s.snapValueY < y);
  }
}
function handleHighVelocityDrag({
  dragDirection,
  snapPoints
}) {
  const bottomSnapPoint = snapPoints[0];
  const topSnapPoint = snapPoints[snapPoints.length - 1];
  if (dragDirection === "down") {
    return {
      yTo: bottomSnapPoint.snapValueY,
      snapIndex: bottomSnapPoint.snapIndex
    };
  }
  return {
    yTo: topSnapPoint.snapValueY,
    snapIndex: topSnapPoint.snapIndex
  };
}
function handleLowVelocityDrag({
  currentSnapPoint,
  currentY,
  dragDirection,
  snapPoints,
  velocity
}) {
  const closestSnapRelativeToCurrentY = findClosestSnapPoint({
    snapPoints,
    currentY
  });
  if (Math.abs(velocity) < 20) {
    return {
      yTo: closestSnapRelativeToCurrentY.snapValueY,
      snapIndex: closestSnapRelativeToCurrentY.snapIndex
    };
  }
  const nextSnapInDirectionRelativeToCurrentY = findNextSnapPointInDirection({
    y: currentY,
    snapPoints,
    dragDirection
  });
  if (nextSnapInDirectionRelativeToCurrentY) {
    return {
      yTo: nextSnapInDirectionRelativeToCurrentY.snapValueY,
      snapIndex: nextSnapInDirectionRelativeToCurrentY.snapIndex
    };
  }
  return {
    yTo: currentSnapPoint.snapValueY,
    snapIndex: currentSnapPoint.snapIndex
  };
}

// src/sheet.tsx
var Sheet = React4.forwardRef(
  ({
    avoidKeyboard = true,
    children,
    className = "",
    detent = "default",
    disableDismiss = false,
    disableDrag: disableDragProp = false,
    disableScrollLocking = false,
    dragCloseThreshold = DEFAULT_DRAG_CLOSE_THRESHOLD,
    dragVelocityThreshold = DEFAULT_DRAG_VELOCITY_THRESHOLD,
    initialSnap,
    isOpen,
    modalEffectRootId,
    modalEffectThreshold,
    mountPoint,
    prefersReducedMotion = false,
    snapPoints: snapPointsProp,
    style,
    tweenConfig = DEFAULT_TWEEN_CONFIG,
    unstyled = false,
    onOpenStart,
    onOpenEnd,
    onClose,
    onCloseStart,
    onCloseEnd,
    onSnap,
    onDrag: onDragProp,
    onDragStart: onDragStartProp,
    onDragEnd: onDragEndProp,
    ...rest
  }, ref) => {
    const [sheetBoundsRef, sheetBounds] = useMeasure__default.default();
    const sheetRef = React4.useRef(null);
    const sheetHeight = Math.round(sheetBounds.height);
    const [currentSnap, setCurrentSnap] = React4.useState(initialSnap);
    const snapPoints = snapPointsProp && sheetHeight > 0 ? computeSnapPoints({ sheetHeight, snapPointsProp }) : [];
    const { windowHeight } = useDimensions();
    const closedY = sheetHeight > 0 ? sheetHeight : windowHeight;
    const y = react.useMotionValue(closedY);
    const yInverted = react.useTransform(y, (val) => Math.max(sheetHeight - val, 0));
    const indicatorRotation = react.useMotionValue(0);
    const shouldReduceMotion = react.useReducedMotion();
    const reduceMotion = Boolean(prefersReducedMotion || shouldReduceMotion);
    const animationOptions = {
      type: "tween",
      ...reduceMotion ? REDUCED_MOTION_TWEEN_CONFIG : tweenConfig
    };
    const keyboard = useVirtualKeyboard({
      isEnabled: isOpen && avoidKeyboard,
      containerRef: sheetRef
    });
    const disableDrag = keyboard.isKeyboardOpen || disableDragProp;
    const zIndex = react.useTransform(
      y,
      (val) => val + 2 >= closedY ? -1 : (style == null ? void 0 : style.zIndex) ?? 9999
    );
    const visibility = react.useTransform(
      y,
      (val) => val + 2 >= closedY ? "hidden" : "visible"
    );
    const updateSnap = useStableCallback((snapIndex) => {
      setCurrentSnap(snapIndex);
      onSnap == null ? void 0 : onSnap(snapIndex);
    });
    const getSnapPoint = useStableCallback((snapIndex) => {
      if (snapPointsProp && snapPoints) {
        if (snapIndex < 0 || snapIndex >= snapPoints.length) {
          console.warn(
            `Invalid snap index ${snapIndex}. Snap points are: [${snapPointsProp.join(", ")}] and their computed values are: [${snapPoints.map((point) => point.snapValue).join(", ")}]`
          );
          return null;
        }
        return snapPoints[snapIndex];
      }
      return null;
    });
    const snapTo = useStableCallback(async (snapIndex) => {
      if (!snapPointsProp) {
        console.warn("Snapping is not possible without `snapPoints` prop.");
        return;
      }
      const snapPoint = getSnapPoint(snapIndex);
      if (snapPoint === null) {
        console.warn(`Invalid snap index ${snapIndex}.`);
        return;
      }
      if (snapIndex === 0) {
        onClose();
        return;
      }
      await react.animate(y, snapPoint.snapValueY, {
        ...animationOptions,
        onComplete: () => updateSnap(snapIndex)
      });
    });
    const blurActiveInput = useStableCallback(() => {
      const focusedElement = document.activeElement;
      if (!focusedElement || !sheetRef.current) return;
      const isInput = focusedElement.tagName === "INPUT" || focusedElement.tagName === "TEXTAREA";
      if (isInput && sheetRef.current.contains(focusedElement)) {
        focusedElement.blur();
      }
    });
    const onDrag = useStableCallback((event, info) => {
      onDragProp == null ? void 0 : onDragProp(event, info);
      const currentY = y.get();
      const velocity = y.getVelocity();
      if (velocity > 0) indicatorRotation.set(10);
      if (velocity < 0) indicatorRotation.set(-10);
      y.set(Math.max(currentY + info.delta.y, 0));
    });
    const onDragStart = useStableCallback((event, info) => {
      blurActiveInput();
      onDragStartProp == null ? void 0 : onDragStartProp(event, info);
    });
    const onDragEnd = useStableCallback((event, info) => {
      blurActiveInput();
      onDragEndProp == null ? void 0 : onDragEndProp(event, info);
      const currentY = y.get();
      let yTo = 0;
      const currentSnapPoint = currentSnap !== void 0 ? getSnapPoint(currentSnap) : null;
      if (currentSnapPoint) {
        const dragOffsetDirection = info.offset.y > 0 ? "down" : "up";
        const dragVelocityDirection = info.velocity.y > 0 ? "down" : "up";
        const isHighVelocity = Math.abs(info.velocity.y) > dragVelocityThreshold;
        let result;
        if (isHighVelocity) {
          result = handleHighVelocityDrag({
            snapPoints,
            dragDirection: dragVelocityDirection
          });
        } else {
          result = handleLowVelocityDrag({
            currentSnapPoint,
            currentY,
            dragDirection: dragOffsetDirection,
            snapPoints,
            velocity: info.velocity.y
          });
        }
        yTo = result.yTo;
        if (disableDismiss && yTo + 1 >= sheetHeight) {
          const bottomSnapPoint = snapPoints.find((s) => s.snapValue > 0);
          if (bottomSnapPoint) {
            yTo = bottomSnapPoint.snapValueY;
            updateSnap(bottomSnapPoint.snapIndex);
          } else {
            yTo = currentY;
          }
        } else if (result.snapIndex !== void 0) {
          updateSnap(result.snapIndex);
        }
      } else if (info.velocity.y > dragVelocityThreshold || currentY > sheetHeight * dragCloseThreshold) {
        if (disableDismiss) {
          yTo = 0;
        } else {
          yTo = closedY;
        }
      }
      react.animate(y, yTo, animationOptions);
      if (yTo + 1 >= sheetHeight && !disableDismiss) {
        onClose();
      }
      indicatorRotation.set(0);
    });
    React4.useImperativeHandle(ref, () => ({
      y,
      yInverted,
      height: sheetHeight,
      snapTo
    }));
    useModalEffect({
      y,
      detent,
      sheetHeight,
      snapPoints,
      rootId: modalEffectRootId,
      startThreshold: modalEffectThreshold
    });
    usePreventScroll({
      isDisabled: disableScrollLocking || !isOpen
    });
    const state = useSheetState({
      isOpen,
      onOpen: async () => {
        onOpenStart == null ? void 0 : onOpenStart();
        await waitForElement("react-modal-sheet-container");
        const initialSnapPoint = initialSnap !== void 0 ? getSnapPoint(initialSnap) : null;
        const yTo = (initialSnapPoint == null ? void 0 : initialSnapPoint.snapValueY) ?? 0;
        await react.animate(y, yTo, animationOptions);
        if (initialSnap !== void 0) {
          updateSnap(initialSnap);
        }
        onOpenEnd == null ? void 0 : onOpenEnd();
      },
      onClosing: async () => {
        onCloseStart == null ? void 0 : onCloseStart();
        await react.animate(y, closedY, animationOptions);
        onCloseEnd == null ? void 0 : onCloseEnd();
      }
    });
    const dragProps = {
      drag: "y",
      dragElastic: 0,
      dragMomentum: false,
      dragPropagation: false,
      onDrag,
      onDragStart,
      onDragEnd
    };
    const context = {
      currentSnap,
      detent,
      disableDrag,
      dragProps,
      indicatorRotation,
      avoidKeyboard,
      sheetBoundsRef,
      sheetRef,
      unstyled,
      y
    };
    const sheet = /* @__PURE__ */ React4__default.default.createElement(SheetContext.Provider, { value: context }, /* @__PURE__ */ React4__default.default.createElement(
      react.motion.div,
      {
        ...rest,
        ref,
        "data-sheet-state": state,
        className: `react-modal-sheet-root ${className}`,
        style: {
          ...applyStyles(styles.root, unstyled),
          zIndex,
          visibility,
          ...style
        }
      },
      state !== "closed" ? children : null
    ));
    if (IS_SSR) return sheet;
    return reactDom.createPortal(sheet, mountPoint ?? document.body);
  }
);
Sheet.displayName = "Sheet";

// src/index.tsx
var Sheet2 = Object.assign(Sheet, {
  Container: SheetContainer,
  Header: SheetHeader,
  DragIndicator: SheetDragIndicator,
  Content: SheetContent,
  Backdrop: SheetBackdrop
});

exports.Sheet = Sheet2;
exports.useScrollPosition = useScrollPosition;
exports.useVirtualKeyboard = useVirtualKeyboard;
//# sourceMappingURL=index.js.map
//# sourceMappingURL=index.js.map