'use strict';

var React = require('react');
var useRenderElement = require('./useRenderElement-cjs.js');
var useScrollLock = require('./useScrollLock-cjs.js');
var useButton = require('./useButton-cjs.js');
var scrollEdges = require('./scrollEdges-cjs.js');
var clamp = require('./clamp-cjs.js');
var jsxRuntime = require('react/jsx-runtime');
var floatingUi_utils_dom = require('./floating-ui.utils.dom-cjs.js');

function _interopNamespaceDefault(e) {
  var n = Object.create(null);
  if (e) {
    Object.keys(e).forEach(function (k) {
      if (k !== 'default') {
        var d = Object.getOwnPropertyDescriptor(e, k);
        Object.defineProperty(n, k, d.get ? d : {
          enumerable: true,
          get: function () { return e[k]; }
        });
      }
    });
  }
  n.default = e;
  return Object.freeze(n);
}

var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);

function getEmptyRootContext() {
  return new useScrollLock.FloatingRootStore({
    open: false,
    transitionStatus: undefined,
    floatingElement: null,
    referenceElement: null,
    triggerElements: new useScrollLock.PopupTriggerMap(),
    floatingId: undefined,
    syncOnly: false,
    nested: false,
    onOpenChange: undefined
  });
}

/**
 * State common to all popup stores.
 */

function createInitialPopupStoreState() {
  return {
    open: false,
    openProp: undefined,
    mounted: false,
    transitionStatus: undefined,
    floatingRootContext: getEmptyRootContext(),
    floatingId: undefined,
    triggerCount: 0,
    preventUnmountingOnClose: false,
    payload: undefined,
    activeTriggerId: null,
    activeTriggerElement: null,
    triggerIdProp: undefined,
    popupElement: null,
    positionerElement: null,
    activeTriggerProps: useRenderElement.EMPTY_OBJECT,
    inactiveTriggerProps: useRenderElement.EMPTY_OBJECT,
    popupProps: useRenderElement.EMPTY_OBJECT
  };
}
function createPopupFloatingRootContext(triggerElements, floatingId, nested = false) {
  return new useScrollLock.FloatingRootStore({
    open: false,
    transitionStatus: undefined,
    floatingElement: null,
    referenceElement: null,
    triggerElements,
    floatingId,
    syncOnly: true,
    nested,
    onOpenChange: undefined
  });
}
const activeTriggerIdSelector = useScrollLock.createSelector(state => state.triggerIdProp ?? state.activeTriggerId);
const openSelector = useScrollLock.createSelector(state => state.openProp ?? state.open);
const popupIdSelector = useScrollLock.createSelector(state => {
  const popupId = state.popupElement?.id ?? state.floatingId;
  return popupId || undefined;
});
function triggerOwnsOpenPopup(state, triggerId) {
  return triggerId !== undefined && openSelector(state) && activeTriggerIdSelector(state) === triggerId;
}
function triggerOwnsOpenPopupOrIsOnlyTrigger(state, triggerId) {
  if (triggerOwnsOpenPopup(state, triggerId)) {
    return true;
  }
  return triggerId !== undefined && openSelector(state) && activeTriggerIdSelector(state) == null && state.triggerCount === 1;
}
const popupStoreSelectors = {
  open: openSelector,
  mounted: useScrollLock.createSelector(state => state.mounted),
  transitionStatus: useScrollLock.createSelector(state => state.transitionStatus),
  floatingRootContext: useScrollLock.createSelector(state => state.floatingRootContext),
  triggerCount: useScrollLock.createSelector(state => state.triggerCount),
  preventUnmountingOnClose: useScrollLock.createSelector(state => state.preventUnmountingOnClose),
  payload: useScrollLock.createSelector(state => state.payload),
  activeTriggerId: activeTriggerIdSelector,
  activeTriggerElement: useScrollLock.createSelector(state => state.mounted ? state.activeTriggerElement : null),
  popupId: popupIdSelector,
  /**
   * Whether the trigger with the given ID was used to open the popup.
   */
  isTriggerActive: useScrollLock.createSelector((state, triggerId) => triggerId !== undefined && activeTriggerIdSelector(state) === triggerId),
  /**
   * Whether the popup is open and was activated by a trigger with the given ID.
   */
  isOpenedByTrigger: useScrollLock.createSelector((state, triggerId) => triggerOwnsOpenPopup(state, triggerId)),
  /**
   * Whether the popup is mounted and was activated by a trigger with the given ID.
   */
  isMountedByTrigger: useScrollLock.createSelector((state, triggerId) => triggerId !== undefined && activeTriggerIdSelector(state) === triggerId && state.mounted),
  triggerProps: useScrollLock.createSelector((state, isActive) => isActive ? state.activeTriggerProps : state.inactiveTriggerProps),
  /**
   * Popup id for the trigger that currently owns the open popup.
   */
  triggerPopupId: useScrollLock.createSelector((state, triggerId) => triggerOwnsOpenPopupOrIsOnlyTrigger(state, triggerId) ? popupIdSelector(state) : undefined),
  popupProps: useScrollLock.createSelector(state => state.popupProps),
  popupElement: useScrollLock.createSelector(state => state.popupElement),
  positionerElement: useScrollLock.createSelector(state => state.positionerElement)
};

const IsDrawerContext = /*#__PURE__*/React__namespace.createContext(false);
if (process.env.NODE_ENV !== "production") IsDrawerContext.displayName = "IsDrawerContext";
const DialogRootContext = /*#__PURE__*/React__namespace.createContext(undefined);
if (process.env.NODE_ENV !== "production") DialogRootContext.displayName = "DialogRootContext";
function useDialogRootContext(optional) {
  const dialogRootContext = React__namespace.useContext(DialogRootContext);
  if (optional === false && dialogRootContext === undefined) {
    throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: DialogRootContext is missing. Dialog parts must be placed within <Dialog.Root>.' : useRenderElement.formatErrorMessage(27));
  }
  return dialogRootContext;
}

const DialogPortalContext = /*#__PURE__*/React__namespace.createContext(undefined);
if (process.env.NODE_ENV !== "production") DialogPortalContext.displayName = "DialogPortalContext";
function useDialogPortalContext() {
  const value = React__namespace.useContext(DialogPortalContext);
  if (value === undefined) {
    throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: <Dialog.Portal> is missing.' : useRenderElement.formatErrorMessage(26));
  }
  return value;
}

const DialogPortal = /*#__PURE__*/React__namespace.forwardRef(function DialogPortal(props, forwardedRef) {
  const {
    keepMounted = false,
    ...portalProps
  } = props;
  const {
    store
  } = useDialogRootContext();
  const mounted = store.useState('mounted');
  const modal = store.useState('modal');
  const open = store.useState('open');
  const shouldRender = mounted || keepMounted;
  if (!shouldRender) {
    return null;
  }
  return /*#__PURE__*/jsxRuntime.jsx(DialogPortalContext.Provider, {
    value: keepMounted,
    children: /*#__PURE__*/jsxRuntime.jsxs(useScrollLock.FloatingPortal, {
      ref: forwardedRef,
      ...portalProps,
      children: [mounted && modal === true && /*#__PURE__*/jsxRuntime.jsx(useScrollLock.InternalBackdrop, {
        ref: store.context.internalBackdropRef,
        inert: useScrollLock.inertValue(!open)
      }), props.children]
    })
  });
});
if (process.env.NODE_ENV !== "production") DialogPortal.displayName = "DialogPortal";

function useDialogRoot(params) {
  const {
    store,
    actionsRef
  } = params;
  const open = store.useState('open');
  useScrollLock.usePopupRootSync(store, open);
  useScrollLock.useImplicitActiveTrigger(store);
  const {
    forceUnmount
  } = useScrollLock.useOpenStateTransitions(open, store);
  const handleImperativeClose = React__namespace.useCallback(() => {
    store.setOpen(false, useButton.createChangeEventDetails(useButton.imperativeAction));
  }, [store]);
  React__namespace.useImperativeHandle(actionsRef, () => ({
    unmount: forceUnmount,
    close: handleImperativeClose
  }), [forceUnmount, handleImperativeClose]);
}
function DialogInteractions({
  store,
  parentContext,
  isDrawer
}) {
  const open = store.useState('open');
  const disablePointerDismissal = store.useState('disablePointerDismissal');
  const modal = store.useState('modal');
  const popupElement = store.useState('popupElement');
  const floatingRootContext = store.useState('floatingRootContext');
  const [ownNestedOpenDialogs, setOwnNestedOpenDialogs] = React__namespace.useState(0);
  const [ownNestedOpenDrawers, setOwnNestedOpenDrawers] = React__namespace.useState(0);
  const isTopmost = ownNestedOpenDialogs === 0;
  const dismiss = useScrollLock.useDismiss(floatingRootContext, {
    outsidePressEvent() {
      if (store.context.internalBackdropRef.current || store.context.backdropRef.current) {
        return 'intentional';
      }
      // Ensure `aria-hidden` on outside elements is removed immediately
      // on outside press when trapping focus.
      return {
        mouse: modal === 'trap-focus' ? 'sloppy' : 'intentional',
        touch: 'sloppy'
      };
    },
    outsidePress(event) {
      if (!store.context.outsidePressEnabledRef.current) {
        return false;
      }

      // For mouse events, only accept left button (button 0)
      // For touch events, a single touch is equivalent to left button
      if ('button' in event && event.button !== 0) {
        return false;
      }
      if ('touches' in event && event.touches.length !== 1) {
        return false;
      }
      const target = useButton.getTarget(event);
      if (isTopmost && !disablePointerDismissal) {
        // Only close if the click occurred on the dialog's owning backdrop.
        // This supports multiple modal dialogs that aren't nested in the React tree:
        // https://github.com/mui/base-ui/issues/1320
        if (modal) {
          return store.context.internalBackdropRef.current || store.context.backdropRef.current ? store.context.internalBackdropRef.current === target || store.context.backdropRef.current === target || useButton.contains(target, popupElement) && !target?.hasAttribute('data-base-ui-portal') : true;
        }
        return true;
      }
      return false;
    },
    escapeKey: isTopmost
  });
  useScrollLock.useScrollLock(open && modal === true, popupElement);

  // Listen for nested open/close events on this store to maintain the counts.
  store.useContextCallback('onNestedDialogOpen', (dialogCount, drawerCount) => {
    setOwnNestedOpenDialogs(dialogCount);
    setOwnNestedOpenDrawers(drawerCount);
  });
  store.useContextCallback('onNestedDialogClose', () => {
    setOwnNestedOpenDialogs(0);
    setOwnNestedOpenDrawers(0);
  });

  // Notify parent of our open/close state using parent callbacks, if any
  React__namespace.useEffect(() => {
    if (parentContext?.onNestedDialogOpen && open) {
      parentContext.onNestedDialogOpen(ownNestedOpenDialogs + 1, ownNestedOpenDrawers + (isDrawer ? 1 : 0));
    }
    if (parentContext?.onNestedDialogClose && !open) {
      parentContext.onNestedDialogClose();
    }
    return () => {
      if (parentContext?.onNestedDialogClose && open) {
        parentContext.onNestedDialogClose();
      }
    };
  }, [isDrawer, open, ownNestedOpenDialogs, ownNestedOpenDrawers, parentContext]);
  const activeTriggerProps = dismiss.reference ?? useRenderElement.EMPTY_OBJECT;
  const inactiveTriggerProps = dismiss.trigger ?? useRenderElement.EMPTY_OBJECT;
  // Consumers (DialogPopup/DrawerPopup) already spread `FOCUSABLE_POPUP_PROPS`
  // directly, so the popup props only need to carry the dismiss handlers.
  const popupProps = dismiss.floating ?? useRenderElement.EMPTY_OBJECT;
  useScrollLock.usePopupInteractionProps(store, {
    activeTriggerProps,
    inactiveTriggerProps,
    popupProps,
    nestedOpenDialogCount: ownNestedOpenDialogs,
    nestedOpenDrawerCount: ownNestedOpenDrawers
  });
  return null;
}

