import React__default, { useMemo, isValidElement, cloneElement, useRef, useState, useCallback, useEffect, createContext } from 'react';
import './warning-s9zGJbnw.js';

/* eslint-disable no-restricted-globals, eqeqeq  */

/**
 * React currently throws a warning when using useLayoutEffect on the server.
 * To get around it, we can conditionally useEffect on the server (no-op) and
 * useLayoutEffect in the browser. We occasionally need useLayoutEffect to
 * ensure we don't get a render flash for certain operations, but we may also
 * need affected components to render on the server. One example is when setting
 * a component's descendants to retrieve their index values.
 *
 * Important to note that using this hook as an escape hatch will break the
 * eslint dependency warnings unless you rename the import to `useLayoutEffect`.
 * Use sparingly only when the effect won't effect the rendered HTML to avoid
 * any server/client mismatch.
 *
 * If a useLayoutEffect is needed and the result would create a mismatch, it's
 * likely that the component in question shouldn't be rendered on the server at
 * all, so a better approach would be to lazily render those in a parent
 * component after client-side hydration.
 *
 * TODO: We are calling useLayoutEffect in a couple of places that will likely
 * cause some issues for SSR users, whether the warning shows or not. Audit and
 * fix these.
 *
 * https://gist.github.com/gaearon/e7d97cdf38a2907924ea12e4ebdf3c85
 * https://github.com/reduxjs/react-redux/blob/master/src/utils/useIsomorphicLayoutEffect.js
 *
 * @param effect
 * @param deps
 */

var useIsomorphicLayoutEffect = /*#__PURE__*/canUseDOM() ? React__default.useLayoutEffect : React__default.useEffect;
var checkedPkgs = {};
/**
 * When in dev mode, checks that styles for a given @reach package are loaded.
 *
 * @param packageName Name of the package to check.
 * @example checkStyles("dialog") will check for styles for @reach/dialog
 */
// @ts-ignore

var checkStyles = noop;

if (process.env.NODE_ENV !== "production") {
  // In CJS files, process.env.NODE_ENV is stripped from our build, but we need
  // it to prevent style checks from clogging up user logs while testing.
  // This is a workaround until we can tweak the build a bit to accommodate.
  var _ref = typeof process !== "undefined" ? process : {
    env: {
      NODE_ENV: "development"
    }
  },
      env = _ref.env;

  checkStyles = function checkStyles(packageName) {
    // only check once per package
    if (checkedPkgs[packageName]) return;
    checkedPkgs[packageName] = true;

    if (env.NODE_ENV !== "test" && parseInt(window.getComputedStyle(document.body).getPropertyValue("--reach-" + packageName), 10) !== 1) {
      console.warn("@reach/" + packageName + " styles not found. If you are using a bundler like webpack or parcel include this in the entry file of your app before any of your own styles:\n\n    import \"@reach/" + packageName + "/styles.css\";\n\n  Otherwise you'll need to include them some other way:\n\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"node_modules/@reach/" + packageName + "/styles.css\" />\n\n  For more information visit https://ui.reach.tech/styling.\n  ");
    }
  };
}
/**
 * Passes or assigns an arbitrary value to a ref function or object.
 *
 * @param ref
 * @param value
 */

function assignRef(ref, value) {
  if (ref == null) return;

  if (isFunction(ref)) {
    ref(value);
  } else {
    try {
      ref.current = value;
    } catch (error) {
      throw new Error("Cannot assign value \"" + value + "\" to ref \"" + ref + "\"");
    }
  }
}
/**
 * Checks true|"true" vs false|"false"
 *
 * @param value
 */


function boolOrBoolString(value) {
  return value === "true" ? true : isBoolean(value) ? value : false;
}

function canUseDOM() {
  return !!(typeof window !== "undefined" && window.document && window.document.createElement);
}
/**
 * Type-safe clone element
 *
 * @param element
 * @param props
 * @param children
 */


function cloneValidElement(element, props) {
  for (var _len = arguments.length, children = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
    children[_key - 2] = arguments[_key];
  }

  return /*#__PURE__*/isValidElement(element) ? cloneElement.apply(void 0, [element, props].concat(children)) : element;
}

