'use strict';

var design = require('@jobber/design');
var React = require('react');
var _commonjsHelpers = require('./_commonjsHelpers-cjs.js');
var identity = require('./identity-cjs.js');
var _baseAssignValue = require('./_baseAssignValue-cjs.js');
var _baseFor = require('./_baseFor-cjs.js');
var keysIn$2 = require('./keysIn-cjs.js');
var isTypedArray$1 = require('./isTypedArray-cjs.js');
var isObjectLike$1 = require('./isObjectLike-cjs.js');
var _isIterateeCall = require('./_isIterateeCall-cjs.js');

var baseAssignValue = _baseAssignValue._baseAssignValue,
    eq = identity.eq_1;

/**
 * This function is like `assignValue` except that it doesn't assign
 * `undefined` values.
 *
 * @private
 * @param {Object} object The object to modify.
 * @param {string} key The key of the property to assign.
 * @param {*} value The value to assign.
 */
function assignMergeValue$2(object, key, value) {
  if ((value !== undefined && !eq(object[key], value)) ||
      (value === undefined && !(key in object))) {
    baseAssignValue(object, key, value);
  }
}

var _assignMergeValue = assignMergeValue$2;

var isArrayLike = isTypedArray$1.isArrayLike_1,
    isObjectLike = isObjectLike$1.isObjectLike_1;

/**
 * This method is like `_.isArrayLike` except that it also checks if `value`
 * is an object.
 *
 * @static
 * @memberOf _
 * @since 4.0.0
 * @category Lang
 * @param {*} value The value to check.
 * @returns {boolean} Returns `true` if `value` is an array-like object,
 *  else `false`.
 * @example
 *
 * _.isArrayLikeObject([1, 2, 3]);
 * // => true
 *
 * _.isArrayLikeObject(document.body.children);
 * // => true
 *
 * _.isArrayLikeObject('abc');
 * // => false
 *
 * _.isArrayLikeObject(_.noop);
 * // => false
 */
function isArrayLikeObject$1(value) {
  return isObjectLike(value) && isArrayLike(value);
}

var isArrayLikeObject_1 = isArrayLikeObject$1;

/**
 * Gets the value at `key`, unless `key` is "__proto__" or "constructor".
 *
 * @private
 * @param {Object} object The object to query.
 * @param {string} key The key of the property to get.
 * @returns {*} Returns the property value.
 */

function safeGet$2(object, key) {
  if (key === 'constructor' && typeof object[key] === 'function') {
    return;
  }

  if (key == '__proto__') {
    return;
  }

  return object[key];
}

var _safeGet = safeGet$2;

var copyObject = keysIn$2._copyObject,
    keysIn$1 = keysIn$2.keysIn_1;

/**
 * Converts `value` to a plain object flattening inherited enumerable string
 * keyed properties of `value` to own properties of the plain object.
 *
 * @static
 * @memberOf _
 * @since 3.0.0
 * @category Lang
 * @param {*} value The value to convert.
 * @returns {Object} Returns the converted plain object.
 * @example
 *
 * function Foo() {
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.assign({ 'a': 1 }, new Foo);
 * // => { 'a': 1, 'b': 2 }
 *
 * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
 * // => { 'a': 1, 'b': 2, 'c': 3 }
 */
function toPlainObject$1(value) {
  return copyObject(value, keysIn$1(value));
}

var toPlainObject_1 = toPlainObject$1;

var assignMergeValue$1 = _assignMergeValue,
    cloneBuffer = keysIn$2._cloneBufferExports,
    cloneTypedArray = keysIn$2._cloneTypedArray,
    copyArray = keysIn$2._copyArray,
    initCloneObject = keysIn$2._initCloneObject,
    isArguments = isTypedArray$1.isArguments_1,
    isArray = isTypedArray$1.isArray_1,
    isArrayLikeObject = isArrayLikeObject_1,
    isBuffer = isTypedArray$1.isBufferExports,
    isFunction = isTypedArray$1.isFunction_1,
    isObject$1 = isObjectLike$1.isObject_1,
    isPlainObject = keysIn$2.isPlainObject_1,
    isTypedArray = isTypedArray$1.isTypedArray_1,
    safeGet$1 = _safeGet,
    toPlainObject = toPlainObject_1;

/**
 * A specialized version of `baseMerge` for arrays and objects which performs
 * deep merges and tracks traversed objects enabling objects with circular
 * references to be merged.
 *
 * @private
 * @param {Object} object The destination object.
 * @param {Object} source The source object.
 * @param {string} key The key of the value to merge.
 * @param {number} srcIndex The index of `source`.
 * @param {Function} mergeFunc The function to merge values.
 * @param {Function} [customizer] The function to customize assigned values.
 * @param {Object} [stack] Tracks traversed source values and their merged
 *  counterparts.
 */