const selectors = {
  ...popupStoreSelectors,
  modal: useScrollLock.createSelector(state => state.modal),
  nested: useScrollLock.createSelector(state => state.nested),
  nestedOpenDialogCount: useScrollLock.createSelector(state => state.nestedOpenDialogCount),
  nestedOpenDrawerCount: useScrollLock.createSelector(state => state.nestedOpenDrawerCount),
  disablePointerDismissal: useScrollLock.createSelector(state => state.disablePointerDismissal),
  openMethod: useScrollLock.createSelector(state => state.openMethod),
  descriptionElementId: useScrollLock.createSelector(state => state.descriptionElementId),
  titleElementId: useScrollLock.createSelector(state => state.titleElementId),
  viewportElement: useScrollLock.createSelector(state => state.viewportElement),
  role: useScrollLock.createSelector(state => state.role)
};
class DialogStore extends useScrollLock.ReactStore {
  constructor(initialState, floatingId, nested = false) {
    const triggerElements = new useScrollLock.PopupTriggerMap();
    const state = createInitialState(initialState);
    state.floatingRootContext = createPopupFloatingRootContext(triggerElements, floatingId, nested);
    super(state, {
      popupRef: /*#__PURE__*/React__namespace.createRef(),
      backdropRef: /*#__PURE__*/React__namespace.createRef(),
      internalBackdropRef: /*#__PURE__*/React__namespace.createRef(),
      outsidePressEnabledRef: {
        current: true
      },
      triggerElements,
      onOpenChange: undefined,
      onOpenChangeComplete: undefined
    }, selectors);
  }
  setOpen = (nextOpen, eventDetails) => {
    eventDetails.preventUnmountOnClose = () => {
      this.set('preventUnmountingOnClose', true);
    };
    if (!nextOpen && eventDetails.trigger == null && this.state.activeTriggerId != null) {
      // When closing the dialog, pass the old trigger to the onOpenChange event
      // so it's not reset too early (potentially causing focus issues in controlled scenarios).
      eventDetails.trigger = this.state.activeTriggerElement ?? undefined;
    }
    this.context.onOpenChange?.(nextOpen, eventDetails);
    if (eventDetails.isCanceled) {
      return;
    }
    this.state.floatingRootContext.dispatchOpenChange(nextOpen, eventDetails);
    const updatedState = {
      open: nextOpen
    };
    useScrollLock.setPopupOpenState(updatedState, nextOpen, eventDetails.trigger);
    this.update(updatedState);
  };
  static useStore(externalStore, initialState) {
    /* eslint-disable react-hooks/rules-of-hooks */
    const store = useScrollLock.usePopupStore(externalStore, (floatingId, nested) => new DialogStore(initialState, floatingId, nested), true).store;
    /* eslint-enable react-hooks/rules-of-hooks */

    return store;
  }
}
function createInitialState(initialState = {}) {
  return {
    ...createInitialPopupStoreState(),
    modal: true,
    disablePointerDismissal: false,
    popupElement: null,
    viewportElement: null,
    descriptionElementId: undefined,
    titleElementId: undefined,
    openMethod: null,
    nested: false,
    nestedOpenDialogCount: 0,
    nestedOpenDrawerCount: 0,
    role: 'dialog',
    ...initialState
  };
}

function useRenderDialogRoot(props, mode = 'dialog') {
  const {
    children,
    open: openProp,
    defaultOpen = false,
    onOpenChange,
    onOpenChangeComplete,
    disablePointerDismissal: disablePointerDismissalProp = false,
    modal: modalProp = true,
    actionsRef,
    handle,
    triggerId: triggerIdProp,
    defaultTriggerId: defaultTriggerIdProp = null
  } = props;
  const isDrawer = mode === 'drawer';
  const isAlertDialog = mode === 'alert-dialog';
  const modal = isAlertDialog ? true : modalProp;
  const disablePointerDismissal = isAlertDialog || disablePointerDismissalProp;
  const role = isAlertDialog ? 'alertdialog' : 'dialog';
  const parentDialogRootContext = useDialogRootContext(true);
  const nested = Boolean(parentDialogRootContext);
  const rootState = {
    modal,
    disablePointerDismissal,
    nested,
    role
  };
  const store = DialogStore.useStore(handle?.store, {
    open: defaultOpen,
    openProp,
    activeTriggerId: defaultTriggerIdProp,
    triggerIdProp,
    ...rootState
  });

  // Support initially open state when uncontrolled
  useScrollLock.useOnFirstRender(() => {
    const nextState = openProp === undefined && store.state.open === false && defaultOpen === true ? {
      open: true,
      activeTriggerId: defaultTriggerIdProp
    } : null;
    if (isAlertDialog) {
      // Handles can reuse plain Dialog stores; alert dialog invariants must exist immediately.
      store.update(nextState ? {
        ...rootState,
        ...nextState
      } : rootState);
    } else if (nextState) {
      store.update(nextState);
    }
  });
  store.useControlledProp('openProp', openProp);
  store.useControlledProp('triggerIdProp', triggerIdProp);
  store.useSyncedValues(rootState);
  store.useContextCallback('onOpenChange', onOpenChange);
  store.useContextCallback('onOpenChangeComplete', onOpenChangeComplete);
  const open = store.useState('open');
  const mounted = store.useState('mounted');
  const payload = store.useState('payload');
  useDialogRoot({
    store,
    actionsRef
  });
  const shouldRenderInteractions = open || mounted;
  const contextValue = React__namespace.useMemo(() => ({
    store
  }), [store]);
  return /*#__PURE__*/jsxRuntime.jsx(IsDrawerContext.Provider, {
    value: false,
    children: /*#__PURE__*/jsxRuntime.jsxs(DialogRootContext.Provider, {
      value: contextValue,
      children: [shouldRenderInteractions && /*#__PURE__*/jsxRuntime.jsx(DialogInteractions, {
        store: store,
        parentContext: parentDialogRootContext?.store.context,
        isDrawer: isDrawer
      }), typeof children === 'function' ? children({
        payload
      }) : children]
    })
  });
}

/**
 * Groups all parts of the dialog.
 * Doesn't render its own HTML element.
 *
 * Documentation: [Base UI Dialog](https://base-ui.com/react/components/dialog)
 */
function DialogRoot(props) {
  const mode = React__namespace.useContext(IsDrawerContext) ? 'drawer' : 'dialog';
  return useRenderDialogRoot(props, mode);
}

/**
 * A button that opens the dialog.
 * Renders a `<button>` element.
 *
 * Documentation: [Base UI Dialog](https://base-ui.com/react/components/dialog)
 */
const DialogTrigger = /*#__PURE__*/React__namespace.forwardRef(function DialogTrigger(componentProps, forwardedRef) {
  const {
    render,
    className,
    style,
    disabled = false,
    nativeButton = true,
    id: idProp,
    payload,
    handle,
    ...elementProps
  } = componentProps;
  const dialogRootContext = useDialogRootContext(true);
  const store = handle?.store ?? dialogRootContext?.store;
  if (!store) {
    throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: <Dialog.Trigger> must be used within <Dialog.Root> or provided with a handle.' : useRenderElement.formatErrorMessage(79));
  }
  const thisTriggerId = useButton.useBaseUiId(idProp);
  const floatingContext = store.useState('floatingRootContext');
  const isOpenedByThisTrigger = store.useState('isOpenedByTrigger', thisTriggerId);
  const popupId = store.useState('triggerPopupId', thisTriggerId);
  const triggerElementRef = React__namespace.useRef(null);
  const {
    registerTrigger,
    isMountedByThisTrigger
  } = useScrollLock.useTriggerDataForwarding(thisTriggerId, triggerElementRef, store, {
    payload
  });
  const {
    getButtonProps,
    buttonRef
  } = useButton.useButton({
    disabled,
    native: nativeButton
  });
  const click = useScrollLock.useClick(floatingContext, {
    enabled: floatingContext != null
  });
  const interactionTypeProps = useScrollLock.useOpenMethodTriggerProps(() => store.select('open'), interactionType => {
    store.set('openMethod', interactionType);
  });
  const state = {
    disabled,
    open: isOpenedByThisTrigger
  };
  const rootTriggerProps = store.useState('triggerProps', isMountedByThisTrigger);
  return useRenderElement.useRenderElement('button', componentProps, {
    state,
    ref: [buttonRef, forwardedRef, registerTrigger, triggerElementRef],
    props: [click.reference, rootTriggerProps, interactionTypeProps, {
      [useScrollLock.CLICK_TRIGGER_IDENTIFIER]: '',
      id: thisTriggerId,
      'aria-haspopup': 'dialog',
      'aria-expanded': isOpenedByThisTrigger,
      'aria-controls': popupId
    }, elementProps, getButtonProps],
    stateAttributesMapping: useScrollLock.triggerOpenStateMapping
  });
});
if (process.env.NODE_ENV !== "production") DialogTrigger.displayName = "DialogTrigger";

let DrawerPopupCssVars = /*#__PURE__*/function (DrawerPopupCssVars) {
  /**
   * The number of nested drawers that are currently open.
   * @type {number}
   */
  DrawerPopupCssVars["nestedDrawers"] = "--nested-drawers";
  /**
   * The height of the drawer popup.
   * @type {CSS length}
   */
  DrawerPopupCssVars["height"] = "--drawer-height";
  /**
   * The height of the frontmost open drawer in the current nested drawer stack.
   * @type {CSS length}
   */
  DrawerPopupCssVars["frontmostHeight"] = "--drawer-frontmost-height";
  /**
   * The swipe movement on the X axis.
   * @type {CSS length}
   */
  DrawerPopupCssVars["swipeMovementX"] = "--drawer-swipe-movement-x";
  /**
   * The swipe movement on the Y axis.
   * @type {CSS length}
   */
  DrawerPopupCssVars["swipeMovementY"] = "--drawer-swipe-movement-y";
  /**
   * The snap point offset used for translating the drawer.
   * @type {CSS length}
   */
  DrawerPopupCssVars["snapPointOffset"] = "--drawer-snap-point-offset";
  /**
   * A scalar (0.1-1) used to scale the swipe release transition duration in CSS.
   * @type {number}
   */
  DrawerPopupCssVars["swipeStrength"] = "--drawer-swipe-strength";
  return DrawerPopupCssVars;
}({});

let DrawerBackdropCssVars = /*#__PURE__*/function (DrawerBackdropCssVars) {
  /**
   * The swipe progress of the drawer gesture.
   * @type {number}
   */
  DrawerBackdropCssVars["swipeProgress"] = "--drawer-swipe-progress";
  return DrawerBackdropCssVars;
}({});

const stateAttributesMapping$1 = {
  ...useScrollLock.popupStateMapping,
  ...useButton.transitionStatusMapping
};

/**
 * An overlay displayed beneath the popup.
 * Renders a `<div>` element.
 *
 * Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
 */
