UNPKG

@enact/ui

Version:

A collection of simplified unstyled cross-platform UI components for Enact

217 lines (214 loc) 9.12 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = exports.Skinnable = void 0; Object.defineProperty(exports, "useSkins", { enumerable: true, get: function get() { return _useSkins["default"]; } }); var _classnames = _interopRequireDefault(require("classnames")); var _hoc = _interopRequireDefault(require("@enact/core/hoc")); var _propTypes = _interopRequireDefault(require("prop-types")); var _useSkins = _interopRequireDefault(require("./useSkins")); var _util = require("./util"); var _jsxRuntime = require("react/jsx-runtime"); var _excluded = ["className", "skin", "skinVariants"]; /** * A higher-order component for customizing the visual appearance throughout an application. * * This is the base-level implementation of this component. It will typically never be accessed * directly, and only be instantiated with a configuration once inside a visual library. * Interface libraries will supply a set of supported skins which will * be accessible to their components. * * @module ui/Skinnable * @exports Skinnable * @public */ /** * Default config for `Skinnable`. * * @memberof ui/Skinnable.Skinnable * @hocconfig * @public */ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } 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(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : String(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(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 defaultConfig = { /** * The prop in which to pass the skinVariants value to the wrapped component. The recommended * value is "skinVariants". * * If left unset, the skinVariant will not be passed to the wrapped component. * * @type {String} * @memberof ui/Skinnable.Skinnable.defaultConfig */ variantsProp: null, /** * The prop in which to pass the effective skin to the wrapped component. * * If left unset, the current skin will not be passed to the wrapped component. * * @type {String} * @memberof ui/Skinnable.Skinnable.defaultConfig */ prop: null, /** * A hash mapping the available skin names to their CSS class name. * * The keys are accepted as the only valid values for the `skin` prop on the wrapped component. * * @type {Object} * @memberof ui/Skinnable.Skinnable.defaultConfig */ skins: null, /** * Assign a default skin from the `skins` list. * * This will be used if the instantiator of the wrapped component provides no value to the * `skin` prop. * * @type {String} * @memberof ui/Skinnable.Skinnable.defaultConfig */ defaultSkin: null, /** * Initial collection of applied variants * * This will be used if the instantiator of the wrapped component provides no value to the * `skinVariants` prop. * * @type {String|String[]} * @memberof ui/Skinnable.Skinnable.defaultConfig */ defaultVariants: null, /** * A complete list of all supported variants. * * These will translate to CSS class names so should not conflict with any skin names. * CamelCase is recommended for the values. * * @type {String[]} * @memberof ui/Skinnable.Skinnable.defaultConfig */ allowedVariants: null }; /** * A higher-order component that assigns skinning classes for the purposes of styling children components. * * Use the config options to specify the skins your theme has. Set this up in your theme's decorator * component to establish your supported skins. * * Note: This HoC passes `className` to the wrapped component. It must be passed to the main DOM * node. Additionally, it can be configured to pass the skin and skin variant as props. * * Example: * ``` * const MyApp = ({skinName, ...rest) => (<div {...props}>{skinName}</div>); * ... * App = Skinnable({ * prop: 'skinName', * skins: { * dark: 'moonstone', * light: 'moonstone-light' * }, * defaultTheme: 'dark' * defaultVariants: ['highContrast'], * allowedVariants: ['highContrast', 'largeText', 'grayscale'] * }, MyApp); * ``` * * @class Skinnable * @memberof ui/Skinnable * @hoc * @public */ var Skinnable = exports.Skinnable = (0, _hoc["default"])(defaultConfig, function (config, Wrapped) { var prop = config.prop, skins = config.skins, defaultSkin = config.defaultSkin, variants = config.allowedVariants, variantsProp = config.variantsProp; var defaultVariants = (0, _util.objectify)(config.defaultVariants); // eslint-disable-next-line no-shadow function Skinnable(_ref) { var className = _ref.className, skin = _ref.skin, skinVariants = _ref.skinVariants, rest = _objectWithoutProperties(_ref, _excluded); var hook = (0, _useSkins["default"])({ defaultSkin: defaultSkin, defaultVariants: defaultVariants, skin: skin, skins: skins, skinVariants: skinVariants, variants: variants }); var allClassNames = (0, _classnames["default"])(hook.className, className); if (allClassNames) { rest.className = allClassNames; } if (prop) { rest[prop] = hook.skin; } if (variantsProp) { rest[variantsProp] = hook.variants; } return hook.provideSkins( /*#__PURE__*/(0, _jsxRuntime.jsx)(Wrapped, _objectSpread({}, rest))); } Skinnable.propTypes = /** @lends ui/Skinnable.Skinnable.prototype */{ /** * The name of the skin a component should use to render itself. Available skins are * defined in the "defaultConfig" for this HOC. * * @type {String} * @public */ skin: _propTypes["default"].string, /** * The variant(s) on a skin that a component should use when rendering. These will * typically alter the appearance of a skin's existing definition in a way that does not * override that skin's general styling. * * Multiple data types are supported by this prop, which afford different conveniences * and abilities. String and Array are effectively the same, supporting just additions * to the variants being applied to a component, and are much more convenient. Objects * may also be used, and have the ability to disable variants being passed by their * ancestors. Objects take the format of a basic hash, with variants as key names and * true/false Booleans as values, depicting their state. If a variant is excluded from * any version of data type used to set this prop, that variant will ignored, falling * back to the defaultVariant or parent variant, in that order. * * skinVariants examples: * ``` * // String * skinVariants="highContrast" * * // Array * skinVariants={['highContrast']} * * // Object * skinVariants={{ * highContrast: true, * grayscale: false * }} * ``` * * @type {String|String[]|Object} * @public */ skinVariants: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].array, _propTypes["default"].object]) }; return Skinnable; }); var _default = exports["default"] = Skinnable;