"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.ThemeContext = exports.ThemeDecorator = exports["default"] = void 0;

var _jsxRuntime = require("react/jsx-runtime");

var _dispatcher = require("@enact/core/dispatcher");

var _hoc = _interopRequireDefault(require("@enact/core/hoc"));

var _keymap = require("@enact/core/keymap");

var _kind = _interopRequireDefault(require("@enact/core/kind"));

var _I18nDecorator = _interopRequireDefault(require("@enact/i18n/I18nDecorator"));

var _SpotlightRootDecorator = _interopRequireDefault(require("@enact/spotlight/SpotlightRootDecorator"));

var _resolution = require("@enact/ui/resolution");

var _FloatingLayer = require("@enact/ui/FloatingLayer");

var _classnames3 = _interopRequireDefault(require("classnames"));

var _colorConvert = _interopRequireDefault(require("color-convert"));

var _propTypes = _interopRequireDefault(require("prop-types"));

var _react = require("react");

var _Skinnable = _interopRequireDefault(require("../Skinnable"));

var _screenTypes = _interopRequireDefault(require("./screenTypes.json"));

var _ThemeDecoratorModule = _interopRequireDefault(require("./ThemeDecorator.module.css"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }

function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }

var ThemeContext = /*#__PURE__*/(0, _react.createContext)(null);
exports.ThemeContext = ThemeContext;
var defaultColors = {
  carbon: {
    accent: '#8fd43a',
    highlight: '#6abe0b'
  },
  cobalt: {
    accent: '#8c81ff',
    highlight: '#ffffff'
  },
  copper: {
    accent: '#a47d66',
    highlight: '#ffffff'
  },
  electro: {
    accent: '#0359f0',
    highlight: '#ff8100'
  },
  gallium: {
    accent: '#8b7efe',
    highlight: '#e16253'
  },
  silicon: {
    accent: '#f1304f',
    highlight: '#9e00d8'
  },
  titanium: {
    accent: '#a6a6a6',
    highlight: '#2a48ca'
  }
};
/**
 * Default config for {@link agate/ThemeDecorator.ThemeDecorator}.
 *
 * @memberof agate/ThemeDecorator.ThemeDecorator
 * @hocconfig
 */

var defaultConfig =
/** @lends agate/ThemeDecorator.ThemeDecorator.defaultConfig */
{
  /**
   * Enables customization of a skin's highlight and accent color.
   *
   * @type {Boolean}
   * @default true
   * @memberof agate/ThemeDecorator.ThemeDecorator.defaultConfig
   * @public
   */
  customSkin: true,

  /**
   * Disables use of full screen.
   *
   * @type {Boolean}
   * @default false
   * @memberof agate/ThemeDecorator.ThemeDecorator.defaultConfig
   * @public
   */
  disableFullscreen: false,

  /**
   * Enables a floating layer for popup components.
   *
   * If `false`, app will be responsible for applying the decorator.
   *
   * @type {Boolean}
   * @default true
   * @see {@link ui/FloatingLayer.FloatingLayerDecorator}
   * @memberof agate/ThemeDecorator.ThemeDecorator.defaultConfig
   * @public
   */
  "float": true,

  /**
   * Applies I18nDecorator.
   *
   * If `false`, app will be responsible for applying the decorator.
   *
   * @type {Boolean}
   * @default true
   * @see {@link i18n/I18nDecorator}
   * @memberof agate/ThemeDecorator.ThemeDecorator.defaultConfig
   * @public
   */
  i18n: true,

  /**
   * Disables setting spotlight focus on first render.
   *
   * @type {Boolean}
   * @default false
   * @memberof agate/ThemeDecorator.ThemeDecorator.defaultConfig
   * @public
   */
  noAutoFocus: false,

  /**
   * Enables overlay mode (no background color will be applied).
   *
   * @type {Boolean}
   * @default false
   * @memberof agate/ThemeDecorator.ThemeDecorator.defaultConfig
   * @public
   */
  overlay: false,

  /**
   * Override the resolution independence settings.
   *
   * @type {Object}
   * @see {@link ui/resolution}
   * @memberof agate/ThemeDecorator.ThemeDecorator.defaultConfig
   * @public
   */
  ri: {
    screenTypes: _screenTypes["default"]
  },

  /**
   * Specifies the id of the React DOM tree root node
   *
   * @type {String}
   * @default 'root'
   * @public
   */
  rootId: 'root',

  /**
   * Applies skinning support.
   *
   * @type {Boolean}
   * @default true
   * @see {@link agate/Skinnable}
   * @memberof agate/ThemeDecorator.ThemeDecorator.defaultConfig
   * @public
   */
  skin: true,

  /**
   * Applies spotlight decorator.
   *
   * If `false`, app will be responsible for applying the decorator.
   *
   * @type {Boolean}
   * @default true
   * @see {@link spotlight/SpotlightRootDecorator}
   * @memberof agate/ThemeDecorator.ThemeDecorator.defaultConfig
   * @public
   */
  spotlight: true
}; // TODO: If this will be public it should be documented or perhaps the props
// added to `ThemeDecorator`