function baseMergeDeep$1(object, source, key, srcIndex, mergeFunc, customizer, stack) {
  var objValue = safeGet$1(object, key),
      srcValue = safeGet$1(source, key),
      stacked = stack.get(srcValue);

  if (stacked) {
    assignMergeValue$1(object, key, stacked);
    return;
  }
  var newValue = customizer
    ? customizer(objValue, srcValue, (key + ''), object, source, stack)
    : undefined;

  var isCommon = newValue === undefined;

  if (isCommon) {
    var isArr = isArray(srcValue),
        isBuff = !isArr && isBuffer(srcValue),
        isTyped = !isArr && !isBuff && isTypedArray(srcValue);

    newValue = srcValue;
    if (isArr || isBuff || isTyped) {
      if (isArray(objValue)) {
        newValue = objValue;
      }
      else if (isArrayLikeObject(objValue)) {
        newValue = copyArray(objValue);
      }
      else if (isBuff) {
        isCommon = false;
        newValue = cloneBuffer(srcValue, true);
      }
      else if (isTyped) {
        isCommon = false;
        newValue = cloneTypedArray(srcValue, true);
      }
      else {
        newValue = [];
      }
    }
    else if (isPlainObject(srcValue) || isArguments(srcValue)) {
      newValue = objValue;
      if (isArguments(objValue)) {
        newValue = toPlainObject(objValue);
      }
      else if (!isObject$1(objValue) || isFunction(objValue)) {
        newValue = initCloneObject(srcValue);
      }
    }
    else {
      isCommon = false;
    }
  }
  if (isCommon) {
    // Recursively merge objects and arrays (susceptible to call stack limits).
    stack.set(srcValue, newValue);
    mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
    stack['delete'](srcValue);
  }
  assignMergeValue$1(object, key, newValue);
}

var _baseMergeDeep = baseMergeDeep$1;

var Stack = identity._Stack,
    assignMergeValue = _assignMergeValue,
    baseFor = _baseFor._baseFor,
    baseMergeDeep = _baseMergeDeep,
    isObject = isObjectLike$1.isObject_1,
    keysIn = keysIn$2.keysIn_1,
    safeGet = _safeGet;

/**
 * The base implementation of `_.merge` without support for multiple sources.
 *
 * @private
 * @param {Object} object The destination object.
 * @param {Object} source The source object.
 * @param {number} srcIndex The index of `source`.
 * @param {Function} [customizer] The function to customize merged values.
 * @param {Object} [stack] Tracks traversed source values and their merged
 *  counterparts.
 */
function baseMerge$1(object, source, srcIndex, customizer, stack) {
  if (object === source) {
    return;
  }
  baseFor(source, function(srcValue, key) {
    stack || (stack = new Stack);
    if (isObject(srcValue)) {
      baseMergeDeep(object, source, key, srcIndex, baseMerge$1, customizer, stack);
    }
    else {
      var newValue = customizer
        ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack)
        : undefined;

      if (newValue === undefined) {
        newValue = srcValue;
      }
      assignMergeValue(object, key, newValue);
    }
  }, keysIn);
}

var _baseMerge = baseMerge$1;

var baseRest = _isIterateeCall._baseRest,
    isIterateeCall = _isIterateeCall._isIterateeCall;

/**
 * Creates a function like `_.assign`.
 *
 * @private
 * @param {Function} assigner The function to assign values.
 * @returns {Function} Returns the new assigner function.
 */
function createAssigner$1(assigner) {
  return baseRest(function(object, sources) {
    var index = -1,
        length = sources.length,
        customizer = length > 1 ? sources[length - 1] : undefined,
        guard = length > 2 ? sources[2] : undefined;

    customizer = (assigner.length > 3 && typeof customizer == 'function')
      ? (length--, customizer)
      : undefined;

    if (guard && isIterateeCall(sources[0], sources[1], guard)) {
      customizer = length < 3 ? undefined : customizer;
      length = 1;
    }
    object = Object(object);
    while (++index < length) {
      var source = sources[index];
      if (source) {
        assigner(object, source, index, customizer);
      }
    }
    return object;
  });
}

var _createAssigner = createAssigner$1;

var baseMerge = _baseMerge,
    createAssigner = _createAssigner;

/**
 * This method is like `_.assign` except that it recursively merges own and
 * inherited enumerable string keyed properties of source objects into the
 * destination object. Source properties that resolve to `undefined` are
 * skipped if a destination value exists. Array and plain object properties
 * are merged recursively. Other objects and value types are overridden by
 * assignment. Source objects are applied from left to right. Subsequent
 * sources overwrite property assignments of previous sources.
 *
 * **Note:** This method mutates `object`.
 *
 * @static
 * @memberOf _
 * @since 0.5.0
 * @category Object
 * @param {Object} object The destination object.
 * @param {...Object} [sources] The source objects.
 * @returns {Object} Returns `object`.
 * @example
 *
 * var object = {
 *   'a': [{ 'b': 2 }, { 'd': 4 }]
 * };
 *
 * var other = {
 *   'a': [{ 'c': 3 }, { 'e': 5 }]
 * };
 *
 * _.merge(object, other);
 * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
 */
