"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = exports.ThemeDecorator = exports.ThemeContext = void 0;
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"));
var _jsxRuntime = require("react/jsx-runtime");
var _excluded = ["cssRules"],
  _excluded2 = ["accent", "className", "highlight"];
/**
 * Applies Agate specific styling and behaviors.
 *
 * @module agate/ThemeDecorator
 * @exports ThemeDecorator
 * @exports ThemeContext
 */
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
function _possibleConstructorReturn(t, e) { if (e && ("object" == typeof e || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); }
function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; }
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }
function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); }
function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var s = Object.getOwnPropertySymbols(e); for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
var ThemeContext = exports.ThemeContext = /*#__PURE__*/(0, _react.createContext)(null);
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, _excluded);
    delete rest.className;
    return cssRules ? /*#__PURE__*/(0, _jsxRuntime.jsx)("style", _objectSpread(_objectSpread({
      type: "text/css"
    }, rest), {}, {
      children: cssRules
    })) : null;
  }
});

/**
 * {@link agate/ThemeDecorator.ThemeDecorator|ThemeDecorator} is a Higher-order Component that applies
 * Agate theming to an application. It also applies
 * {@link ui/FloatingLayer.FloatingLayerDecorator|floating layer},
 * {@link ui/resolution.ResolutionDecorator|resolution independence},
 * {@link ui/Skinnable|skin support}, {@link spotlight.SpotlightRootDecorator|spotlight}, and
 * {@link i18n/I18nDecorator.I18nDecorator|internationalization support}. It is meant to be applied to
 * the root element of an app.
 *
 * {@link ui/Skinnable|Skins} 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 = exports.ThemeDecorator = (0, _hoc["default"])(defaultConfig, function (config, Wrapped) {
  var _Class;
  // 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"])(_defineProperty({
    'enact-fit': !disableFullscreen
  }, _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,
    rootId: rootId
  }, 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 = (_Class = /*#__PURE__*/function (_Component) {
    function Decorator() {
      _classCallCheck(this, Decorator);
      return _callSuper(this, Decorator, arguments);
    }
    _inherits(Decorator, _Component);
    return _createClass(Decorator, [{
      key: "render",
      value: function render() {
        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, _excluded2);
        var customizableSkinClassName = 'agate-customized-skin';
        var allClassNames = (0, _classnames3["default"])(className, 'enact-unselectable', _ThemeDecoratorModule["default"].root, _defineProperty(_defineProperty(_defineProperty({}, customizableSkinClassName, customSkin), bgClassName, !_float), 'enact-fit', !disableFullscreen));
        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
          }))]
        });
      }
    }]);
  }(_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
  }, _Class);
  return Decorator;
});
var _default = exports["default"] = ThemeDecorator;