var CustomizableSkinStyle = (0, _kind["default"])({
  name: 'CustomizableSkinStyle',
  propTypes: {
    className: _propTypes["default"].string.isRequired,

    /**
     * A custom accent color, as a hex string.
     *
     * @memberof agate/ThemeDecorator.CustomizableSkinStyle.prototype
     * @type {String}
     * @default '#8b7efe'
     * @private
     */
    accent: _propTypes["default"].string,

    /**
     * A custom highlight color, as a hex string.
     *
     * @memberof agate/ThemeDecorator.CustomizableSkinStyle.prototype
     * @type {String}
     * @default '#c6c0fe'
     * @private
     */
    highlight: _propTypes["default"].string
  },
  // TODO: Consider allowing `null` and dropping this override completely
  defaultProps: {
    accent: '#8b7efe',
    highlight: '#c6c0fe'
  },
  computed: {
    cssRules: function cssRules(_ref) {
      var className = _ref.className,
          accent = _ref.accent,
          highlight = _ref.highlight;

      var accentObj = _colorConvert["default"].hex.hsl(accent);

      var highlightObj = _colorConvert["default"].hex.hsl(highlight);

      var style = {
        '--agate-accent-color': accent,
        '--agate-accent-h': accentObj[0],
        '--agate-accent-s': accentObj[1] + '%',
        '--agate-accent-l': accentObj[2] + '%',
        '--agate-highlight-color': highlight,
        '--agate-highlight-h': highlightObj[0],
        '--agate-highlight-s': highlightObj[1] + '%',
        '--agate-highlight-l': highlightObj[2] + '%'
      };
      var styleRules = '';

      for (var rule in style) {
        styleRules += "\t".concat(rule, ": ").concat(style[rule], ";\n");
      }

      return ".".concat(className, " {\n").concat(styleRules, "}\n");
    }
  },
  render: function render(_ref2) {
    var cssRules = _ref2.cssRules,
        rest = _objectWithoutProperties(_ref2, ["cssRules"]);

    delete rest.className;
    return cssRules ? /*#__PURE__*/(0, _jsxRuntime.jsx)("style", _objectSpread(_objectSpread({
      type: "text/css"
    }, rest), {}, {
      children: cssRules
    })) : null;
  }
});
/**
 * {@link agate/ThemeDecorator.ThemeDecorator} is a Higher-order Component that applies
 * Agate theming to an application. It also applies
 * [floating layer]{@link ui/FloatingLayer.FloatingLayerDecorator},
 * [resolution independence]{@link ui/resolution.ResolutionDecorator},
 * [skin support]{@link ui/Skinnable}, [spotlight]{@link spotlight.SpotlightRootDecorator}, and
 * [internationalization support]{@link i18n/I18nDecorator.I18nDecorator}. It is meant to be applied to
 * the root element of an app.
 *
 * [Skins]{@link ui/Skinnable} provide a way to change the coloration of your app. The currently
 * supported skins for Agate are "agate" (the default, dark skin) and "agate-light".
 * Use the `skin` property to assign a skin. Ex: `<DecoratedApp skin="light" />`
 *
 * @class ThemeDecorator
 * @hoc
 * @memberof agate/ThemeDecorator
 * @mixes ui/FloatingLayer.FloatingLayerDecorator
 * @mixes ui/resolution.ResolutionDecorator
 * @mixes spotlight/SpotlightRootDecorator.SpotlightRootDecorator
 * @mixes agate/Skinnable.Skinnable
 * @public
 */