const DrawerBackdrop = /*#__PURE__*/React__namespace.forwardRef(function DrawerBackdrop(componentProps, forwardedRef) {
  const {
    render,
    className,
    style,
    forceRender = false,
    ...elementProps
  } = componentProps;
  const {
    store
  } = useDialogRootContext();
  const open = store.useState('open');
  const nested = store.useState('nested');
  const mounted = store.useState('mounted');
  const transitionStatus = store.useState('transitionStatus');
  const state = {
    open,
    transitionStatus
  };
  return useRenderElement.useRenderElement('div', componentProps, {
    state,
    ref: [store.context.backdropRef, forwardedRef],
    stateAttributesMapping: stateAttributesMapping$1,
    props: [{
      role: 'presentation',
      hidden: !mounted,
      style: {
        pointerEvents: !open ? 'none' : undefined,
        userSelect: 'none',
        WebkitUserSelect: 'none',
        [DrawerBackdropCssVars.swipeProgress]: '0',
        [DrawerPopupCssVars.swipeStrength]: '1'
      }
    }, elementProps],
    enabled: forceRender || !nested
  });
});
if (process.env.NODE_ENV !== "production") DrawerBackdrop.displayName = "DrawerBackdrop";

const DRAWER_CONTENT_ATTRIBUTE = 'data-drawer-content';

/**
 * A container for the drawer contents.
 * Renders a `<div>` element.
 *
 * Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
 */
const DrawerContent = /*#__PURE__*/React__namespace.forwardRef(function DrawerContent(componentProps, forwardedRef) {
  const {
    render,
    className,
    style,
    ...elementProps
  } = componentProps;
  useDialogRootContext();
  return useRenderElement.useRenderElement('div', componentProps, {
    ref: forwardedRef,
    props: [{
      [DRAWER_CONTENT_ATTRIBUTE]: ''
    }, elementProps]
  });
});
if (process.env.NODE_ENV !== "production") DrawerContent.displayName = "DrawerContent";

const DrawerProviderContext = /*#__PURE__*/React__namespace.createContext(undefined);
if (process.env.NODE_ENV !== "production") DrawerProviderContext.displayName = "DrawerProviderContext";
function useDrawerProviderContext(optional) {
  const context = React__namespace.useContext(DrawerProviderContext);
  return context;
}

let DrawerPopupDataAttributes = function (DrawerPopupDataAttributes) {
  /**
   * Present when the drawer is open.
   */
  DrawerPopupDataAttributes[DrawerPopupDataAttributes["open"] = useScrollLock.CommonPopupDataAttributes.open] = "open";
  /**
   * Present when the drawer is closed.
   */
  DrawerPopupDataAttributes[DrawerPopupDataAttributes["closed"] = useScrollLock.CommonPopupDataAttributes.closed] = "closed";
  /**
   * Present when the drawer is animating in.
   */
  DrawerPopupDataAttributes[DrawerPopupDataAttributes["startingStyle"] = useScrollLock.CommonPopupDataAttributes.startingStyle] = "startingStyle";
  /**
   * Present when the drawer is animating out.
   */
  DrawerPopupDataAttributes[DrawerPopupDataAttributes["endingStyle"] = useScrollLock.CommonPopupDataAttributes.endingStyle] = "endingStyle";
  /**
   * Present when the drawer is at the expanded (full-height) snap point.
   */
  DrawerPopupDataAttributes["expanded"] = "data-expanded";
  /**
   * Present when a nested drawer is open.
   */
  DrawerPopupDataAttributes["nestedDrawerOpen"] = "data-nested-drawer-open";
  /**
   * Present when a nested drawer is being swiped.
   */
  DrawerPopupDataAttributes["nestedDrawerSwiping"] = "data-nested-drawer-swiping";
  /**
   * Present when the drawer is dismissed by swiping.
   */
  DrawerPopupDataAttributes["swipeDismiss"] = "data-swipe-dismiss";
  /**
   * Indicates the swipe direction.
   * @type {'up' | 'down' | 'left' | 'right'}
   */
  DrawerPopupDataAttributes["swipeDirection"] = "data-swipe-direction";
  /**
   * Present when the drawer is being swiped.
   */
  DrawerPopupDataAttributes["swiping"] = "data-swiping";
  return DrawerPopupDataAttributes;
}({});

const DrawerRootContext = /*#__PURE__*/React__namespace.createContext(undefined);
if (process.env.NODE_ENV !== "production") DrawerRootContext.displayName = "DrawerRootContext";
function useDrawerRootContext(optional) {
  const drawerRootContext = React__namespace.useContext(DrawerRootContext);
  if (optional === false && drawerRootContext === undefined) {
    throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: DrawerRootContext is missing. Drawer parts must be placed within <Drawer.Root>.' : useRenderElement.formatErrorMessage(90));
  }
  return drawerRootContext;
}

/**
 * Resolves the vertical swipe movement for a snap point, applying square-root damping once the drag
 * overshoots the fully-open edge (`nextOffset < 0`) so the popup resists travelling past it.
 */
function getSnapPointSwipeMovement(baseOffset, movementValue) {
  const nextOffset = baseOffset + movementValue;
  if (nextOffset >= 0) {
    return movementValue;
  }
  return -Math.sqrt(-nextOffset) - baseOffset;
}
function resolveSnapPointValue(snapPoint, viewportHeight, rootFontSize) {
  if (!Number.isFinite(viewportHeight) || viewportHeight <= 0) {
    return null;
  }
  if (typeof snapPoint === 'number') {
    if (!Number.isFinite(snapPoint)) {
      return null;
    }
    if (snapPoint <= 1) {
      return clamp.clamp(snapPoint, 0, 1) * viewportHeight;
    }
    return snapPoint;
  }
  const trimmed = snapPoint.trim();
  if (trimmed.endsWith('px')) {
    const value = Number.parseFloat(trimmed);
    return Number.isFinite(value) ? value : null;
  }
  if (trimmed.endsWith('rem')) {
    const value = Number.parseFloat(trimmed);
    return Number.isFinite(value) ? value * rootFontSize : null;
  }
  return null;
}
function findClosestSnapPoint(height, points) {
  let closest = null;
  let closestDistance = Infinity;
  for (const point of points) {
    const distance = Math.abs(point.height - height);
    if (distance < closestDistance) {
      closestDistance = distance;
      closest = point;
    }
  }
  return closest;
}
function useDrawerSnapPoints() {
  const {
    store
  } = useDialogRootContext();
  const {
    snapPoints,
    activeSnapPoint,
    setActiveSnapPoint,
    popupHeight
  } = useDrawerRootContext();
  const viewportElement = store.useState('viewportElement');
  const [viewportHeight, setViewportHeight] = React__namespace.useState(0);
  const [rootFontSize, setRootFontSize] = React__namespace.useState(16);
  const measureViewportHeight = useButton.useStableCallback(() => {
    const doc = useButton.ownerDocument(viewportElement);
    const html = doc.documentElement;
    if (viewportElement) {
      setViewportHeight(viewportElement.offsetHeight);
    }
    if (!viewportElement) {
      setViewportHeight(html.clientHeight);
    }
    const fontSize = parseFloat(getComputedStyle(html).fontSize);
    if (Number.isFinite(fontSize)) {
      setRootFontSize(fontSize);
    }
  });
  useButton.useIsoLayoutEffect(() => {
    measureViewportHeight();
    if (!viewportElement || typeof ResizeObserver !== 'function') {
      return undefined;
    }
    const resizeObserver = new ResizeObserver(measureViewportHeight);
    resizeObserver.observe(viewportElement);
    return () => {
      resizeObserver.disconnect();
    };
  }, [measureViewportHeight, viewportElement]);
  const resolvedSnapPoints = React__namespace.useMemo(() => {
    if (!snapPoints || snapPoints.length === 0 || viewportHeight <= 0 || popupHeight <= 0) {
      return [];
    }
    const maxHeight = Math.min(popupHeight, viewportHeight);
    if (!Number.isFinite(maxHeight) || maxHeight <= 0) {
      return [];
    }
    const resolved = snapPoints.map(value => {
      const resolvedHeight = resolveSnapPointValue(value, viewportHeight, rootFontSize);
      if (resolvedHeight === null || !Number.isFinite(resolvedHeight)) {
        return null;
      }
      const clampedHeight = clamp.clamp(resolvedHeight, 0, maxHeight);
      return {
        value,
        height: clampedHeight,
        offset: Math.max(0, popupHeight - clampedHeight)
      };
    }).filter(point => Boolean(point));
    if (resolved.length <= 1) {
      return resolved;
    }
    const deduped = [];
    const seenHeights = [];
    for (let index = resolved.length - 1; index >= 0; index -= 1) {
      const point = resolved[index];
      const isDuplicate = seenHeights.some(height => Math.abs(height - point.height) <= 1);
      if (isDuplicate) {
        continue;
      }
      seenHeights.push(point.height);
      deduped.push(point);
    }
    deduped.reverse();
    return deduped;
  }, [popupHeight, rootFontSize, snapPoints, viewportHeight]);
  const resolvedActiveSnapPoint = React__namespace.useMemo(() => {
    if (activeSnapPoint === undefined) {
      return resolvedSnapPoints[0];
    }
    if (activeSnapPoint === null) {
      return undefined;
    }
    const exactMatch = resolvedSnapPoints.find(point => Object.is(point.value, activeSnapPoint));
    if (exactMatch) {
      return exactMatch;
    }
    const maxHeight = Math.min(popupHeight, viewportHeight);
    const resolvedHeight = resolveSnapPointValue(activeSnapPoint, viewportHeight, rootFontSize);
    if (resolvedHeight === null || !Number.isFinite(resolvedHeight)) {
      return undefined;
    }
    const clampedHeight = clamp.clamp(resolvedHeight, 0, maxHeight);
    return findClosestSnapPoint(clampedHeight, resolvedSnapPoints) ?? undefined;
  }, [activeSnapPoint, popupHeight, resolvedSnapPoints, rootFontSize, viewportHeight]);
  return {
    snapPoints,
    activeSnapPoint,
    setActiveSnapPoint,
    popupHeight,
    viewportHeight,
    resolvedSnapPoints,
    activeSnapPointOffset: resolvedActiveSnapPoint?.offset ?? null
  };
}

const DrawerViewportContext = /*#__PURE__*/React__namespace.createContext(null);
if (process.env.NODE_ENV !== "production") DrawerViewportContext.displayName = "DrawerViewportContext";
function useDrawerViewportContext(optional) {
  const context = React__namespace.useContext(DrawerViewportContext);
  return context;
}

let drawerSwipeVarsRegistered = false;

/**
 * Removes inheritance of high-frequency drawer swipe CSS variables, which
 * reduces style recalculation cost in complex drawers with deep subtrees.
 * See https://motion.dev/blog/web-animation-performance-tier-list
 * under the "Improving CSS variable performance" section.
 */