var merge = createAssigner(function(object, source, srcIndex) {
  baseMerge(object, source, srcIndex);
});

var merge_1 = merge;

var merge$1 = /*@__PURE__*/_commonjsHelpers.getDefaultExportFromCjs(merge_1);

const THEME_CHANGE_EVENT = "atlantis.toggle-theme";

var styles = {"staticThemeProviderWrapper":"P6HrDSaI0Ac-","overrideTokensWrapper":"j-NMCOBL3-E-","spinning":"iq03qkKnXBA-"};

const atlantisThemeContextDefaultValues = {
    theme: "light",
    tokens: design.tokens,
};
const actualDarkTokens = merge$1({}, design.tokens, design.darkTokens);
const AtlantisThemeContext = React.createContext(atlantisThemeContextDefaultValues);
function AtlantisThemeContextProvider({ children, dangerouslyOverrideTheme, dangerouslyOverrideTokens, }) {
    if (dangerouslyOverrideTheme) {
        return (React.createElement(InternalStaticThemeProvider, { dangerouslyOverrideTokens: dangerouslyOverrideTokens, dangerouslyOverrideTheme: dangerouslyOverrideTheme }, children));
    }
    return (React.createElement(InternalDynamicThemeProvider, { dangerouslyOverrideTokens: dangerouslyOverrideTokens }, children));
}
function InternalDynamicThemeProvider({ children, dangerouslyOverrideTokens, }) {
    var _a;
    const initialTheme = (_a = globalThis.document.documentElement.dataset.theme) !== null && _a !== void 0 ? _a : "light";
    const [internalTheme, setInternalTheme] = React.useState(initialTheme);
    const { finalTokens, cssVariableOverrides } = useTokens(internalTheme, dangerouslyOverrideTokens);
    const handleThemeChangeEvent = React.useCallback((event) => {
        const newTheme = event.detail.theme;
        setInternalTheme(newTheme);
    }, []);
    React.useEffect(() => {
        if (!globalThis.window)
            return;
        globalThis.window.addEventListener(THEME_CHANGE_EVENT, handleThemeChangeEvent);
        return () => {
            globalThis.window.removeEventListener(THEME_CHANGE_EVENT, handleThemeChangeEvent);
        };
    }, [handleThemeChangeEvent]);
    return (React.createElement(AtlantisThemeContext.Provider, { value: {
            theme: internalTheme,
            tokens: finalTokens,
            overrideTokens: dangerouslyOverrideTokens,
        } }, cssVariableOverrides ? (React.createElement("div", { className: styles.overrideTokensWrapper, style: cssVariableOverrides }, children)) : (children)));
}
function InternalStaticThemeProvider({ dangerouslyOverrideTheme, children, dangerouslyOverrideTokens, }) {
    const { finalTokens, cssVariableOverrides } = useTokens(dangerouslyOverrideTheme, dangerouslyOverrideTokens);
    return (React.createElement(AtlantisThemeContext.Provider, { value: {
            theme: dangerouslyOverrideTheme,
            tokens: finalTokens,
            overrideTokens: dangerouslyOverrideTokens,
        } },
        React.createElement("div", { "data-theme": dangerouslyOverrideTheme, className: styles.staticThemeProviderWrapper, style: cssVariableOverrides }, children)));
}
function useAtlantisTheme() {
    return React.useContext(AtlantisThemeContext);
}
function getCssVariableOverrides(overrideTokens) {
    const cssVariables = Object.entries(overrideTokens).reduce((variables, [tokenName, tokenValue]) => {
        // @ts-expect-error - css variables are valid keys for style objects. @types/react may be outdated.
        variables[`--${tokenName}`] = tokenValue;
        return variables;
    }, {});
    return cssVariables;
}
function useTokens(theme, overrideTokens) {
    const currentTokens = theme === "dark" ? actualDarkTokens : design.tokens;
    const finalTokens = React.useMemo(() => {
        if (overrideTokens) {
            return merge$1({}, currentTokens, overrideTokens);
        }
        return currentTokens;
    }, [currentTokens, overrideTokens]);
    const cssVariableOverrides = overrideTokens
        ? getCssVariableOverrides(overrideTokens)
        : undefined;
    return {
        finalTokens,
        cssVariableOverrides,
    };
}

exports.AtlantisThemeContextProvider = AtlantisThemeContextProvider;
exports.THEME_CHANGE_EVENT = THEME_CHANGE_EVENT;
exports.atlantisThemeContextDefaultValues = atlantisThemeContextDefaultValues;
exports.useAtlantisTheme = useAtlantisTheme;