function createNamedContext(name, defaultValue) {
  var Ctx = /*#__PURE__*/createContext(defaultValue);
  Ctx.displayName = name;
  return Ctx;
}
/**
 * This is a hack for sure. The thing is, getting a component to intelligently
 * infer props based on a component or JSX string passed into an `as` prop is
 * kind of a huge pain. Getting it to work and satisfy the constraints of
 * `forwardRef` seems dang near impossible. To avoid needing to do this awkward
 * type song-and-dance every time we want to forward a ref into a component
 * that accepts an `as` prop, we abstract all of that mess to this function for
 * the time time being.
 */


function forwardRefWithAs(render) {
  return /*#__PURE__*/React__default.forwardRef(render);
}

function memoWithAs(Component, propsAreEqual) {
  return /*#__PURE__*/React__default.memo(Component, propsAreEqual);
}
/**
 * Get the size of the working document minus the scrollbar offset.
 *
 * @param element
 */


function getDocumentDimensions(element) {
  if (!canUseDOM()) return {
    width: 0,
    height: 0
  };
  var doc = document;
  var win = window;
  return {
    width: doc.documentElement.clientWidth || win.innerWidth,
    height: doc.documentElement.clientHeight || win.innerHeight
  };
}
/**
 * Get a computed style value by property, backwards compatible with IE
 * @param element
 * @param styleProp
 */


function getElementComputedStyle(element, styleProp) {
  var y = null;
  var doc = getOwnerDocument(element);

  if (element.currentStyle) {
    y = element.currentStyle[styleProp];
  } else if (doc && doc.defaultView && isFunction(doc.defaultView.getComputedStyle)) {
    y = doc.defaultView.getComputedStyle(element, null).getPropertyValue(styleProp);
  }

  return y;
}
/**
 * Get an element's owner document. Useful when components are used in iframes
 * or other environments like dev tools.
 *
 * @param element
 */


function getOwnerDocument(element) {
  return element && element.ownerDocument ? element.ownerDocument : canUseDOM() ? document : null;
}
/**
 * Checks whether or not a value is a boolean.
 *
 * @param value
 */


function isBoolean(value) {
  return typeof value === "boolean";
}
/**
 * Checks whether or not a value is a function.
 *
 * @param value
 */


function isFunction(value) {
  return !!(value && {}.toString.call(value) == "[object Function]");
}
/**
 * Checks whether or not a value is a number.
 *
 * @param value
 */


function isNumber(value) {
  return typeof value === "number" && !isNaN(value);
}
/**
 * Checks whether or not a value is a string.
 *
 * @param value
 */


function isString(value) {
  return typeof value === "string";
}
/**
 * Joins strings to format IDs for compound components.
 *
 * @param args
 */


function makeId() {
  for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
    args[_key2] = arguments[_key2];
  }

  return args.filter(function (val) {
    return val != null;
  }).join("--");
}
/**
 * No-op function.
 */


function noop() {}
/**
 * Check if a component is controlled or uncontrolled and return the correct
 * state value and setter accordingly. If the component state is controlled by
 * the app, the setter is a noop.
 *
 * @param controlledValue
 * @param defaultValue
 */


function useControlledState(controlledValue, defaultValue) {
  var controlledRef = useRef(controlledValue != null);

  var _useState = useState(defaultValue),
      valueState = _useState[0],
      setValue = _useState[1];

  var set = useCallback(function (n) {
    if (!controlledRef.current) {
      setValue(n);
    }
  }, []);
  return [controlledRef.current ? controlledValue : valueState, set];
}
/**
 * Logs a warning in dev mode when a component switches from controlled to
 * uncontrolled, or vice versa
 *
 * A single prop should typically be used to determine whether or not a
 * component is controlled or not.
 *
 * @param controlledValue
 * @param controlledPropName
 * @param componentName
 */


var useControlledSwitchWarning = noop;