function removeCSSVariableInheritance$1() {
  if (drawerSwipeVarsRegistered) {
    return;
  }

  // Intentionally keep inheritance disabled on WebKit as well. Safari doesn't support
  // opting descendants back in via `--var: inherit` for custom properties registered
  // with `inherits: false`, but Drawer does not rely on descendant access to these vars
  // (unlike ScrollArea), so we keep the performance optimization enabled.
  if (typeof CSS !== 'undefined' && 'registerProperty' in CSS) {
    [DrawerPopupCssVars.swipeMovementX, DrawerPopupCssVars.swipeMovementY, DrawerPopupCssVars.snapPointOffset].forEach(name => {
      try {
        CSS.registerProperty({
          name,
          syntax: '<length>',
          inherits: false,
          initialValue: '0px'
        });
      } catch {
        /* ignore already-registered */
      }
    });
    [{
      name: DrawerBackdropCssVars.swipeProgress,
      initialValue: '0'
    }, {
      name: DrawerPopupCssVars.swipeStrength,
      initialValue: '1'
    }].forEach(({
      name,
      initialValue
    }) => {
      try {
        CSS.registerProperty({
          name,
          syntax: '<number>',
          inherits: false,
          initialValue
        });
      } catch {
        /* ignore already-registered */
      }
    });
  }
  drawerSwipeVarsRegistered = true;
}
const stateAttributesMapping = {
  ...useScrollLock.popupStateMapping,
  ...useButton.transitionStatusMapping,
  expanded(value) {
    return value ? {
      [DrawerPopupDataAttributes.expanded]: ''
    } : null;
  },
  nestedDrawerOpen(value) {
    return value ? {
      [DrawerPopupDataAttributes.nestedDrawerOpen]: ''
    } : null;
  },
  nestedDrawerSwiping(value) {
    return value ? {
      [DrawerPopupDataAttributes.nestedDrawerSwiping]: ''
    } : null;
  },
  swipeDirection(value) {
    return value ? {
      [DrawerPopupDataAttributes.swipeDirection]: value
    } : null;
  },
  swiping(value) {
    return value ? {
      [DrawerPopupDataAttributes.swiping]: ''
    } : null;
  }
};

/**
 * A container for the drawer contents.
 * Renders a `<div>` element.
 *
 * Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
 */
const DrawerPopup = /*#__PURE__*/React__namespace.forwardRef(function DrawerPopup(componentProps, forwardedRef) {
  const {
    render,
    className,
    style,
    finalFocus,
    initialFocus,
    ...elementProps
  } = componentProps;
  const {
    store
  } = useDialogRootContext();
  const popupRef = store.context.popupRef;
  const {
    swipeDirection,
    frontmostHeight,
    hasNestedDrawer,
    nestedSwiping,
    nestedSwipeProgressStore,
    onPopupHeightChange,
    notifyParentFrontmostHeight,
    notifyParentHasNestedDrawer
  } = useDrawerRootContext();
  const descriptionElementId = store.useState('descriptionElementId');
  const disablePointerDismissal = store.useState('disablePointerDismissal');
  const floatingRootContext = store.useState('floatingRootContext');
  const rootPopupProps = store.useState('popupProps');
  const modal = store.useState('modal');
  const mounted = store.useState('mounted');
  const nested = store.useState('nested');
  const nestedOpenDrawerCount = store.useState('nestedOpenDrawerCount');
  const transitionStatus = store.useState('transitionStatus');
  const open = store.useState('open');
  const openMethod = store.useState('openMethod');
  const titleElementId = store.useState('titleElementId');
  const role = store.useState('role');
  const floatingId = floatingRootContext.useState('floatingId');
  const popupId = elementProps.id ?? floatingId;
  const swipe = useDrawerViewportContext();
  useDialogPortalContext();
  const {
    snapPoints,
    activeSnapPoint,
    activeSnapPointOffset
  } = useDrawerSnapPoints();
  const nestedDrawerOpen = nestedOpenDrawerCount > 0;
  const swiping = swipe?.swiping ?? false;
  const swipeStrength = swipe?.swipeStrength ?? null;
  const [popupHeight, setPopupHeight] = React__namespace.useState(0);
  const popupHeightRef = React__namespace.useRef(0);
  if (process.env.NODE_ENV !== 'production') {
    // eslint-disable-next-line react-hooks/rules-of-hooks
    React__namespace.useEffect(() => {
      if (swipe) {
        return;
      }
      const ownerStackMessage = useButton.SafeReact.captureOwnerStack?.() || '';
      const message = '<Drawer.Popup> expected to be rendered within <Drawer.Viewport>. Omitting the ' + 'viewport disables drawer swipe handling and touch scroll locking. Wrap ' + '<Drawer.Popup> in <Drawer.Viewport>.';
      useButton.error(`${message}${ownerStackMessage}`);
    }, [swipe]);
  }
  const measureHeight = useButton.useStableCallback(() => {
    const popupElement = popupRef.current;
    if (!popupElement) {
      return;
    }
    const offsetHeight = popupElement.offsetHeight;

    // Only skip while the element is still actually stretched beyond its last measured height.
    if (popupHeightRef.current > 0 && frontmostHeight > popupHeightRef.current && offsetHeight > popupHeightRef.current) {
      return;
    }
    const keepHeightWhileNested = popupHeightRef.current > 0 && hasNestedDrawer;
    if (keepHeightWhileNested) {
      const oldHeight = popupHeightRef.current;
      setPopupHeight(oldHeight);
      onPopupHeightChange(oldHeight);
      return;
    }
    const nextHeight = offsetHeight;
    if (nextHeight === popupHeightRef.current) {
      return;
    }
    popupHeightRef.current = nextHeight;
    setPopupHeight(nextHeight);
    onPopupHeightChange(nextHeight);
  });
  useButton.useIsoLayoutEffect(() => {
    if (!mounted) {
      popupHeightRef.current = 0;
      setPopupHeight(0);
      onPopupHeightChange(0);
      return undefined;
    }
    const popupElement = popupRef.current;
    if (!popupElement) {
      return undefined;
    }
    removeCSSVariableInheritance$1();
    measureHeight();
    if (typeof ResizeObserver !== 'function') {
      return undefined;
    }
    const resizeObserver = new ResizeObserver(measureHeight);
    resizeObserver.observe(popupElement);
    return () => {
      resizeObserver.disconnect();
    };
  }, [measureHeight, mounted, nestedDrawerOpen, onPopupHeightChange, popupRef]);
  useButton.useIsoLayoutEffect(() => {
    const syncNestedSwipeProgress = () => {
      const popupElement = popupRef.current;
      if (!popupElement) {
        return;
      }
      const progress = nestedSwipeProgressStore.getSnapshot();
      if (progress > 0) {
        popupElement.style.setProperty(DrawerBackdropCssVars.swipeProgress, `${progress}`);
      } else {
        popupElement.style.setProperty(DrawerBackdropCssVars.swipeProgress, '0');
      }
    };
    syncNestedSwipeProgress();
    const unsubscribe = nestedSwipeProgressStore.subscribe(syncNestedSwipeProgress);
    const popupElement = popupRef.current;
    return () => {
      unsubscribe();
      if (popupElement) {
        popupElement.style.setProperty(DrawerBackdropCssVars.swipeProgress, '0');
      }
    };
  }, [nestedSwipeProgressStore, popupRef]);
  React__namespace.useEffect(() => {
    if (!open) {
      return undefined;
    }
    notifyParentFrontmostHeight?.(frontmostHeight);
    return () => {
      notifyParentFrontmostHeight?.(0);
    };
  }, [frontmostHeight, open, notifyParentFrontmostHeight]);
  React__namespace.useEffect(() => {
    if (!notifyParentHasNestedDrawer) {
      return undefined;
    }
    const present = open || transitionStatus === 'ending';
    notifyParentHasNestedDrawer(present);
    return () => {
      notifyParentHasNestedDrawer(false);
    };
  }, [notifyParentHasNestedDrawer, open, transitionStatus]);
  useButton.useOpenChangeComplete({
    open,
    ref: popupRef,
    onComplete() {
      if (open) {
        store.context.onOpenChangeComplete?.(true);
      }
    }
  });
  const resolvedInitialFocus = initialFocus === undefined ? popupRef : initialFocus;
  const setPopupElement = store.useStateSetter('popupElement');
  const state = {
    open,
    nested,
    transitionStatus,
    expanded: activeSnapPoint === 1,
    nestedDrawerOpen,
    nestedDrawerSwiping: nestedSwiping,
    swipeDirection,
    swiping
  };
  let popupHeightCssVarValue;
  const shouldUseAutoHeight = !hasNestedDrawer && transitionStatus !== 'ending';
  if (popupHeight && !shouldUseAutoHeight) {
    popupHeightCssVarValue = `${popupHeight}px`;
  }
  const shouldApplySnapPoints = snapPoints && snapPoints.length > 0 && (swipeDirection === 'down' || swipeDirection === 'up');
  let snapPointOffsetValue = null;
  if (shouldApplySnapPoints && activeSnapPointOffset !== null) {
    snapPointOffsetValue = swipeDirection === 'up' ? -activeSnapPointOffset : activeSnapPointOffset;
  }
  let dragStyles = swipe ? swipe.getDragStyles() : useRenderElement.EMPTY_OBJECT;
  if (shouldApplySnapPoints && swipeDirection === 'down') {
    const baseOffset = activeSnapPointOffset ?? 0;
    const movementValue = Number.parseFloat(String(dragStyles[DrawerPopupCssVars.swipeMovementY] ?? 0));
    if (swiping && Number.isFinite(movementValue)) {
      dragStyles = {
        ...dragStyles,
        transform: undefined,
        [DrawerPopupCssVars.swipeMovementY]: `${getSnapPointSwipeMovement(baseOffset, movementValue)}px`
      };
    } else {
      dragStyles = {
        ...dragStyles,
        transform: undefined
      };
    }
  }
  const element = useRenderElement.useRenderElement('div', componentProps, {
    state,
    props: [rootPopupProps, {
      id: popupId,
      'aria-labelledby': titleElementId,
      'aria-describedby': descriptionElementId,
      role,
      ...useScrollLock.FOCUSABLE_POPUP_PROPS,
      hidden: !mounted,
      onKeyDown(event) {
        if (scrollEdges.COMPOSITE_KEYS.has(event.key)) {
          event.stopPropagation();
        }
      },
      style: {
        ...dragStyles,
        [DrawerBackdropCssVars.swipeProgress]: '0',
        [DrawerPopupCssVars.nestedDrawers]: nestedOpenDrawerCount,
        [DrawerPopupCssVars.height]: popupHeightCssVarValue,
        [DrawerPopupCssVars.snapPointOffset]: typeof snapPointOffsetValue === 'number' ? `${snapPointOffsetValue}px` : '0px',
        [DrawerPopupCssVars.frontmostHeight]: frontmostHeight ? `${frontmostHeight}px` : undefined,
        [DrawerPopupCssVars.swipeStrength]: typeof swipeStrength === 'number' && Number.isFinite(swipeStrength) && swipeStrength > 0 ? `${swipeStrength}` : '1'
      }
    }, elementProps],
    ref: [forwardedRef, popupRef, setPopupElement],
    stateAttributesMapping
  });
  return /*#__PURE__*/jsxRuntime.jsx(useScrollLock.FloatingFocusManager, {
    context: floatingRootContext,
    openInteractionType: openMethod,
    disabled: !mounted,
    closeOnFocusOut: !disablePointerDismissal,
    initialFocus: resolvedInitialFocus,
    returnFocus: finalFocus,
    modal: modal !== false,
    restoreFocus: "popup",
    children: element
  });
});
if (process.env.NODE_ENV !== "production") DrawerPopup.displayName = "DrawerPopup";

/**
 * A portal element that moves the popup to a different part of the DOM.
 * By default, the portal element is appended to `<body>`.
 * Renders a `<div>` element.
 *
 * Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
 */
const DrawerPortal = DialogPortal;

var _DrawerProviderReport, _DrawerProviderReport2;
/**
 * Groups all parts of the drawer.
 * Doesn't render its own HTML element.
 *
 * Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
 */
