"use strict";

import { forwardRef, useImperativeHandle, useRef, useEffect, useState, useCallback, useMemo } from 'react';
import { View, StyleSheet, Modal, Pressable, Dimensions, Platform } from 'react-native';
import { Gesture, GestureDetector, GestureHandlerRootView } from 'react-native-gesture-handler';
import Animated, { interpolate, runOnJS, useAnimatedScrollHandler, useAnimatedStyle, useSharedValue, withSpring, withTiming } from 'react-native-reanimated';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useTheme } from "../theme/use-theme.js";

// Keyboard handler — only on native platforms. On web, keyboard events are handled by the browser.
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const noopKeyboardHandler = (_handlers, _deps) => {};
let useKeyboardHandler = noopKeyboardHandler;
if (Platform.OS !== 'web' && typeof require !== 'undefined') {
  try {
    const moduleName = 'react-native-keyboard-controller';
    useKeyboardHandler = require(moduleName).useKeyboardHandler;
  } catch {
    // react-native-keyboard-controller not available
  }
}

/** Hook that returns current screen dimensions and updates on rotation/resize. */
function useScreenDimensions() {
  const [dimensions, setDimensions] = useState(() => Dimensions.get('window'));
  useEffect(() => {
    const subscription = Dimensions.addEventListener('change', ({
      window
    }) => {
      setDimensions(window);
    });
    return () => subscription.remove();
  }, []);
  return dimensions;
}
const SPRING_CONFIG = {
  damping: 25,
  stiffness: 300,
  mass: 0.8
};
const BottomSheet = /*#__PURE__*/forwardRef((props, ref) => {
  const {
    children,
    onDismiss,
    enablePanDownToClose = true,
    backgroundComponent,
    backdropComponent,
    style,
    enableHandlePanningGesture = true,
    onDismissAttempt,
    detached = false,
    showHandle = true,
    backdropOpacity = 0.5,
    scrollable = true,
    manualActivation = false,
    dynamicBackdrop = false,
    handleComponent
  } = props;
  const insets = useSafeAreaInsets();
  const theme = useTheme();
  const {
    colors
  } = theme;
  const {
    height: screenHeight
  } = useScreenDimensions();
  const [visible, setVisible] = useState(false);
  const [rendered, setRendered] = useState(false); // keep mounted for exit animation
  const closeTimeoutRef = useRef(null);
  const hasClosedRef = useRef(false);
  const scrollViewRef = useRef(null);
  /**
   * Monotonically increasing counter that identifies "the current close
   * attempt". Bumped every time the sheet re-opens (`present()`), so any
   * in-flight `withTiming` completion callback or fallback timer from a
   * PREVIOUS close cycle becomes a no-op. Without this guard, a stale
   * `runOnJS(finishClose)` from an aborted close would fire `onDismiss`
   * and unmount the sheet immediately after the user opens it again,
   * causing "tap to open does nothing" reports in production.
   */
  const closeGenerationRef = useRef(0);
  const screenHeightSV = useSharedValue(screenHeight);
  // Keep shared value in sync when screen dimensions change (rotation/resize)
  useEffect(() => {
    screenHeightSV.value = screenHeight;
  }, [screenHeight, screenHeightSV]);
  const translateY = useSharedValue(screenHeight);
  const opacity = useSharedValue(0);
  const scrollOffsetY = useSharedValue(0);
  const isScrollAtTop = useSharedValue(true);
  const allowPanClose = useSharedValue(true);
  const keyboardHeight = useSharedValue(0);
  // Stores the sheet's `translateY` captured at the moment a pan gesture
  // begins, so `onUpdate` can offset from the starting position. This MUST
  // be a primitive shared value, not an object-valued one. Under
  // react-native-worklets 0.8.x (Reanimated 4), assigning a fresh object
  // literal to an object-valued shared value's `.value` inside a worklet
  // freezes the object (`freezeObjectInDev`) and routes the mutation through
  // the serializer's listener machinery — which then tries to call the
  // non-worklet `removeListener` synchronously on the UI thread and crashes
  // ("Tried to synchronously call a non-worklet function `removeListener`").
  // A scalar shared value sidesteps all object serialization.
  const contextY = useSharedValue(0);
  // Mirror of `closeGenerationRef` for worklet access. Bumped from the JS
  // thread in lockstep with the ref so gesture worklets always see the
  // current generation when they snapshot it on `onEnd`.
  const closeGeneration = useSharedValue(0);
  // Used by `manualActivation` body pan to track the touch's initial Y so
  // it can compute downward distance for the activation decision.
  const touchStartY = useSharedValue(0);

  // Refs used to mark the handle pan and the body pan as mutually
  // simultaneous (manualActivation mode only). Without this RNGH treats them
  // as racing gestures and a touch that begins in the handle area could be
  // claimed by whichever recognizer activates first — leading to
  // inconsistent drag start.
  const bodyPanRef = useRef(undefined);
  const handlePanRef = useRef(undefined);
  useKeyboardHandler({
    onMove: e => {
      'worklet';

      keyboardHeight.value = e.height;
    },
    onEnd: e => {
      'worklet';

      keyboardHeight.value = e.height;
    }
  }, []);

  // Dismiss callbacks
  const safeClose = useCallback(() => {
    if (onDismissAttempt?.()) {
      onDismiss?.();
    } else if (!onDismissAttempt) {
      onDismiss?.();
    }
  }, [onDismissAttempt, onDismiss]);

  // Mirror `safeClose` and `rendered` into refs so the unmount cleanup can
  // fire the latest dismiss callback when needed, without re-binding the
  // cleanup effect on every render.
  const safeCloseRef = useRef(safeClose);
  useEffect(() => {
    safeCloseRef.current = safeClose;
  }, [safeClose]);
  const renderedRef = useRef(rendered);
  useEffect(() => {
    renderedRef.current = rendered;
  }, [rendered]);

  /**
   * Commit a close. Two guards prevent stale callbacks from firing:
   *   1. `hasClosedRef` — protects against the fallback timer AND the
   *      animation callback both racing to call us within a single close
   *      cycle.
   *   2. `generation` — protects against a callback from a PREVIOUS close
   *      cycle firing AFTER the user reopened. If the live generation has
   *      advanced past the one captured when the close started, this
   *      callback is from a cycle that the user has implicitly cancelled
   *      by reopening — silently drop it.
   */
  const finishClose = useCallback(generation => {
    if (closeGenerationRef.current !== generation) return;
    if (hasClosedRef.current) return;
    hasClosedRef.current = true;
    safeClose();
    setRendered(false);
  }, [safeClose]);
  useEffect(() => {
    if (visible) {
      if (closeTimeoutRef.current) {
        clearTimeout(closeTimeoutRef.current);
        closeTimeoutRef.current = null;
      }
      hasClosedRef.current = false;
      // Bump generation: any pending close-completion callback from a
      // prior cycle (animation or fallback timer) will now no-op when
      // it eventually fires, because its captured generation is stale.
      closeGenerationRef.current += 1;
      closeGeneration.value = closeGenerationRef.current;
      opacity.value = withTiming(1, {
        duration: 250
      });
      translateY.value = withSpring(0, SPRING_CONFIG);
    } else if (rendered) {
      // Capture the generation for THIS close cycle so the animation
      // callback (running on the UI thread, scheduled back to JS) and
      // the fallback timer agree on which cycle they belong to.
      const generation = closeGenerationRef.current;
      opacity.value = withTiming(0, {
        duration: 250
      }, finished => {
        if (finished) {
          runOnJS(finishClose)(generation);
        }
      });
      translateY.value = withSpring(screenHeight, {
        ...SPRING_CONFIG,
        stiffness: 250
      });

      // Fallback timer to ensure close completes (especially on web
      // where reanimated callbacks occasionally drop on tab blur).
      if (closeTimeoutRef.current) {
        clearTimeout(closeTimeoutRef.current);
      }
      closeTimeoutRef.current = setTimeout(() => {
        finishClose(generation);
        closeTimeoutRef.current = null;
      }, 300);
    }
  }, [visible, rendered, finishClose, screenHeight, closeGeneration, opacity, translateY]);

  // On unmount: ensure pending close callbacks (e.g. consumer's `onDismiss`)
  // still fire if the BS is yanked mid-animation by a parent re-render.
  // Without this, `Dialog`'s `handleDismiss` never runs and queued
  // callbacks (post-close handlers) are silently lost.
  // Only fires when the sheet was actually rendered (open or closing) to
  // avoid spuriously calling onDismiss on bare unmount of a never-opened
  // sheet. Refs are read inside the cleanup, so latest values are captured.
  useEffect(() => () => {
    if (closeTimeoutRef.current) {
      clearTimeout(closeTimeoutRef.current);
      closeTimeoutRef.current = null;
    }
    if (renderedRef.current && !hasClosedRef.current) {
      hasClosedRef.current = true;
      safeCloseRef.current();
    }
  }, []);

  // Apply web scrollbar styles when colors change; clean up on unmount
  useEffect(() => {
    if (Platform.OS === 'web') {
      createWebScrollbarStyle(colors.border);
    }
    return () => {
      removeWebScrollbarStyle();
    };
  }, [colors.border]);
  const present = useCallback(() => {
    setRendered(true);
    setVisible(true);
  }, []);
  const dismiss = useCallback(() => {
    setVisible(false);
  }, []);
  const scrollTo = useCallback((y, animated = true) => {
    scrollViewRef.current?.scrollTo({
      y,
      animated
    });
  }, []);
  useImperativeHandle(ref, () => ({
    present,
    dismiss,
    close: dismiss,
    expand: present,
    collapse: dismiss,
    scrollTo
  }), [present, dismiss, scrollTo]);
  const nativeGesture = useMemo(() => Gesture.Native(), []);

  // Body pan — two strategies, switched by `manualActivation`.
  //
  // (1) Legacy mode (`manualActivation: false`, the bloom 0.3.x default):
  //     Pan is always active. We snapshot the scroll offset at `onStart`
  //     and gate movement on `scrollOffsetY <= 8` during the gesture.
  //     This is what current bloom consumers expect.
  //
  // (2) gorhom-style mode (`manualActivation: true`):
  //     Pan uses `manualActivation(true)` and only flips to active when
  //     the inner ScrollView is at the top AND the user has moved their
  //     finger downward > 8dp. In every other case it fails, so the
  //     ScrollView keeps full ownership of the touch. This is the only
  //     RNGH 2.x pattern that does not steal vertical events from the
  //     inner scroller on Android. Required for FileManagement /
  //     PhotoPicker style sheets.
  const panGesture = useMemo(() => {
    if (manualActivation) {
      return Gesture.Pan().enabled(enablePanDownToClose).withRef(bodyPanRef).manualActivation(true).simultaneousWithExternalGesture(scrollViewRef, handlePanRef).onTouchesDown(e => {
        'worklet';

        const t = e.changedTouches[0];
        if (t) touchStartY.value = t.absoluteY;
        contextY.value = translateY.value;
      }).onTouchesMove((e, state) => {
        'worklet';

        const t = e.changedTouches[0];
        if (!t) return;
        const dy = t.absoluteY - touchStartY.value;
        const atTop = scrollOffsetY.value <= 4;
        // Activate only when (at scroll top) AND (finger has moved
        // downward by > 8dp). Any other motion: fail so the
        // ScrollView claims the gesture.
        if (atTop && dy > 8) {
          state.activate();
        } else if (dy < -4 || !atTop) {
          state.fail();
        }
      }).onUpdate(event => {
        'worklet';

        if (event.translationY < 0) return;
        const newTranslateY = contextY.value + event.translationY;
        if (newTranslateY >= 0) {
          translateY.value = newTranslateY;
        }
      }).onEnd(event => {
        'worklet';

        const velocity = event.velocityY;
        const distance = translateY.value;
        const closeThreshold = Math.max(140, screenHeightSV.value * 0.25);
        const fastSwipeThreshold = 900;
        const shouldClose = velocity > fastSwipeThreshold || distance > closeThreshold && velocity > -300;
        if (shouldClose) {
          // Snapshot the generation on the UI thread at the
          // moment the close gesture commits. The completion
          // callback only fires `finishClose` if no reopen
          // bumped the generation in between.
          const generation = closeGeneration.value;
          translateY.value = withSpring(screenHeightSV.value, {
            ...SPRING_CONFIG,
            velocity
          });
          opacity.value = withTiming(0, {
            duration: 250
          }, finished => {
            if (finished) runOnJS(finishClose)(generation);
          });
        } else {
          translateY.value = withSpring(0, {
            ...SPRING_CONFIG,
            velocity
          });
        }
      });
    }

    // Legacy always-active pan (bloom 0.3.x behaviour).
    return Gesture.Pan().enabled(enablePanDownToClose).simultaneousWithExternalGesture(nativeGesture).onStart(() => {
      'worklet';

      contextY.value = translateY.value;
      allowPanClose.value = scrollOffsetY.value <= 8;
    }).onUpdate(event => {
      'worklet';

      if (!allowPanClose.value) {
        return;
      }
      const newTranslateY = contextY.value + event.translationY;
      // If user is scrolling down while content isn't at (or near) the top, let ScrollView handle it
      const atTopOrNearTop = scrollOffsetY.value <= 8; // slightly larger tolerance for smoother handoff
      if (event.translationY > 0 && !atTopOrNearTop) {
        return;
      }
      if (newTranslateY >= 0) {
        translateY.value = newTranslateY;
      } else if (detached) {
        // Only allow overdrag (pulling up beyond top) when detached
        translateY.value = newTranslateY * 0.3;
      } else {
        // In normal mode, prevent overdrag - clamp to 0
        translateY.value = 0;
      }
    }).onEnd(event => {
      'worklet';

      if (!allowPanClose.value) {
        return;
      }
      const velocity = event.velocityY;
      const distance = translateY.value;
      // Require a deeper pull to close (more like native bottom sheets)
      const closeThreshold = Math.max(140, screenHeightSV.value * 0.25);
      const fastSwipeThreshold = 900;
      const shouldClose = velocity > fastSwipeThreshold || distance > closeThreshold && velocity > -300;
      if (shouldClose) {
        const generation = closeGeneration.value;
        translateY.value = withSpring(screenHeightSV.value, {
          ...SPRING_CONFIG,
          velocity: velocity
        });
        opacity.value = withTiming(0, {
          duration: 250
        }, finished => {
          if (finished) {
            runOnJS(finishClose)(generation);
          }
        });
      } else {
        translateY.value = withSpring(0, {
          ...SPRING_CONFIG,
          velocity: velocity
        });
      }
    });
    // Shared values are stable refs; the listed deps are the only JS-side
    // values that change the gesture's behavior. `finishClose` is stable
    // (useCallback with stable deps).
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [enablePanDownToClose, detached, manualActivation, nativeGesture, finishClose]);

  // Dedicated handle pan — only built in `manualActivation` mode. Always
  // active so users can drag the handle even while content is mid-scroll.
  // In legacy mode the body pan already wraps the whole sheet (handle
  // included), so no separate gesture is needed.
  const handlePanGesture = useMemo(() => {
    if (!manualActivation) return undefined;
    return Gesture.Pan().enabled(enablePanDownToClose && enableHandlePanningGesture).withRef(handlePanRef).simultaneousWithExternalGesture(bodyPanRef).activeOffsetY([-8, 8]).onStart(() => {
      'worklet';

      contextY.value = translateY.value;
    }).onUpdate(event => {
      'worklet';

      const newTranslateY = contextY.value + event.translationY;
      if (newTranslateY >= 0) {
        translateY.value = newTranslateY;
      } else if (detached) {
        translateY.value = newTranslateY * 0.3;
      } else {
        translateY.value = 0;
      }
    }).onEnd(event => {
      'worklet';

      const velocity = event.velocityY;
      const distance = translateY.value;
      const closeThreshold = Math.max(140, screenHeightSV.value * 0.25);
      const fastSwipeThreshold = 900;
      const shouldClose = velocity > fastSwipeThreshold || distance > closeThreshold && velocity > -300;
      if (shouldClose) {
        const generation = closeGeneration.value;
        translateY.value = withSpring(screenHeightSV.value, {
          ...SPRING_CONFIG,
          velocity
        });
        opacity.value = withTiming(0, {
          duration: 250
        }, finished => {
          if (finished) runOnJS(finishClose)(generation);
        });
      } else {
        translateY.value = withSpring(0, {
          ...SPRING_CONFIG,
          velocity
        });
      }
    });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [manualActivation, enablePanDownToClose, enableHandlePanningGesture, detached, finishClose]);

  // `opacity.value` drives the fade in/out (0 -> 1). `backdropOpacity` is the
  // final dim level once fully visible. We multiply so the consumer-provided
  // dim opacity applies smoothly across the animation. When
  // `dynamicBackdrop` is enabled, the dim also fades proportionally with
  // drag distance (iOS Photos style).
  const backdropStyle = useAnimatedStyle(() => {
    const dragFactor = dynamicBackdrop ? interpolate(translateY.value, [0, screenHeightSV.value * 0.4], [1, 0.3], 'clamp') : 1;
    return {
      opacity: opacity.value * backdropOpacity * dragFactor
    };
  }, [backdropOpacity, dynamicBackdrop]);
  const sheetStyle = useAnimatedStyle(() => {
    const scale = interpolate(translateY.value, [0, screenHeightSV.value], [1, 0.95]);
    return {
      transform: [{
        translateY: translateY.value - keyboardHeight.value
      }, {
        scale
      }]
    };
  });
  const sheetHeightStyle = useAnimatedStyle(() => ({
    maxHeight: screenHeightSV.value - keyboardHeight.value - insets.top - (detached ? insets.bottom + 16 : 0)
  }), [insets.top, insets.bottom, detached]);
  const sheetMarginStyle = useAnimatedStyle(() => {
    // Only add margin when detached, otherwise extend behind safe area
    if (detached) {
      return {
        marginBottom: keyboardHeight.value > 0 ? 16 : insets.bottom + 16
      };
    }
    return {
      marginBottom: 0
    };
  }, [insets.bottom, detached]);
  const handleBackdropPress = useCallback(() => {
    // Always animate close on backdrop press
    if (onDismissAttempt && !onDismissAttempt()) {
      return;
    }
    dismiss();
  }, [onDismissAttempt, dismiss]);
  const scrollHandler = useAnimatedScrollHandler({
    onScroll: event => {
      scrollOffsetY.value = event.contentOffset.y;
      isScrollAtTop.value = event.contentOffset.y <= 0;
    }
  });
  const dynamicStyles = useMemo(() => {
    return StyleSheet.create({
      handle: {
        ...styles.handle,
        backgroundColor: theme.isDark ? '#444' : '#C7C7CC'
      },
      sheet: {
        ...styles.sheet,
        backgroundColor: colors.background,
        ...(detached ? styles.sheetDetached : styles.sheetNormal)
      },
      scrollContent: {
        ...styles.scrollContent
        // In normal mode, don't add padding here - screens handle their own padding
        // The sheet extends behind safe area, and screens add padding as needed
      }
    });
  }, [colors.background, theme.isDark, detached]);
  if (!rendered) return null;

  // Default handle render — used when `handleComponent` is not provided.
  const renderDefaultHandle = () => /*#__PURE__*/_jsx(View, {
    style: dynamicStyles.handle
  });
  const handleNode = showHandle ? handleComponent ? handleComponent() : renderDefaultHandle() : null;

  // In `manualActivation` mode the handle gets its own gesture detector
  // sitting in a dedicated absolutely-positioned hit area at the top of the
  // sheet. In legacy mode the handle is rendered inline as a decorative
  // overlay (the body pan covers the entire sheet, handle included).
  const handleSlot = handleNode && manualActivation && handlePanGesture ? /*#__PURE__*/_jsx(GestureDetector, {
    gesture: handlePanGesture,
    children: /*#__PURE__*/_jsx(View, {
      style: styles.handleHitArea,
      accessible: true,
      accessibilityRole: "adjustable",
      children: handleNode
    })
  }) : handleNode;

  // Inner content: scrollable wraps in Animated.ScrollView, non-scrollable
  // renders children directly. In legacy mode the scrollview is also
  // wrapped in the `nativeGesture` detector for scroll/pan coordination.
  const scrollViewNode = /*#__PURE__*/_jsx(Animated.ScrollView, {
    ref: scrollViewRef,
    style: [styles.scrollView, Platform.OS === 'web' && {
      scrollbarWidth: 'thin',
      scrollbarColor: `${colors.border} transparent`
    }],
    contentContainerStyle: dynamicStyles.scrollContent,
    showsVerticalScrollIndicator: false,
    keyboardShouldPersistTaps: "handled",
    onScroll: scrollHandler,
    scrollEventThrottle: 16,
    ...(Platform.OS === 'web' ? {
      className: 'bottom-sheet-scrollview'
    } : undefined),
    onLayout: () => {
      if (Platform.OS === 'web') {
        createWebScrollbarStyle(colors.border);
      }
    },
    children: children
  });
  const bodyContent = scrollable ? manualActivation
  // In manualActivation mode the scroll view is referenced by the
  // pan's simultaneous list directly; no wrapping native gesture.
  ? scrollViewNode
  // Legacy mode: native gesture wraps the scroll view to coordinate
  // with the always-active body pan.
  : /*#__PURE__*/_jsx(GestureDetector, {
    gesture: nativeGesture,
    children: scrollViewNode
  }) : /*#__PURE__*/_jsx(View, {
    style: styles.nonScrollableContent,
    children: children
  });
  return /*#__PURE__*/_jsx(Modal, {
    visible: rendered,
    transparent: true,
    animationType: "none",
    statusBarTranslucent: true,
    onRequestClose: dismiss,
    children: /*#__PURE__*/_jsx(GestureHandlerRootView, {
      style: styles.rootView,
      children: /*#__PURE__*/_jsxs(View, {
        style: StyleSheet.absoluteFill,
        children: [/*#__PURE__*/_jsx(Animated.View, {
          style: [styles.backdrop, backdropStyle],
          children: backdropComponent ? backdropComponent({
            onPress: handleBackdropPress
          }) : /*#__PURE__*/_jsx(Pressable, {
            style: styles.backdropTouchable,
            onPress: handleBackdropPress,
            children: /*#__PURE__*/_jsx(View, {
              style: StyleSheet.absoluteFill
            })
          })
        }), /*#__PURE__*/_jsx(GestureDetector, {
          gesture: panGesture,
          children: /*#__PURE__*/_jsxs(Animated.View, {
            style: [dynamicStyles.sheet, sheetMarginStyle, sheetStyle, sheetHeightStyle, style],
            children: [backgroundComponent?.({
              style: styles.background
            }), handleSlot, bodyContent]
          })
        })]
      })
    })
  });
});
BottomSheet.displayName = 'BottomSheet';
const styles = StyleSheet.create({
  rootView: {
    flex: 1
  },
  backdrop: {
    // Color is solid black; the dim level is driven by `backdropOpacity` via
    // the animated `opacity` style on the wrapping <Animated.View>.
    flex: 1,
    backgroundColor: '#000'
  },
  backdropTouchable: {
    flex: 1
  },
  sheet: {
    position: 'absolute',
    bottom: 0,
    overflow: 'hidden',
    maxWidth: 800,
    alignSelf: 'center',
    marginHorizontal: 'auto'
  },
  sheetDetached: {
    left: 16,
    right: 16,
    borderRadius: 24
  },
  sheetNormal: {
    left: 0,
    right: 0,
    borderTopLeftRadius: 24,
    borderTopRightRadius: 24
  },
  /** Legacy (non-manualActivation) handle: decorative overlay only. */
  handle: {
    position: 'absolute',
    top: 10,
    left: '50%',
    marginLeft: -18,
    width: 36,
    height: 5,
    borderRadius: 3,
    zIndex: 100
  },
  /**
   * Hit area for the drag handle in `manualActivation` mode. Absolutely
   * positioned at the top of the sheet so the area visually "floats" above
   * the content — content scrolls up underneath it (no layout offset)
   * while the thumb can still grab the full-width 28dp strip to drag.
   */
  handleHitArea: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    height: 28,
    alignItems: 'center',
    justifyContent: 'flex-start',
    paddingTop: 6,
    zIndex: 100
  },
  background: {
    ...StyleSheet.absoluteFill
  },
  scrollView: {
    flex: 1
  },
  scrollContent: {
    flexGrow: 1
  },
  nonScrollableContent: {
    flex: 1
  }
});

// Create web scrollbar styles dynamically based on theme
const createWebScrollbarStyle = borderColor => {
  if (Platform.OS !== 'web' || typeof document === 'undefined') return;
  let styleElement = document.getElementById(SCROLLBAR_STYLE_ID);
  if (!styleElement) {
    styleElement = document.createElement('style');
    styleElement.id = SCROLLBAR_STYLE_ID;
    document.head.appendChild(styleElement);
  }

  // Derive a slightly darker scrollbar hover color from the border color
  const scrollbarColor = borderColor;
  const scrollbarHoverColor = borderColor.startsWith('hsl') ? borderColor.replace(/\)$/, ' / 0.7)') // add alpha for hover
  : '#888';
  styleElement.textContent = `
        .bottom-sheet-scrollview::-webkit-scrollbar {
            width: 6px;
        }
        .bottom-sheet-scrollview::-webkit-scrollbar-track {
            background: transparent;
            border-radius: 10px;
        }
        .bottom-sheet-scrollview::-webkit-scrollbar-thumb {
            background: ${scrollbarColor};
            border-radius: 10px;
        }
        .bottom-sheet-scrollview::-webkit-scrollbar-thumb:hover {
            background: ${scrollbarHoverColor};
        }
    `;
};
const SCROLLBAR_STYLE_ID = 'bottom-sheet-scrollbar-style';

/** Remove the injected scrollbar <style> tag on unmount. */
const removeWebScrollbarStyle = () => {
  if (Platform.OS !== 'web' || typeof document === 'undefined') return;
  document.getElementById(SCROLLBAR_STYLE_ID)?.remove();
};
export default BottomSheet;
export { BottomSheet };
//# sourceMappingURL=index.js.map