var ThemeDecorator = (0, _hoc["default"])(defaultConfig, function (config, Wrapped) {
  var _class, _temp;

  // TODO: Document props passable to hoc ()
  var customSkin = config.customSkin,
      _float = config["float"],
      i18n = config.i18n,
      noAutoFocus = config.noAutoFocus,
      overlay = config.overlay,
      ri = config.ri,
      skin = config.skin,
      spotlight = config.spotlight,
      disableFullscreen = config.disableFullscreen,
      rootId = config.rootId;
  var defaultSkin = 'gallium';
  var bgClassName = (0, _classnames3["default"])('enact-fit', _defineProperty({}, _ThemeDecoratorModule["default"].bg, !overlay));
  var App = Wrapped;
  if (_float) App = (0, _FloatingLayer.FloatingLayerDecorator)({
    wrappedClassName: bgClassName
  }, App);
  if (ri) App = (0, _resolution.ResolutionDecorator)(ri, App);
  if (i18n) App = (0, _I18nDecorator["default"])({
    sync: true
  }, App);
  if (spotlight) App = (0, _SpotlightRootDecorator["default"])({
    noAutoFocus: noAutoFocus
  }, App);
  if (skin) App = (0, _Skinnable["default"])({
    defaultSkin: defaultSkin
  }, App); // add webOS-specific key maps

  (0, _keymap.addAll)({
    cancel: 461,
    pointerHide: 1537,
    pointerShow: 1536
  }); // set the DOM node ID of the React DOM tree root

  (0, _dispatcher.setDefaultTargetById)(rootId);
  var Decorator = (_temp = _class = /*#__PURE__*/function (_Component) {
    _inherits(Decorator, _Component);

    var _super = _createSuper(Decorator);

    function Decorator() {
      _classCallCheck(this, Decorator);

      return _super.apply(this, arguments);
    }

    _createClass(Decorator, [{
      key: "render",
      value: function render() {
        var _classnames2;

        var currentSkin = this.props.skin || defaultSkin;

        var _this$props = this.props,
            _this$props$accent = _this$props.accent,
            accent = _this$props$accent === void 0 ? defaultColors[currentSkin].accent : _this$props$accent,
            className = _this$props.className,
            _this$props$highlight = _this$props.highlight,
            highlight = _this$props$highlight === void 0 ? defaultColors[currentSkin].highlight : _this$props$highlight,
            rest = _objectWithoutProperties(_this$props, ["accent", "className", "highlight"]);

        var customizableSkinClassName = 'agate-customized-skin';
        var allClassNames = (0, _classnames3["default"])(className, 'enact-unselectable', _ThemeDecoratorModule["default"].root, (_classnames2 = {}, _defineProperty(_classnames2, customizableSkinClassName, customSkin), _defineProperty(_classnames2, bgClassName, !_float), _defineProperty(_classnames2, 'enact-fit', !disableFullscreen), _classnames2));
        return /*#__PURE__*/(0, _jsxRuntime.jsxs)(ThemeContext.Provider, {
          value: {
            accent: accent,
            highlight: highlight
          },
          children: [customSkin ? /*#__PURE__*/(0, _jsxRuntime.jsx)(CustomizableSkinStyle, {
            className: customizableSkinClassName,
            accent: accent,
            highlight: highlight
          }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(App, _objectSpread(_objectSpread({}, rest), {}, {
            accent: accent,
            highlight: highlight,
            className: allClassNames
          }))]
        });
      }
    }]);

    return Decorator;
  }(_react.Component), _class.displayName = 'ThemeDecorator', _class.propTypes =
  /** @lends agate/ThemeDecorator.ThemeDecorator.prototype */
  {
    /**
     * A custom accent color, as a hex string.
     *
     * @memberof agate/ThemeDecorator.ThemeDecorator.prototype
     * @type {String}
     * @public
     */
    accent: _propTypes["default"].string,

    /**
     * A custom highlight color, as a hex string.
     *
     * @memberof agate/ThemeDecorator.ThemeDecorator.prototype
     * @type {String}
     * @public
     */
    highlight: _propTypes["default"].string,

    /**
     * The name of the skin a component should use to render itself.
     *
     * @type {String}
     * @public
     */
    skin: _propTypes["default"].string
  }, _temp);
  return Decorator;
});
exports.ThemeDecorator = ThemeDecorator;
var _default = ThemeDecorator;
exports["default"] = _default;