function DrawerRoot(props) {
  const {
    children,
    open: openProp,
    defaultOpen = false,
    onOpenChange,
    onOpenChangeComplete,
    disablePointerDismissal = false,
    modal = true,
    actionsRef,
    handle,
    triggerId: triggerIdProp,
    defaultTriggerId: defaultTriggerIdProp = null,
    swipeDirection = 'down',
    snapToSequentialPoints = false,
    snapPoints,
    snapPoint: snapPointProp,
    defaultSnapPoint,
    onSnapPointChange
  } = props;
  const parentDrawerRootContext = useDrawerRootContext(true);
  const notifyParentSwipeProgressChange = parentDrawerRootContext?.onNestedSwipeProgressChange;
  const notifyParentFrontmostHeight = parentDrawerRootContext?.onNestedFrontmostHeightChange;
  const notifyParentSwipingChange = parentDrawerRootContext?.onNestedSwipingChange;
  const notifyParentHasNestedDrawer = parentDrawerRootContext?.onNestedDrawerPresenceChange;
  const [popupHeight, setPopupHeight] = React__namespace.useState(0);
  const [frontmostHeight, setFrontmostHeight] = React__namespace.useState(0);
  const [hasNestedDrawer, setHasNestedDrawer] = React__namespace.useState(false);
  const [nestedSwiping, setNestedSwiping] = React__namespace.useState(false);
  const [nestedSwipeProgressStore] = React__namespace.useState(createNestedSwipeProgressStore);
  const resolvedDefaultSnapPoint = defaultSnapPoint !== undefined ? defaultSnapPoint : snapPoints?.[0] ?? null;
  const isSnapPointControlled = snapPointProp !== undefined;
  const [activeSnapPoint, setActiveSnapPointUnwrapped] = useButton.useControlled({
    controlled: snapPointProp,
    default: resolvedDefaultSnapPoint,
    name: 'Drawer',
    state: 'snapPoint'
  });
  const isNestedDrawerOpenRef = React__namespace.useRef(false);
  const setActiveSnapPoint = useButton.useStableCallback((nextSnapPoint, eventDetails) => {
    const resolvedEventDetails = eventDetails ?? useButton.createChangeEventDetails(useButton.none);
    onSnapPointChange?.(nextSnapPoint, resolvedEventDetails);
    if (resolvedEventDetails.isCanceled) {
      return;
    }
    setActiveSnapPointUnwrapped(nextSnapPoint);
  });
  const resolvedActiveSnapPoint = React__namespace.useMemo(() => {
    if (isSnapPointControlled) {
      return activeSnapPoint;
    }
    if (!snapPoints || snapPoints.length === 0) {
      return activeSnapPoint;
    }
    if (activeSnapPoint === null || !snapPoints.some(snapPoint => Object.is(snapPoint, activeSnapPoint))) {
      return resolvedDefaultSnapPoint;
    }
    return activeSnapPoint;
  }, [activeSnapPoint, isSnapPointControlled, resolvedDefaultSnapPoint, snapPoints]);
  const onPopupHeightChange = useButton.useStableCallback(height => {
    setPopupHeight(height);
    if (!isNestedDrawerOpenRef.current && height > 0) {
      setFrontmostHeight(height);
    }
  });
  const onNestedFrontmostHeightChange = useButton.useStableCallback(height => {
    if (height > 0) {
      isNestedDrawerOpenRef.current = true;
      setFrontmostHeight(height);
      return;
    }
    isNestedDrawerOpenRef.current = false;
    if (popupHeight > 0) {
      setFrontmostHeight(popupHeight);
    }
  });
  const onNestedDrawerPresenceChange = useButton.useStableCallback(present => {
    setHasNestedDrawer(present);
  });
  const onNestedSwipeProgressChange = useButton.useStableCallback(progress => {
    nestedSwipeProgressStore.set(progress);
    notifyParentSwipeProgressChange?.(progress);
  });
  const onNestedSwipingChange = useButton.useStableCallback(swiping => {
    setNestedSwiping(swiping);
    notifyParentSwipingChange?.(swiping);
  });
  const handleOpenChange = useButton.useStableCallback((nextOpen, eventDetails) => {
    onOpenChange?.(nextOpen, eventDetails);
    if (eventDetails.isCanceled) {
      return;
    }
    if (!nextOpen && snapPoints && snapPoints.length > 0) {
      setActiveSnapPoint(resolvedDefaultSnapPoint, useButton.createChangeEventDetails(eventDetails.reason, eventDetails.event, eventDetails.trigger));
    }
  });
  const contextValue = React__namespace.useMemo(() => ({
    swipeDirection,
    snapToSequentialPoints,
    snapPoints,
    activeSnapPoint: resolvedActiveSnapPoint,
    setActiveSnapPoint,
    frontmostHeight,
    popupHeight,
    hasNestedDrawer,
    nestedSwiping,
    nestedSwipeProgressStore,
    onNestedDrawerPresenceChange,
    onPopupHeightChange,
    onNestedFrontmostHeightChange,
    onNestedSwipingChange,
    onNestedSwipeProgressChange,
    notifyParentFrontmostHeight,
    notifyParentSwipingChange,
    notifyParentSwipeProgressChange,
    notifyParentHasNestedDrawer
  }), [resolvedActiveSnapPoint, frontmostHeight, hasNestedDrawer, nestedSwiping, nestedSwipeProgressStore, notifyParentHasNestedDrawer, notifyParentSwipeProgressChange, notifyParentSwipingChange, notifyParentFrontmostHeight, onNestedDrawerPresenceChange, onNestedFrontmostHeightChange, onNestedSwipeProgressChange, onNestedSwipingChange, onPopupHeightChange, popupHeight, setActiveSnapPoint, snapPoints, snapToSequentialPoints, swipeDirection]);
  const resolvedChildren = typeof children === 'function' ? payload => /*#__PURE__*/jsxRuntime.jsxs(React__namespace.Fragment, {
    children: [_DrawerProviderReport || (_DrawerProviderReport = /*#__PURE__*/jsxRuntime.jsx(DrawerProviderReporter, {})), children(payload)]
  }) : /*#__PURE__*/jsxRuntime.jsxs(React__namespace.Fragment, {
    children: [_DrawerProviderReport2 || (_DrawerProviderReport2 = /*#__PURE__*/jsxRuntime.jsx(DrawerProviderReporter, {})), children]
  });
  return /*#__PURE__*/jsxRuntime.jsx(DrawerRootContext.Provider, {
    value: contextValue,
    children: /*#__PURE__*/jsxRuntime.jsx(IsDrawerContext.Provider, {
      value: true,
      children: /*#__PURE__*/jsxRuntime.jsx(DialogRoot, {
        open: openProp,
        defaultOpen: defaultOpen,
        onOpenChange: handleOpenChange,
        onOpenChangeComplete: onOpenChangeComplete,
        disablePointerDismissal: disablePointerDismissal,
        modal: modal,
        actionsRef: actionsRef,
        handle: handle,
        triggerId: triggerIdProp,
        defaultTriggerId: defaultTriggerIdProp,
        children: resolvedChildren
      })
    })
  });
}
function createNestedSwipeProgressStore() {
  let progress = 0;
  const listeners = new Set();
  return {
    getSnapshot: () => progress,
    set(nextProgress) {
      const resolved = Number.isFinite(nextProgress) ? nextProgress : 0;
      if (resolved === progress) {
        return;
      }
      progress = resolved;
      listeners.forEach(listener => {
        listener();
      });
    },
    subscribe(listener) {
      listeners.add(listener);
      return () => {
        listeners.delete(listener);
      };
    }
  };
}
function DrawerProviderReporter() {
  const drawerId = useButton.useId();
  const providerContext = useDrawerProviderContext();
  const {
    store
  } = useDialogRootContext(false);
  const open = store.useState('open');
  const nestedOpenDialogCount = store.useState('nestedOpenDialogCount');
  const popupElement = store.useState('popupElement');
  const isTopmost = nestedOpenDialogCount === 0;
  React__namespace.useEffect(() => {
    if (!providerContext || drawerId == null) {
      return undefined;
    }
    return () => {
      providerContext.removeDrawer(drawerId);
    };
  }, [drawerId, providerContext]);
  React__namespace.useEffect(() => {
    if (drawerId == null) {
      return;
    }
    providerContext?.setDrawerOpen(drawerId, open);
  }, [drawerId, open, providerContext]);
  React__namespace.useEffect(() => {
    // CloseWatcher enables the Android back gesture (Chromium-only).
    // Keep this Android-only for now to avoid interfering with Escape/nesting semantics on desktop due to `useDismiss`.
    if (!open || !isTopmost || !useButton.android) {
      return undefined;
    }
    const win = floatingUi_utils_dom.getWindow(popupElement);
    const CloseWatcherCtor = win.CloseWatcher;
    if (!CloseWatcherCtor) {
      return undefined;
    }
    function handleCloseWatcher(event) {
      if (!store.select('open')) {
        return;
      }
      store.setOpen(false, useButton.createChangeEventDetails(useButton.closeWatcher, event));
    }
    const closeWatcher = new CloseWatcherCtor();
    const unsubscribe = useButton.addEventListener(closeWatcher, 'close', handleCloseWatcher);
    return () => {
      unsubscribe();
      closeWatcher.destroy();
    };
  }, [store, isTopmost, open, popupElement]);
  return null;
}

/**
 * A button that opens the drawer.
 * Renders a `<button>` element.
 *
 * Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
 */
const DrawerTrigger = DialogTrigger;

const ScrollAreaRootContext = /*#__PURE__*/React__namespace.createContext(undefined);
if (process.env.NODE_ENV !== "production") ScrollAreaRootContext.displayName = "ScrollAreaRootContext";
function useScrollAreaRootContext() {
  const context = React__namespace.useContext(ScrollAreaRootContext);
  if (context === undefined) {
    throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: ScrollAreaRootContext is missing. ScrollArea parts must be placed within <ScrollArea.Root>.' : useRenderElement.formatErrorMessage(53));
  }
  return context;
}

let ScrollAreaRootCssVars = /*#__PURE__*/function (ScrollAreaRootCssVars) {
  /**
   * The scroll area's corner height.
   * @type {number}
   */
  ScrollAreaRootCssVars["scrollAreaCornerHeight"] = "--scroll-area-corner-height";
  /**
   * The scroll area's corner width.
   * @type {number}
   */
  ScrollAreaRootCssVars["scrollAreaCornerWidth"] = "--scroll-area-corner-width";
  return ScrollAreaRootCssVars;
}({});

const SCROLL_TIMEOUT = 500;
const MIN_THUMB_SIZE = 16;

function getOffset(element, prop, axis) {
  if (!element) {
    return 0;
  }
  const styles = getComputedStyle(element);
  const propAxis = axis === 'x' ? 'Inline' : 'Block';

  // Safari misreports `marginInlineEnd` in RTL.
  // We have to assume the start/end values are symmetrical, which is likely.
  if (axis === 'x' && prop === 'margin') {
    return parseFloat(styles[`${prop}InlineStart`]) * 2;
  }
  return parseFloat(styles[`${prop}${propAxis}Start`]) + parseFloat(styles[`${prop}${propAxis}End`]);
}

