"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _react = _interopRequireWildcard(require("react"));
var _reactNative = require("react-native");
var _lodash = _interopRequireDefault(require("lodash.isequal"));
var _invariant = _interopRequireDefault(require("invariant"));
var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
var _reactNativeGestureHandler = require("react-native-gesture-handler");
var _reactNativeRedash = require("react-native-redash");
var _bottomSheetDraggableView = _interopRequireDefault(require("../bottomSheetDraggableView"));
var _bottomSheetContentWrapper = _interopRequireDefault(require("../bottomSheetContentWrapper"));
var _bottomSheetContainer = _interopRequireDefault(require("../bottomSheetContainer"));
var _bottomSheetHandleContainer = _interopRequireDefault(require("../bottomSheetHandleContainer"));
var _bottomSheetBackgroundContainer = _interopRequireDefault(require("../bottomSheetBackgroundContainer"));
var _bottomSheetBackdropContainer = _interopRequireDefault(require("../bottomSheetBackdropContainer"));
var _useTransition = require("./useTransition");
var _hooks = require("../../hooks");
var _contexts = require("../../contexts");
var _constants = require("../../constants");
var _constants2 = require("./constants");
var _styles = require("./styles");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } // @ts-nocheck
// import BottomSheetDebugView from '../bottomSheetDebugView';
const {
  interpolate: interpolateV1,
  interpolateNode: interpolateV2
} = require('react-native-reanimated');
const interpolate = interpolateV2 || interpolateV1;
_reactNativeReanimated.default.addWhitelistedUIProps({
  decelerationRate: true
});
const BottomSheetComponent = /*#__PURE__*/(0, _react.forwardRef)((props, ref) => {
  //#region validate props
  (0, _hooks.usePropsValidator)(props);
  //#endregion

  //#region extract props
  const {
    // animations configurations
    animationDuration = _constants2.DEFAULT_ANIMATION_DURATION,
    animationEasing = _constants2.DEFAULT_ANIMATION_EASING,
    // configurations
    index: _providedIndex = 0,
    snapPoints: _providedSnapPoints,
    handleHeight: _providedHandleHeight,
    containerHeight: _providedContainerHeight,
    topInset = 0,
    bottomInset = 0,
    enableContentPanningGesture = _constants2.DEFAULT_ENABLE_CONTENT_PANNING_GESTURE,
    enableHandlePanningGesture = _constants2.DEFAULT_ENABLE_HANDLE_PANNING_GESTURE,
    animateOnMount = _constants2.DEFAULT_ANIMATE_ON_MOUNT,
    style: _providedStyle,
    // animated nodes callback
    animatedPosition: _providedAnimatedPosition,
    animatedIndex: _providedAnimatedIndex,
    // callbacks
    onChange: _providedOnChange,
    onAnimate: _providedOnAnimate,
    // components
    handleComponent,
    backdropComponent,
    backgroundComponent,
    children,
    // accessibility
    accessible: _providedAccessible = _constants2.DEFAULT_ACCESSIBLE,
    accessibilityLabel: _providedAccessibilityLabel = _constants2.DEFAULT_ACCESSIBILITY_LABEL,
    accessibilityRole: _providedAccessibilityRole = _constants2.DEFAULT_ACCESSIBILITY_ROLE,
    enableAccessibilityChangeAnnouncement: _providedEnableAccessibilityChangeAnnouncement = _constants2.DEFAULT_ENABLE_ACCESSIBILITY_CHANGE_ANNOUNCEMENT,
    accessibilityPositionChangeAnnouncement: _providedAccessibilityPositionChangeAnnouncement = _constants2.DEFAULT_ACCESSIBILITY_POSITION_CHANGE_ANNOUNCEMENT,
    ...rest
  } = props;
  //#endregion

  //#region component refs
  const containerTapGestureRef = (0, _react.useRef)(null);
  //#endregion

  //#region layout variables
  // state
  const [containerHeight, setContainerHeight] = (0, _react.useState)(_providedContainerHeight);
  const [handleHeight, setHandleHeight] = (0, _react.useState)(_providedHandleHeight);

  // safe layout values

  const safeHandleHeight = (0, _react.useMemo)(() => handleComponent === null ? 0 : handleHeight || _constants2.DEFAULT_HANDLE_HEIGHT, [handleHeight, handleComponent]);
  const safeContainerHeight = (0, _react.useMemo)(() => _providedContainerHeight || containerHeight || _constants.WINDOW_HEIGHT, [_providedContainerHeight, containerHeight]);

  // conditions
  const shouldMeasureContainerHeight = (0, _react.useMemo)(() => _providedContainerHeight === undefined, [_providedContainerHeight]);
  const shouldMeasureHandleHeight = (0, _react.useMemo)(() => _providedHandleHeight === undefined && handleComponent !== undefined && handleComponent !== null, [_providedHandleHeight, handleComponent]);

  // refs
  const didSetHandleHeight = (0, _react.useRef)(!shouldMeasureHandleHeight);
  const didSetContainerHeight = (0, _react.useRef)(!shouldMeasureContainerHeight);
  const isLayoutCalculated = (0, _react.useMemo)(() => {
    return didSetHandleHeight.current && didSetContainerHeight.current;
  },
  // eslint-disable-next-line react-hooks/exhaustive-deps
  [containerHeight, handleHeight]);
  const animatedIsLayoutReady = (0, _hooks.useReactiveValue)(isLayoutCalculated ? 1 : 0);

  //#endregion

  //#region variables

  // refs
  const currentIndexRef = (0, _react.useRef)(_providedIndex);
  const isClosing = (0, _react.useRef)(false);
  const didMountOnAnimate = (0, _react.useRef)(false);
  const {
    scrollableContentOffsetY,
    setScrollableRef,
    removeScrollableRef,
    scrollToTop,
    flashScrollableIndicators
  } = (0, _hooks.useScrollable)();
  const snapPoints = (0, _hooks.useNormalizedSnapPoints)(_providedSnapPoints, safeContainerHeight, safeHandleHeight);
  const sheetHeight = (0, _react.useMemo)(() => safeContainerHeight - snapPoints[snapPoints.length - 1] - safeHandleHeight, [snapPoints, safeContainerHeight, safeHandleHeight]);
  const initialPosition = (0, _react.useMemo)(() => {
    return currentIndexRef.current < 0 || animateOnMount ? safeContainerHeight : snapPoints[currentIndexRef.current];
  }, [snapPoints, animateOnMount, safeContainerHeight]);
  const currentPositionRef = (0, _react.useRef)(initialPosition);
  //#endregion

  //#region gestures
  const {
    state: containerTapGestureState,
    gestureHandler: containerTapGestureHandler
  } = (0, _reactNativeRedash.useTapGestureHandler)();
  const {
    state: handlePanGestureState,
    translation: {
      y: handlePanGestureTranslationY
    },
    velocity: {
      y: handlePanGestureVelocityY
    },
    gestureHandler: handlePanGestureHandler
  } = (0, _reactNativeRedash.usePanGestureHandler)();
  const {
    state: contentPanGestureState,
    translation: {
      y: contentPanGestureTranslationY
    },
    velocity: {
      y: contentPanGestureVelocityY
    }
  } = (0, _reactNativeRedash.usePanGestureHandler)();
  //#endregion

  //#region animated variables
  const handleOnAnimate = (0, _hooks.useStableCallback)((fromIndex, toIndex) => {
    if (_providedOnAnimate) {
      _providedOnAnimate(fromIndex, toIndex);
    }
  });
  const {
    position,
    manualSnapToPoint,
    currentPosition,
    currentGesture
  } = (0, _useTransition.useTransition)({
    animationDuration,
    animationEasing,
    contentPanGestureState,
    contentPanGestureTranslationY,
    contentPanGestureVelocityY,
    handlePanGestureState,
    handlePanGestureTranslationY,
    handlePanGestureVelocityY,
    scrollableContentOffsetY,
    animatedIsLayoutReady,
    snapPoints,
    initialPosition,
    currentIndexRef,
    onAnimate: handleOnAnimate
  });

  // animated values
  const animatedIndex = (0, _react.useMemo)(() => {
    const adjustedSnapPoints = snapPoints.slice().reverse();
    const adjustedSnapPointsIndexes = snapPoints.slice().map((_, index) => index).reverse();

    /**
     * this been added to resolve issues when provide
     * one snap point.
     */
    if (snapPoints.length === 1) {
      adjustedSnapPoints.push(safeContainerHeight);
      adjustedSnapPointsIndexes.push(-1);
    }
    return (0, _reactNativeReanimated.cond)(animatedIsLayoutReady, interpolate(position, {
      inputRange: adjustedSnapPoints,
      outputRange: adjustedSnapPointsIndexes,
      extrapolate: _reactNativeReanimated.Extrapolate.CLAMP
    }), 0);
  }, [position, animatedIsLayoutReady, safeContainerHeight, snapPoints]);
  const animatedPosition = (0, _react.useMemo)(() => (0, _reactNativeReanimated.cond)(animatedIsLayoutReady, (0, _reactNativeReanimated.abs)((0, _reactNativeReanimated.sub)(safeContainerHeight, position)), safeContainerHeight), [safeContainerHeight, position, animatedIsLayoutReady]);

  /**
   * Scrollable animated props.
   */
  const decelerationRate = (0, _react.useMemo)(() => (0, _reactNativeReanimated.cond)((0, _reactNativeReanimated.greaterThan)(position, snapPoints[snapPoints.length - 1]), 0.001, _constants2.NORMAL_DECELERATION_RATE), [position, snapPoints]);
  //#endregion

  //#region layout callbacks
  const handleOnContainerMeasureHeight = (0, _react.useCallback)(height => {
    // 
    didSetContainerHeight.current = true;
    setContainerHeight(height);
  }, []);
  const handleOnHandleMeasureHeight = (0, _react.useCallback)(height => {
    // 
    didSetHandleHeight.current = true;
    setHandleHeight(height);
  }, []);
  //#endregion

  //#region private methods
  const refreshUIElements = (0, _react.useCallback)(() => {
    const currentPositionIndex = Math.max(currentIndexRef.current, 0);
    if (containerTapGestureRef.current) {
      // @ts-ignore
      containerTapGestureRef.current.setNativeProps({
        maxDeltaY: Math.abs(snapPoints[snapPoints.length - 1] - snapPoints[currentPositionIndex])
      });
    }
    if (currentPositionIndex === snapPoints.length - 1) {
      flashScrollableIndicators();
    }
  }, [snapPoints, containerTapGestureRef, flashScrollableIndicators]);
  const handleOnChange = (0, _hooks.useStableCallback)(index => {
    if (_providedOnChange) {
      _providedOnChange(index);
    }
  });
  const handleSettingScrollableRef = (0, _react.useCallback)(scrollableRef => {
    setScrollableRef(scrollableRef);
    refreshUIElements();
  }, [setScrollableRef, refreshUIElements]);
  //#endregion

  //#region public methods
  const handleSnapTo = (0, _react.useCallback)(function (index) {
    let force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
    (0, _invariant.default)(index >= 0 && index <= snapPoints.length - 1, `'index' was provided but out of the provided snap points range! expected value to be between -1, ${snapPoints.length - 1}`);
    if (isClosing.current && !force) {
      return;
    }
    manualSnapToPoint.setValue(snapPoints[index]);
  }, [snapPoints, manualSnapToPoint]);
  const handleClose = (0, _react.useCallback)(() => {
    const currentIndexValue = currentIndexRef.current;
    if (currentIndexValue === -1 || isClosing.current || currentPositionRef.current === safeContainerHeight) {
      return;
    }
    isClosing.current = true;
    manualSnapToPoint.setValue(safeContainerHeight);
  }, [manualSnapToPoint, safeContainerHeight]);
  const handleExpand = (0, _react.useCallback)(() => {
    if (isClosing.current) {
      return;
    }
    manualSnapToPoint.setValue(snapPoints[snapPoints.length - 1]);
  }, [snapPoints, manualSnapToPoint]);
  const handleCollapse = (0, _react.useCallback)(() => {
    if (isClosing.current) {
      return;
    }
    manualSnapToPoint.setValue(snapPoints[0]);
  }, [snapPoints, manualSnapToPoint]);
  //#endregion

  //#region context variables
  const internalContextVariables = (0, _react.useMemo)(() => ({
    enableContentPanningGesture,
    containerTapGestureRef,
    handlePanGestureState,
    handlePanGestureTranslationY,
    handlePanGestureVelocityY,
    contentPanGestureState,
    contentPanGestureTranslationY,
    contentPanGestureVelocityY,
    scrollableContentOffsetY,
    decelerationRate,
    setScrollableRef: handleSettingScrollableRef,
    removeScrollableRef
  }), [enableContentPanningGesture, containerTapGestureRef, contentPanGestureState, contentPanGestureTranslationY, contentPanGestureVelocityY, handlePanGestureState, handlePanGestureTranslationY, handlePanGestureVelocityY, decelerationRate, scrollableContentOffsetY, handleSettingScrollableRef, removeScrollableRef]);
  const externalContextVariables = (0, _react.useMemo)(() => ({
    snapTo: handleSnapTo,
    expand: handleExpand,
    collapse: handleCollapse,
    close: handleClose
  }), [handleSnapTo, handleExpand, handleCollapse, handleClose]);
  //#endregion

  //#region expose public methods
  (0, _react.useImperativeHandle)(ref, () => ({
    snapTo: handleSnapTo,
    expand: handleExpand,
    collapse: handleCollapse,
    close: handleClose
  }));
  //#endregion

  //#region styles
  const containerStyle = (0, _react.useMemo)(() => [_providedStyle, _styles.styles.container, {
    opacity: animatedIsLayoutReady,
    transform: [{
      translateY: (0, _reactNativeReanimated.cond)(animatedIsLayoutReady, position, safeContainerHeight)
    }]
  }], [safeContainerHeight, _providedStyle, position, animatedIsLayoutReady]);
  const contentContainerStyle = (0, _react.useMemo)(() => ({
    ..._styles.styles.contentContainer,
    height: sheetHeight
  }), [sheetHeight]);

  /**
   * added safe area to prevent the sheet from floating above
   * the bottom of the screen, when sheet being over dragged or
   * when the sheet is resized.
   */
  const contentMaskContainerStyle = (0, _react.useMemo)(() => ({
    ..._styles.styles.contentMaskContainer,
    paddingBottom: animatedIsLayoutReady ? sheetHeight : 0
  }), [sheetHeight, animatedIsLayoutReady]);
  //#endregion

  //#region effects

  /**
   * This will animate the sheet to the initial snap point
   * when component is mounted.
   */
  (0, _react.useLayoutEffect)(() => {
    if (animateOnMount && isLayoutCalculated && didMountOnAnimate.current === false && isClosing.current === false && _providedIndex !== -1) {
      manualSnapToPoint.setValue(snapPoints[_providedIndex]);
      didMountOnAnimate.current = true;
    }
  }, [_providedIndex, animateOnMount, isLayoutCalculated, manualSnapToPoint, snapPoints]);

  /*
   * keep animated position synced with snap points.
   */
  (0, _react.useEffect)(() => {
    if (isLayoutCalculated && currentIndexRef.current !== -1 && isClosing.current === false) {
      manualSnapToPoint.setValue(snapPoints[currentIndexRef.current]);
    }
  }, [isLayoutCalculated, snapPoints, manualSnapToPoint]);

  /**
   * @DEV
   * here we track the current position and
   * - call on change ( if provided ).
   * - flash scrollable component scroll indicators.
   * - manipulate the root tap gesture handler maxDeltaY,
   *   which allows the scrollable component to be activated.
   */
  (0, _reactNativeReanimated.useCode)(() => (0, _reactNativeReanimated.onChange)(currentPosition, [(0, _reactNativeReanimated.call)([currentPosition], args => {
    const currentPositionIndex = snapPoints.indexOf(args[0]);

    /**
     * reset is closing
     */
    isClosing.current = false;

    /**
     * if animation was interrupted, we ignore the change.
     */
    if (currentPositionIndex === -1 && args[0] !== safeContainerHeight - topInset) {
      return;
    }

    /**
     * Here we announce the bottom sheet position
     * for accessibility service.
     */
    _reactNative.AccessibilityInfo.isScreenReaderEnabled().then(isEnabled => {
      if (!isEnabled || !_providedEnableAccessibilityChangeAnnouncement) {
        return;
      }
      const positionInScreen = Math.max(Math.floor((_constants.WINDOW_HEIGHT - snapPoints[currentPositionIndex] || 1) / _constants.WINDOW_HEIGHT * 100), 0).toFixed(0);
      _reactNative.AccessibilityInfo.announceForAccessibility(typeof _providedAccessibilityPositionChangeAnnouncement === 'function' ? _providedAccessibilityPositionChangeAnnouncement(positionInScreen) : _providedAccessibilityPositionChangeAnnouncement);
    });
    currentIndexRef.current = currentPositionIndex;
    currentPositionRef.current = args[0];
    refreshUIElements();
    handleOnChange(currentPositionIndex);
  })]), [snapPoints, safeContainerHeight, topInset, refreshUIElements]);

  /**
   * @DEV
   * Once the root tap gesture handler states change to failed
   * and the sheet not fully extended, we make sure to prevent the
   * scrollable component from scrolling.
   */
  (0, _reactNativeReanimated.useCode)(() => (0, _reactNativeReanimated.cond)((0, _reactNativeReanimated.and)((0, _reactNativeReanimated.eq)(containerTapGestureState, _reactNativeGestureHandler.State.FAILED), (0, _reactNativeReanimated.eq)(currentGesture, _constants.GESTURE.CONTENT), (0, _reactNativeReanimated.neq)(position, snapPoints[snapPoints.length - 1])), (0, _reactNativeReanimated.call)([], () => {
    scrollToTop();
  })), [snapPoints]);
  //#endregion

  //#region render
  // 
  //   snapPoints,
  //   shouldMeasureContainerHeight,
  //   safeContainerHeight,
  //   topInset,
  //   bottomInset,
  // });
  return /*#__PURE__*/_react.default.createElement(_contexts.BottomSheetProvider, {
    value: externalContextVariables
  }, /*#__PURE__*/_react.default.createElement(_bottomSheetBackdropContainer.default, {
    key: "BottomSheetBackdropContainer",
    animatedIndex: animatedIndex,
    animatedPosition: animatedPosition,
    backdropComponent: backdropComponent
  }), /*#__PURE__*/_react.default.createElement(_bottomSheetContainer.default, {
    key: "BottomSheetContainer",
    shouldMeasureHeight: shouldMeasureContainerHeight,
    onMeasureHeight: handleOnContainerMeasureHeight,
    topInset: topInset,
    bottomInset: bottomInset
  }, /*#__PURE__*/_react.default.createElement(_bottomSheetContentWrapper.default, _extends({
    key: "BottomSheetContentWrapper",
    ref: containerTapGestureRef
  }, containerTapGestureHandler), /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, _extends({
    accessible: _providedAccessible !== null && _providedAccessible !== void 0 ? _providedAccessible : undefined,
    accessibilityRole: _providedAccessibilityRole !== null && _providedAccessibilityRole !== void 0 ? _providedAccessibilityRole : undefined,
    accessibilityLabel: _providedAccessibilityLabel !== null && _providedAccessibilityLabel !== void 0 ? _providedAccessibilityLabel : undefined,
    style: containerStyle
  }, rest), /*#__PURE__*/_react.default.createElement(_contexts.BottomSheetInternalProvider, {
    value: internalContextVariables
  }, /*#__PURE__*/_react.default.createElement(_bottomSheetBackgroundContainer.default, {
    key: "BottomSheetBackgroundContainer",
    animatedIndex: animatedIndex,
    animatedPosition: animatedPosition,
    backgroundComponent: backgroundComponent
  }), /*#__PURE__*/_react.default.createElement(_bottomSheetHandleContainer.default, _extends({
    key: "BottomSheetHandleContainer",
    animatedIndex: animatedIndex,
    animatedPosition: animatedPosition,
    simultaneousHandlers: containerTapGestureRef,
    shouldMeasureHeight: shouldMeasureHandleHeight,
    enableHandlePanningGesture: enableHandlePanningGesture,
    handleComponent: handleComponent,
    onMeasureHeight: handleOnHandleMeasureHeight
  }, handlePanGestureHandler)), /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, {
    pointerEvents: "box-none",
    style: contentMaskContainerStyle
  }, /*#__PURE__*/_react.default.createElement(_bottomSheetDraggableView.default, {
    key: "BottomSheetRootDraggableView",
    style: contentContainerStyle
  }, children))))), _providedAnimatedPosition && /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.Code, {
    exec: (0, _reactNativeReanimated.set)(_providedAnimatedPosition, animatedPosition)
  }), _providedAnimatedIndex && /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.Code, {
    exec: (0, _reactNativeReanimated.set)(_providedAnimatedIndex, animatedIndex)
  })));
  //#endregion
});

const BottomSheet = /*#__PURE__*/(0, _react.memo)(BottomSheetComponent, _lodash.default);
var _default = BottomSheet;
exports.default = _default;
//# sourceMappingURL=BottomSheet.js.map