if (process.env.NODE_ENV !== "production") {
  useControlledSwitchWarning = function useControlledSwitchWarning(controlledValue, controlledPropName, componentName) {
    var controlledRef = useRef(controlledValue != null);
    var nameCache = useRef({
      componentName: componentName,
      controlledPropName: controlledPropName
    });
    useEffect(function () {
      nameCache.current = {
        componentName: componentName,
        controlledPropName: controlledPropName
      };
    }, [componentName, controlledPropName]);
    useEffect(function () {
      var wasControlled = controlledRef.current;
      var _nameCache$current = nameCache.current,
          componentName = _nameCache$current.componentName,
          controlledPropName = _nameCache$current.controlledPropName;
      var isControlled = controlledValue != null;

      if (wasControlled !== isControlled) {
        console.error("A component is changing an " + (wasControlled ? "" : "un") + "controlled `" + controlledPropName + "` state of " + componentName + " to be " + (wasControlled ? "un" : "") + "controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled " + componentName + " element for the lifetime of the component.\nMore info: https://fb.me/react-controlled-components");
      }
    }, [controlledValue]);
  };
}

if (process.env.NODE_ENV !== "production") ;
/**
 * @param callback
 */


function useEventCallback(callback) {
  var ref = useRef(callback);
  useIsomorphicLayoutEffect(function () {
    ref.current = callback;
  });
  return useCallback(function (event) {
    for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
      args[_key3 - 1] = arguments[_key3];
    }

    return ref.current.apply(ref, [event].concat(args));
  }, []);
}
/**
 * Forces a re-render, similar to `forceUpdate` in class components.
 */


function useForceUpdate() {
  var _useState2 = useState(Object.create(null)),
      dispatch = _useState2[1];

  return useCallback(function () {
    dispatch(Object.create(null));
  }, []);
}
/**
 * Passes or assigns a value to multiple refs (typically a DOM node). Useful for
 * dealing with components that need an explicit ref for DOM calculations but
 * also forwards refs assigned by an app.
 *
 * @param refs Refs to fork
 */


function useForkedRef() {
  for (var _len4 = arguments.length, refs = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
    refs[_key4] = arguments[_key4];
  }

  return useMemo(function () {
    if (refs.every(function (ref) {
      return ref == null;
    })) {
      return null;
    }

    return function (node) {
      refs.forEach(function (ref) {
        assignRef(ref, node);
      });
    }; // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [].concat(refs));
}
/**
 * Returns the previous value of a reference after a component update.
 *
 * @param value
 */


function usePrevious(value) {
  var ref = useRef(null);
  useEffect(function () {
    ref.current = value;
  }, [value]);
  return ref.current;
}
/**
 * Call an effect after a component update, skipping the initial mount.
 *
 * @param effect Effect to call
 * @param deps Effect dependency list
 */


function useUpdateEffect(effect, deps) {
  var mounted = useRef(false);
  useEffect(function () {
    if (mounted.current) {
      effect();
    } else {
      mounted.current = true;
    } // eslint-disable-next-line react-hooks/exhaustive-deps

  }, deps);
}

if (process.env.NODE_ENV !== "production") ;
/**
 * Wraps a lib-defined event handler and a user-defined event handler, returning
 * a single handler that allows a user to prevent lib-defined handlers from
 * firing.
 *
 * @param theirHandler User-supplied event handler
 * @param ourHandler Library-supplied event handler
 */


function wrapEvent(theirHandler, ourHandler) {
  return function (event) {
    theirHandler && theirHandler(event);

    if (!event.defaultPrevented) {
      return ourHandler(event);
    }
  };
}

export { useForceUpdate as a, useForkedRef as b, createNamedContext as c, usePrevious as d, memoWithAs as e, forwardRefWithAs as f, getOwnerDocument as g, useControlledSwitchWarning as h, isNumber as i, useControlledState as j, isFunction as k, checkStyles as l, makeId as m, noop as n, getElementComputedStyle as o, useEventCallback as p, boolOrBoolString as q, cloneValidElement as r, useUpdateEffect as s, getDocumentDimensions as t, useIsomorphicLayoutEffect as u, isString as v, wrapEvent as w };