let ScrollAreaScrollbarDataAttributes = /*#__PURE__*/function (ScrollAreaScrollbarDataAttributes) {
  /**
   * Indicates the orientation of the scrollbar.
   * @type {'horizontal' | 'vertical'}
   */
  ScrollAreaScrollbarDataAttributes["orientation"] = "data-orientation";
  /**
   * Present when the pointer is over the scroll area.
   */
  ScrollAreaScrollbarDataAttributes["hovering"] = "data-hovering";
  /**
   * Present when the user scrolls inside the scroll area.
   */
  ScrollAreaScrollbarDataAttributes["scrolling"] = "data-scrolling";
  /**
   * Present when the scroll area content is wider than the viewport.
   */
  ScrollAreaScrollbarDataAttributes["hasOverflowX"] = "data-has-overflow-x";
  /**
   * Present when the scroll area content is taller than the viewport.
   */
  ScrollAreaScrollbarDataAttributes["hasOverflowY"] = "data-has-overflow-y";
  /**
   * Present when there is overflow on the horizontal start side.
   */
  ScrollAreaScrollbarDataAttributes["overflowXStart"] = "data-overflow-x-start";
  /**
   * Present when there is overflow on the horizontal end side.
   */
  ScrollAreaScrollbarDataAttributes["overflowXEnd"] = "data-overflow-x-end";
  /**
   * Present when there is overflow on the vertical start side.
   */
  ScrollAreaScrollbarDataAttributes["overflowYStart"] = "data-overflow-y-start";
  /**
   * Present when there is overflow on the vertical end side.
   */
  ScrollAreaScrollbarDataAttributes["overflowYEnd"] = "data-overflow-y-end";
  return ScrollAreaScrollbarDataAttributes;
}({});

let ScrollAreaRootDataAttributes = /*#__PURE__*/function (ScrollAreaRootDataAttributes) {
  /**
   * Present when the user scrolls inside the scroll area.
   */
  ScrollAreaRootDataAttributes["scrolling"] = "data-scrolling";
  /**
   * Present when the scroll area content is wider than the viewport.
   */
  ScrollAreaRootDataAttributes["hasOverflowX"] = "data-has-overflow-x";
  /**
   * Present when the scroll area content is taller than the viewport.
   */
  ScrollAreaRootDataAttributes["hasOverflowY"] = "data-has-overflow-y";
  /**
   * Present when there is overflow on the horizontal start side.
   */
  ScrollAreaRootDataAttributes["overflowXStart"] = "data-overflow-x-start";
  /**
   * Present when there is overflow on the horizontal end side.
   */
  ScrollAreaRootDataAttributes["overflowXEnd"] = "data-overflow-x-end";
  /**
   * Present when there is overflow on the vertical start side.
   */
  ScrollAreaRootDataAttributes["overflowYStart"] = "data-overflow-y-start";
  /**
   * Present when there is overflow on the vertical end side.
   */
  ScrollAreaRootDataAttributes["overflowYEnd"] = "data-overflow-y-end";
  return ScrollAreaRootDataAttributes;
}({});

const scrollAreaStateAttributesMapping = {
  hasOverflowX: value => value ? {
    [ScrollAreaRootDataAttributes.hasOverflowX]: ''
  } : null,
  hasOverflowY: value => value ? {
    [ScrollAreaRootDataAttributes.hasOverflowY]: ''
  } : null,
  overflowXStart: value => value ? {
    [ScrollAreaRootDataAttributes.overflowXStart]: ''
  } : null,
  overflowXEnd: value => value ? {
    [ScrollAreaRootDataAttributes.overflowXEnd]: ''
  } : null,
  overflowYStart: value => value ? {
    [ScrollAreaRootDataAttributes.overflowYStart]: ''
  } : null,
  overflowYEnd: value => value ? {
    [ScrollAreaRootDataAttributes.overflowYEnd]: ''
  } : null,
  cornerHidden: () => null
};

const DEFAULT_COORDS = {
  x: 0,
  y: 0
};
const DEFAULT_SIZE = {
  width: 0,
  height: 0
};
const DEFAULT_OVERFLOW_EDGES = {
  xStart: false,
  xEnd: false,
  yStart: false,
  yEnd: false
};
const DEFAULT_HIDDEN_STATE = {
  x: true,
  y: true,
  corner: true
};
/**
 * Groups all parts of the scroll area.
 * Renders a `<div>` element.
 *
 * Documentation: [Base UI Scroll Area](https://base-ui.com/react/components/scroll-area)
 */
const ScrollAreaRoot = /*#__PURE__*/React__namespace.forwardRef(function ScrollAreaRoot(componentProps, forwardedRef) {
  const {
    render,
    className,
    overflowEdgeThreshold: overflowEdgeThresholdProp,
    style,
    ...elementProps
  } = componentProps;
  const {
    xStart,
    xEnd,
    yStart,
    yEnd
  } = normalizeOverflowEdgeThreshold(overflowEdgeThresholdProp);
  const rootId = useButton.useBaseUiId();
  const scrollYTimeout = useButton.useTimeout();
  const scrollXTimeout = useButton.useTimeout();
  const {
    nonce,
    disableStyleElements
  } = scrollEdges.useCSPContext();
  const [hovering, setHovering] = React__namespace.useState(false);
  const [scrollingX, setScrollingX] = React__namespace.useState(false);
  const [scrollingY, setScrollingY] = React__namespace.useState(false);
  const [touchModality, setTouchModality] = React__namespace.useState(false);
  const [hasMeasuredScrollbar, setHasMeasuredScrollbar] = React__namespace.useState(false);
  const [cornerSize, setCornerSize] = React__namespace.useState(DEFAULT_SIZE);
  const [thumbSize, setThumbSize] = React__namespace.useState(DEFAULT_SIZE);
  const [overflowEdges, setOverflowEdges] = React__namespace.useState(DEFAULT_OVERFLOW_EDGES);
  const [hiddenState, setHiddenState] = React__namespace.useState(DEFAULT_HIDDEN_STATE);
  const rootRef = React__namespace.useRef(null);
  const viewportRef = React__namespace.useRef(null);
  const scrollbarYRef = React__namespace.useRef(null);
  const scrollbarXRef = React__namespace.useRef(null);
  const thumbYRef = React__namespace.useRef(null);
  const thumbXRef = React__namespace.useRef(null);
  const cornerRef = React__namespace.useRef(null);
  const thumbDraggingRef = React__namespace.useRef(false);
  const startYRef = React__namespace.useRef(0);
  const startXRef = React__namespace.useRef(0);
  const startScrollTopRef = React__namespace.useRef(0);
  const startScrollLeftRef = React__namespace.useRef(0);
  const currentOrientationRef = React__namespace.useRef('vertical');
  const scrollPositionRef = React__namespace.useRef(DEFAULT_COORDS);
  const handleScroll = useButton.useStableCallback(scrollPosition => {
    const offsetX = scrollPosition.x - scrollPositionRef.current.x;
    const offsetY = scrollPosition.y - scrollPositionRef.current.y;
    scrollPositionRef.current = scrollPosition;
    if (offsetY !== 0) {
      setScrollingY(true);
      scrollYTimeout.start(SCROLL_TIMEOUT, () => {
        setScrollingY(false);
      });
    }
    if (offsetX !== 0) {
      setScrollingX(true);
      scrollXTimeout.start(SCROLL_TIMEOUT, () => {
        setScrollingX(false);
      });
    }
  });
  const handlePointerDown = useButton.useStableCallback(event => {
    if (event.button !== 0) {
      return;
    }
    thumbDraggingRef.current = true;
    startYRef.current = event.clientY;
    startXRef.current = event.clientX;
    currentOrientationRef.current = event.currentTarget.getAttribute(ScrollAreaScrollbarDataAttributes.orientation);
    if (viewportRef.current) {
      startScrollTopRef.current = viewportRef.current.scrollTop;
      startScrollLeftRef.current = viewportRef.current.scrollLeft;
    }
    if (thumbYRef.current && currentOrientationRef.current === 'vertical') {
      thumbYRef.current.setPointerCapture(event.pointerId);
    }
    if (thumbXRef.current && currentOrientationRef.current === 'horizontal') {
      thumbXRef.current.setPointerCapture(event.pointerId);
    }
  });
  const handlePointerMove = useButton.useStableCallback(event => {
    if (!thumbDraggingRef.current) {
      return;
    }
    const deltaY = event.clientY - startYRef.current;
    const deltaX = event.clientX - startXRef.current;
    if (viewportRef.current) {
      const scrollableContentHeight = viewportRef.current.scrollHeight;
      const viewportHeight = viewportRef.current.clientHeight;
      const scrollableContentWidth = viewportRef.current.scrollWidth;
      const viewportWidth = viewportRef.current.clientWidth;
      if (thumbYRef.current && scrollbarYRef.current && currentOrientationRef.current === 'vertical') {
        const scrollbarYOffset = getOffset(scrollbarYRef.current, 'padding', 'y');
        const thumbYOffset = getOffset(thumbYRef.current, 'margin', 'y');
        const thumbHeight = thumbYRef.current.offsetHeight;
        const maxThumbOffsetY = scrollbarYRef.current.offsetHeight - thumbHeight - scrollbarYOffset - thumbYOffset;
        const scrollRatioY = deltaY / maxThumbOffsetY;
        viewportRef.current.scrollTop = startScrollTopRef.current + scrollRatioY * (scrollableContentHeight - viewportHeight);
        event.preventDefault();
        setScrollingY(true);
        scrollYTimeout.start(SCROLL_TIMEOUT, () => {
          setScrollingY(false);
        });
      }
      if (thumbXRef.current && scrollbarXRef.current && currentOrientationRef.current === 'horizontal') {
        const scrollbarXOffset = getOffset(scrollbarXRef.current, 'padding', 'x');
        const thumbXOffset = getOffset(thumbXRef.current, 'margin', 'x');
        const thumbWidth = thumbXRef.current.offsetWidth;
        const maxThumbOffsetX = scrollbarXRef.current.offsetWidth - thumbWidth - scrollbarXOffset - thumbXOffset;
        const scrollRatioX = deltaX / maxThumbOffsetX;
        viewportRef.current.scrollLeft = startScrollLeftRef.current + scrollRatioX * (scrollableContentWidth - viewportWidth);
        event.preventDefault();
        setScrollingX(true);
        scrollXTimeout.start(SCROLL_TIMEOUT, () => {
          setScrollingX(false);
        });
      }
    }
  });
  const handlePointerUp = useButton.useStableCallback(event => {
    thumbDraggingRef.current = false;

    // `pointercancel` releases capture implicitly, so guard against releasing a
    // capture we no longer hold (which would throw).
    if (thumbYRef.current && currentOrientationRef.current === 'vertical' && thumbYRef.current.hasPointerCapture(event.pointerId)) {
      thumbYRef.current.releasePointerCapture(event.pointerId);
    }
    if (thumbXRef.current && currentOrientationRef.current === 'horizontal' && thumbXRef.current.hasPointerCapture(event.pointerId)) {
      thumbXRef.current.releasePointerCapture(event.pointerId);
    }
  });
  function handleTouchModalityChange(event) {
    setTouchModality(event.pointerType === 'touch');
  }
  function handlePointerEnterOrMove(event) {
    handleTouchModalityChange(event);
    if (event.pointerType !== 'touch') {
      const isTargetRootChild = useButton.contains(rootRef.current, event.target);
      setHovering(isTargetRootChild);
    }
  }
  const state = React__namespace.useMemo(() => ({
    scrolling: scrollingX || scrollingY,
    hasOverflowX: !hiddenState.x,
    hasOverflowY: !hiddenState.y,
    overflowXStart: overflowEdges.xStart,
    overflowXEnd: overflowEdges.xEnd,
    overflowYStart: overflowEdges.yStart,
    overflowYEnd: overflowEdges.yEnd,
    cornerHidden: hiddenState.corner
  }), [scrollingX, scrollingY, hiddenState.x, hiddenState.y, hiddenState.corner, overflowEdges]);
  const props = {
    role: 'presentation',
    onPointerEnter: handlePointerEnterOrMove,
    onPointerMove: handlePointerEnterOrMove,
    onPointerDown: handleTouchModalityChange,
    onPointerLeave() {
      setHovering(false);
    },
    style: {
      position: 'relative',
      [ScrollAreaRootCssVars.scrollAreaCornerHeight]: `${cornerSize.height}px`,
      [ScrollAreaRootCssVars.scrollAreaCornerWidth]: `${cornerSize.width}px`
    }
  };
  const element = useRenderElement.useRenderElement('div', componentProps, {
    state,
    ref: [forwardedRef, rootRef],
    props: [props, elementProps],
    stateAttributesMapping: scrollAreaStateAttributesMapping
  });
  const contextValue = React__namespace.useMemo(() => ({
    handlePointerDown,
    handlePointerMove,
    handlePointerUp,
    handleScroll,
    cornerSize,
    setCornerSize,
    thumbSize,
    setThumbSize,
    hasMeasuredScrollbar,
    setHasMeasuredScrollbar,
    touchModality,
    cornerRef,
    scrollingX,
    setScrollingX,
    scrollingY,
    setScrollingY,
    hovering,
    setHovering,
    viewportRef,
    rootRef,
    scrollbarYRef,
    scrollbarXRef,
    thumbYRef,
    thumbXRef,
    rootId,
    hiddenState,
    setHiddenState,
    overflowEdges,
    setOverflowEdges,
    viewportState: state,
    overflowEdgeThreshold: {
      xStart,
      xEnd,
      yStart,
      yEnd
    }
  }), [handlePointerDown, handlePointerMove, handlePointerUp, handleScroll, cornerSize, thumbSize, hasMeasuredScrollbar, touchModality, scrollingX, setScrollingX, scrollingY, setScrollingY, hovering, setHovering, rootId, hiddenState, overflowEdges, state, xStart, xEnd, yStart, yEnd]);
  return /*#__PURE__*/jsxRuntime.jsxs(ScrollAreaRootContext.Provider, {
    value: contextValue,
    children: [!disableStyleElements && scrollEdges.styleDisableScrollbar.getElement(nonce), element]
  });
});
if (process.env.NODE_ENV !== "production") ScrollAreaRoot.displayName = "ScrollAreaRoot";
function normalizeOverflowEdgeThreshold(threshold) {
  if (typeof threshold === 'number') {
    const value = Math.max(0, threshold);
    return {
      xStart: value,
      xEnd: value,
      yStart: value,
      yEnd: value
    };
  }
  return {
    xStart: Math.max(0, threshold?.xStart || 0),
    xEnd: Math.max(0, threshold?.xEnd || 0),
    yStart: Math.max(0, threshold?.yStart || 0),
    yEnd: Math.max(0, threshold?.yEnd || 0)
  };
}

const ScrollAreaViewportContext = /*#__PURE__*/React__namespace.createContext(undefined);
if (process.env.NODE_ENV !== "production") ScrollAreaViewportContext.displayName = "ScrollAreaViewportContext";
function useScrollAreaViewportContext() {
  const context = React__namespace.useContext(ScrollAreaViewportContext);
  if (context === undefined) {
    throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: ScrollAreaViewportContext missing. ScrollAreaViewport parts must be placed within <ScrollArea.Viewport>.' : useRenderElement.formatErrorMessage(55));
  }
  return context;
}

let ScrollAreaViewportCssVars = /*#__PURE__*/function (ScrollAreaViewportCssVars) {
  /**
   * The distance from the horizontal start edge in pixels.
   * @type {number}
   */
  ScrollAreaViewportCssVars["scrollAreaOverflowXStart"] = "--scroll-area-overflow-x-start";
  /**
   * The distance from the horizontal end edge in pixels.
   * @type {number}
   */
  ScrollAreaViewportCssVars["scrollAreaOverflowXEnd"] = "--scroll-area-overflow-x-end";
  /**
   * The distance from the vertical start edge in pixels.
   * @type {number}
   */
  ScrollAreaViewportCssVars["scrollAreaOverflowYStart"] = "--scroll-area-overflow-y-start";
  /**
   * The distance from the vertical end edge in pixels.
   * @type {number}
   */
  ScrollAreaViewportCssVars["scrollAreaOverflowYEnd"] = "--scroll-area-overflow-y-end";
  return ScrollAreaViewportCssVars;
}({});

let scrollAreaOverflowVarsRegistered = false;

/**
 * Removes inheritance of the scroll area overflow CSS variables, which
 * improves rendering performance in complex scroll areas with deep subtrees.
 * Instead, each child must manually opt-in to using these properties by
 * specifying `inherit`.
 * See https://motion.dev/blog/web-animation-performance-tier-list
 * under the "Improving CSS variable performance" section.
 */
function removeCSSVariableInheritance() {
  if (scrollAreaOverflowVarsRegistered ||
  // When `inherits: false`, specifying `inherit` on child elements doesn't work
  // in Safari. To let CSS features work correctly, this optimization must be skipped.
  useScrollLock.webkit) {
    return;
  }
  if (typeof CSS !== 'undefined' && 'registerProperty' in CSS) {
    [ScrollAreaViewportCssVars.scrollAreaOverflowXStart, ScrollAreaViewportCssVars.scrollAreaOverflowXEnd, ScrollAreaViewportCssVars.scrollAreaOverflowYStart, ScrollAreaViewportCssVars.scrollAreaOverflowYEnd].forEach(name => {
      try {
        CSS.registerProperty({
          name,
          syntax: '<length>',
          inherits: false,
          initialValue: '0px'
        });
      } catch {
        /* ignore already-registered */
      }
    });
  }
  scrollAreaOverflowVarsRegistered = true;
}

/**
 * The actual scrollable container of the scroll area.
 * Renders a `<div>` element.
 *
 * Documentation: [Base UI Scroll Area](https://base-ui.com/react/components/scroll-area)
 */
const ScrollAreaViewport = /*#__PURE__*/React__namespace.forwardRef(function ScrollAreaViewport(componentProps, forwardedRef) {
  const {
    render,
    className,
    style,
    ...elementProps
  } = componentProps;
  const {
    viewportRef,
    scrollbarYRef,
    scrollbarXRef,
    thumbYRef,
    thumbXRef,
    cornerRef,
    cornerSize,
    setCornerSize,
    setThumbSize,
    rootId,
    setHiddenState,
    hiddenState,
    setHasMeasuredScrollbar,
    handleScroll,
    setHovering,
    setOverflowEdges,
    overflowEdges,
    overflowEdgeThreshold,
    scrollingX,
    scrollingY
  } = useScrollAreaRootContext();
  const direction = useScrollLock.useDirection();
  const programmaticScrollRef = React__namespace.useRef(true);
  const lastMeasuredViewportMetricsRef = React__namespace.useRef([NaN, NaN, NaN, NaN]);
  const scrollEndTimeout = useButton.useTimeout();
  const waitForAnimationsTimeout = useButton.useTimeout();
  const computeThumbPosition = useButton.useStableCallback(() => {
    const viewportEl = viewportRef.current;
    const scrollbarYEl = scrollbarYRef.current;
    const scrollbarXEl = scrollbarXRef.current;
    const thumbYEl = thumbYRef.current;
    const thumbXEl = thumbXRef.current;
    const cornerEl = cornerRef.current;
    if (!viewportEl) {
      return;
    }
    const scrollableContentHeight = viewportEl.scrollHeight;
    const scrollableContentWidth = viewportEl.scrollWidth;
    const viewportHeight = viewportEl.clientHeight;
    const viewportWidth = viewportEl.clientWidth;
    const scrollTop = viewportEl.scrollTop;
    const scrollLeft = viewportEl.scrollLeft;
    const lastMeasuredViewportMetrics = lastMeasuredViewportMetricsRef.current;
    const isFirstMeasurement = Number.isNaN(lastMeasuredViewportMetrics[0]);
    lastMeasuredViewportMetrics[0] = viewportHeight;
    lastMeasuredViewportMetrics[1] = scrollableContentHeight;
    lastMeasuredViewportMetrics[2] = viewportWidth;
    lastMeasuredViewportMetrics[3] = scrollableContentWidth;
    if (isFirstMeasurement) {
      setHasMeasuredScrollbar(true);
    }
    if (scrollableContentHeight === 0 || scrollableContentWidth === 0) {
      return;
    }
    const nextHiddenState = getHiddenState(viewportEl);
    const scrollbarYHidden = nextHiddenState.y;
    const scrollbarXHidden = nextHiddenState.x;
    const ratioX = viewportWidth / scrollableContentWidth;
    const ratioY = viewportHeight / scrollableContentHeight;
    const maxScrollLeft = Math.max(0, scrollableContentWidth - viewportWidth);
    const maxScrollTop = Math.max(0, scrollableContentHeight - viewportHeight);
    let scrollLeftFromStart = 0;
    let scrollLeftFromEnd = 0;
    if (!scrollbarXHidden) {
      let rawScrollLeftFromStart = 0;
      if (direction === 'rtl') {
        rawScrollLeftFromStart = clamp.clamp(-scrollLeft, 0, maxScrollLeft);
      } else {
        rawScrollLeftFromStart = clamp.clamp(scrollLeft, 0, maxScrollLeft);
      }
      scrollLeftFromStart = scrollEdges.normalizeScrollOffset(rawScrollLeftFromStart, maxScrollLeft);
      scrollLeftFromEnd = maxScrollLeft - scrollLeftFromStart;
    }
    const rawScrollTopFromStart = !scrollbarYHidden ? clamp.clamp(scrollTop, 0, maxScrollTop) : 0;
    const scrollTopFromStart = !scrollbarYHidden ? scrollEdges.normalizeScrollOffset(rawScrollTopFromStart, maxScrollTop) : 0;
    const scrollTopFromEnd = !scrollbarYHidden ? maxScrollTop - scrollTopFromStart : 0;
    const nextWidth = scrollbarXHidden ? 0 : viewportWidth;
    const nextHeight = scrollbarYHidden ? 0 : viewportHeight;
    let nextCornerWidth = 0;
    let nextCornerHeight = 0;
    if (!scrollbarXHidden && !scrollbarYHidden) {
      nextCornerWidth = scrollbarYEl?.offsetWidth || 0;
      nextCornerHeight = scrollbarXEl?.offsetHeight || 0;
    }

    // Only subtract corner size from scrollbar dimensions if the corner hasn't been sized yet.
    // Once sized, the layout will already account for it.
    const cornerNotYetSized = cornerSize.width === 0 && cornerSize.height === 0;
    const cornerWidthOffset = cornerNotYetSized ? nextCornerWidth : 0;
    const cornerHeightOffset = cornerNotYetSized ? nextCornerHeight : 0;
    const scrollbarXOffset = getOffset(scrollbarXEl, 'padding', 'x');
    const scrollbarYOffset = getOffset(scrollbarYEl, 'padding', 'y');
    const thumbXOffset = getOffset(thumbXEl, 'margin', 'x');
    const thumbYOffset = getOffset(thumbYEl, 'margin', 'y');
    const idealNextWidth = nextWidth - scrollbarXOffset - thumbXOffset;
    const idealNextHeight = nextHeight - scrollbarYOffset - thumbYOffset;
    const maxNextWidth = scrollbarXEl ? Math.min(scrollbarXEl.offsetWidth - cornerWidthOffset, idealNextWidth) : idealNextWidth;
    const maxNextHeight = scrollbarYEl ? Math.min(scrollbarYEl.offsetHeight - cornerHeightOffset, idealNextHeight) : idealNextHeight;
    const clampedNextWidth = Math.max(MIN_THUMB_SIZE, maxNextWidth * ratioX);
    const clampedNextHeight = Math.max(MIN_THUMB_SIZE, maxNextHeight * ratioY);
    setThumbSize(prevSize => {
      if (prevSize.height === clampedNextHeight && prevSize.width === clampedNextWidth) {
        return prevSize;
      }
      return {
        width: clampedNextWidth,
        height: clampedNextHeight
      };
    });

    // Handle Y (vertical) scroll
    if (scrollbarYEl && thumbYEl) {
      const maxThumbOffsetY = scrollbarYEl.offsetHeight - clampedNextHeight - scrollbarYOffset - thumbYOffset;
      const scrollRangeY = scrollableContentHeight - viewportHeight;
      const scrollRatioY = scrollRangeY === 0 ? 0 : scrollTop / scrollRangeY;

      // In Safari, don't allow it to go negative or too far as `scrollTop` considers the rubber
      // band effect.
      const thumbOffsetY = Math.min(maxThumbOffsetY, Math.max(0, scrollRatioY * maxThumbOffsetY));
      thumbYEl.style.transform = `translate3d(0,${thumbOffsetY}px,0)`;
    }

    // Handle X (horizontal) scroll
    if (scrollbarXEl && thumbXEl) {
      const maxThumbOffsetX = scrollbarXEl.offsetWidth - clampedNextWidth - scrollbarXOffset - thumbXOffset;
      const scrollRangeX = scrollableContentWidth - viewportWidth;
      const scrollRatioX = scrollRangeX === 0 ? 0 : scrollLeft / scrollRangeX;

      // In Safari, don't allow it to go negative or too far as `scrollLeft` considers the rubber
      // band effect.
      const thumbOffsetX = direction === 'rtl' ? clamp.clamp(scrollRatioX * maxThumbOffsetX, -maxThumbOffsetX, 0) : clamp.clamp(scrollRatioX * maxThumbOffsetX, 0, maxThumbOffsetX);
      thumbXEl.style.transform = `translate3d(${thumbOffsetX}px,0,0)`;
    }
    const overflowMetricsPx = [[ScrollAreaViewportCssVars.scrollAreaOverflowXStart, scrollLeftFromStart], [ScrollAreaViewportCssVars.scrollAreaOverflowXEnd, scrollLeftFromEnd], [ScrollAreaViewportCssVars.scrollAreaOverflowYStart, scrollTopFromStart], [ScrollAreaViewportCssVars.scrollAreaOverflowYEnd, scrollTopFromEnd]];
    for (const [cssVar, value] of overflowMetricsPx) {
      viewportEl.style.setProperty(cssVar, `${value}px`);
    }
    if (cornerEl) {
      if (scrollbarXHidden || scrollbarYHidden) {
        setCornerSize({
          width: 0,
          height: 0
        });
      } else if (!scrollbarXHidden && !scrollbarYHidden) {
        setCornerSize({
          width: nextCornerWidth,
          height: nextCornerHeight
        });
      }
    }
    setHiddenState(prevState => mergeHiddenState(prevState, nextHiddenState));
    const nextOverflowEdges = {
      xStart: !scrollbarXHidden && scrollLeftFromStart > overflowEdgeThreshold.xStart,
      xEnd: !scrollbarXHidden && scrollLeftFromEnd > overflowEdgeThreshold.xEnd,
      yStart: !scrollbarYHidden && scrollTopFromStart > overflowEdgeThreshold.yStart,
      yEnd: !scrollbarYHidden && scrollTopFromEnd > overflowEdgeThreshold.yEnd
    };
    setOverflowEdges(prev => {
      if (prev.xStart === nextOverflowEdges.xStart && prev.xEnd === nextOverflowEdges.xEnd && prev.yStart === nextOverflowEdges.yStart && prev.yEnd === nextOverflowEdges.yEnd) {
        return prev;
      }
      return nextOverflowEdges;
    });
  });
  useButton.useIsoLayoutEffect(() => {
    if (!viewportRef.current) {
      return;
    }
    removeCSSVariableInheritance();
  }, [viewportRef]);
  useButton.useIsoLayoutEffect(() => {
    // Wait for scrollbar and thumb refs after hidden-state toggles, refresh math on direction
    // flips, and re-evaluate overflow edges when the threshold changes.
    queueMicrotask(computeThumbPosition);
  }, [computeThumbPosition, hiddenState, direction, overflowEdgeThreshold.xStart, overflowEdgeThreshold.xEnd, overflowEdgeThreshold.yStart, overflowEdgeThreshold.yEnd]);
  useButton.useIsoLayoutEffect(() => {
    // `onMouseEnter` doesn't fire upon load, so we need to check if the viewport is already
    // being hovered.
    if (viewportRef.current?.matches(':hover')) {
      setHovering(true);
    }
  }, [viewportRef, setHovering]);
  useButton.useIsoLayoutEffect(() => {
    const viewport = viewportRef.current;
    if (typeof ResizeObserver === 'undefined' || !viewport) {
      return undefined;
    }
    let hasInitialized = false;
    const resizeObserver = new ResizeObserver(() => {
      // Avoid duplicate mount-time recompute when observer data matches what the mount
      // scheduling pass already measured. If dimensions changed before the first observer
      // delivery, keep the recompute so overflow transitions stay in sync.
      if (!hasInitialized) {
        hasInitialized = true;
        const lastMeasuredViewportMetrics = lastMeasuredViewportMetricsRef.current;
        if (lastMeasuredViewportMetrics[0] === viewport.clientHeight && lastMeasuredViewportMetrics[1] === viewport.scrollHeight && lastMeasuredViewportMetrics[2] === viewport.clientWidth && lastMeasuredViewportMetrics[3] === viewport.scrollWidth) {
          return;
        }
      }
      computeThumbPosition();
    });
    resizeObserver.observe(viewport);

    // Wait for subtree animations to finish, then recompute thumb geometry that
    // may have been affected by transform-based animations.
    waitForAnimationsTimeout.start(0, () => {
      const animations = viewport.getAnimations({
        subtree: true
      });
      if (animations.length === 0) {
        return;
      }
      Promise.allSettled(animations.map(animation => animation.finished)).then(computeThumbPosition).catch(() => {});
    });
    return () => {
      resizeObserver.disconnect();
      waitForAnimationsTimeout.clear();
    };
  }, [computeThumbPosition, viewportRef, waitForAnimationsTimeout]);
  function handleUserInteraction() {
    programmaticScrollRef.current = false;
  }
  const props = {
    role: 'presentation',
    ...(rootId && {
      'data-id': `${rootId}-viewport`
    }),
    // https://accessibilityinsights.io/info-examples/web/scrollable-region-focusable/
    // Keep non-scrollable viewports out of tab order.
    tabIndex: hiddenState.x && hiddenState.y ? -1 : 0,
    className: scrollEdges.styleDisableScrollbar.className,
    style: {
      overflow: 'scroll'
    },
    onScroll() {
      if (!viewportRef.current) {
        return;
      }
      computeThumbPosition();
      if (!programmaticScrollRef.current) {
        handleScroll({
          x: viewportRef.current.scrollLeft,
          y: viewportRef.current.scrollTop
        });
      }

      // Debounce the restoration of the programmatic flag so that it only
      // flips back to `true` once scrolling has come to a rest. This ensures
      // that momentum scrolling (where no further user-interaction events fire)
      // is still treated as user-driven.
      // 100 ms without scroll events ≈ scroll end
      // https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollend_event
      scrollEndTimeout.start(100, () => {
        programmaticScrollRef.current = true;
      });
    },
    onWheel: handleUserInteraction,
    onTouchMove: handleUserInteraction,
    onPointerMove: handleUserInteraction,
    onPointerEnter: handleUserInteraction,
    onKeyDown: handleUserInteraction
  };
  const viewportState = React__namespace.useMemo(() => ({
    scrolling: scrollingX || scrollingY,
    hasOverflowX: !hiddenState.x,
    hasOverflowY: !hiddenState.y,
    overflowXStart: overflowEdges.xStart,
    overflowXEnd: overflowEdges.xEnd,
    overflowYStart: overflowEdges.yStart,
    overflowYEnd: overflowEdges.yEnd,
    cornerHidden: hiddenState.corner
  }), [scrollingX, scrollingY, hiddenState.x, hiddenState.y, hiddenState.corner, overflowEdges]);
  const element = useRenderElement.useRenderElement('div', componentProps, {
    ref: [forwardedRef, viewportRef],
    state: viewportState,
    props: [props, elementProps],
    stateAttributesMapping: scrollAreaStateAttributesMapping
  });
  const contextValue = React__namespace.useMemo(() => ({
    computeThumbPosition
  }), [computeThumbPosition]);
  return /*#__PURE__*/jsxRuntime.jsx(ScrollAreaViewportContext.Provider, {
    value: contextValue,
    children: element
  });
});
if (process.env.NODE_ENV !== "production") ScrollAreaViewport.displayName = "ScrollAreaViewport";
function getHiddenState(viewport) {
  const y = viewport.clientHeight >= viewport.scrollHeight;
  const x = viewport.clientWidth >= viewport.scrollWidth;
  return {
    y,
    x,
    corner: y || x
  };
}
function mergeHiddenState(prevState, nextState) {
  if (prevState.y === nextState.y && prevState.x === nextState.x && prevState.corner === nextState.corner) {
    return prevState;
  }
  return nextState;
}

exports.DRAWER_CONTENT_ATTRIBUTE = DRAWER_CONTENT_ATTRIBUTE;
exports.DialogPortal = DialogPortal;
exports.DialogRoot = DialogRoot;
exports.DialogStore = DialogStore;
exports.DialogTrigger = DialogTrigger;
exports.DrawerBackdrop = DrawerBackdrop;
exports.DrawerBackdropCssVars = DrawerBackdropCssVars;
exports.DrawerContent = DrawerContent;
exports.DrawerPopup = DrawerPopup;
exports.DrawerPopupCssVars = DrawerPopupCssVars;
exports.DrawerPopupDataAttributes = DrawerPopupDataAttributes;
exports.DrawerPortal = DrawerPortal;
exports.DrawerProviderContext = DrawerProviderContext;
exports.DrawerRoot = DrawerRoot;
exports.DrawerTrigger = DrawerTrigger;
exports.DrawerViewportContext = DrawerViewportContext;
exports.ScrollAreaRoot = ScrollAreaRoot;
exports.ScrollAreaRootCssVars = ScrollAreaRootCssVars;
exports.ScrollAreaViewport = ScrollAreaViewport;
exports.createInitialPopupStoreState = createInitialPopupStoreState;
exports.getOffset = getOffset;
exports.getSnapPointSwipeMovement = getSnapPointSwipeMovement;
exports.popupStoreSelectors = popupStoreSelectors;
exports.scrollAreaStateAttributesMapping = scrollAreaStateAttributesMapping;
exports.useDialogPortalContext = useDialogPortalContext;
exports.useDialogRootContext = useDialogRootContext;
exports.useDrawerProviderContext = useDrawerProviderContext;
exports.useDrawerRootContext = useDrawerRootContext;
exports.useDrawerSnapPoints = useDrawerSnapPoints;
exports.useScrollAreaRootContext = useScrollAreaRootContext;
exports.useScrollAreaViewportContext = useScrollAreaViewportContext;
