UNPKG

layeshifter-fela

Version:

State-Driven Styling in JavaScript

291 lines (213 loc) 11 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; exports.default = createRenderer; var _cssifyDeclaration = require('css-in-js-utils/lib/cssifyDeclaration'); var _cssifyDeclaration2 = _interopRequireDefault(_cssifyDeclaration); var _arrayEach = require('fast-loops/lib/arrayEach'); var _arrayEach2 = _interopRequireDefault(_arrayEach); var _isobject = require('isobject'); var _isobject2 = _interopRequireDefault(_isobject); var _felaUtils = require('fela-utils'); var _cssifyFontFace = require('./cssifyFontFace'); var _cssifyFontFace2 = _interopRequireDefault(_cssifyFontFace); var _cssifyKeyframe = require('./cssifyKeyframe'); var _cssifyKeyframe2 = _interopRequireDefault(_cssifyKeyframe); var _cssifyStaticStyle = require('./cssifyStaticStyle'); var _cssifyStaticStyle2 = _interopRequireDefault(_cssifyStaticStyle); var _generateAnimationName = require('./generateAnimationName'); var _generateAnimationName2 = _interopRequireDefault(_generateAnimationName); var _generateClassName = require('./generateClassName'); var _generateClassName2 = _interopRequireDefault(_generateClassName); var _generateFontSource = require('./generateFontSource'); var _generateFontSource2 = _interopRequireDefault(_generateFontSource); var _generateStaticReference = require('./generateStaticReference'); var _generateStaticReference2 = _interopRequireDefault(_generateStaticReference); var _getFontLocals = require('./getFontLocals'); var _getFontLocals2 = _interopRequireDefault(_getFontLocals); var _isSafeClassName = require('./isSafeClassName'); var _isSafeClassName2 = _interopRequireDefault(_isSafeClassName); var _toCSSString = require('./toCSSString'); var _toCSSString2 = _interopRequireDefault(_toCSSString); var _validateSelectorPrefix = require('./validateSelectorPrefix'); var _validateSelectorPrefix2 = _interopRequireDefault(_validateSelectorPrefix); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } function createRenderer() { var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var renderer = { listeners: [], keyframePrefixes: config.keyframePrefixes || ['-webkit-', '-moz-'], plugins: config.plugins || [], mediaQueryOrder: config.mediaQueryOrder || [], supportQueryOrder: config.supportQueryOrder || [], ruleOrder: [/^:link/, /^:visited/, /^:hover/, /^:focus-within/, /^:focus/, /^:active/], rendererId: (0, _validateSelectorPrefix2.default)(config.rendererId), selectorPrefix: (0, _validateSelectorPrefix2.default)(config.selectorPrefix), filterClassName: config.filterClassName || _isSafeClassName2.default, devMode: config.devMode || false, uniqueRuleIdentifier: 0, uniqueKeyframeIdentifier: 0, nodes: {}, scoreIndex: {}, // use a flat cache object with pure string references // to achieve maximal lookup performance and memoization speed cache: {}, getNextRuleIdentifier: function getNextRuleIdentifier() { return ++renderer.uniqueRuleIdentifier; }, renderRule: function renderRule(rule) { var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return renderer._renderStyle(rule(props, renderer), props); }, renderKeyframe: function renderKeyframe(keyframe) { var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var resolvedKeyframe = keyframe(props, renderer); var keyframeReference = JSON.stringify(resolvedKeyframe); if (!renderer.cache.hasOwnProperty(keyframeReference)) { // use another unique identifier to ensure minimal css markup var animationName = (0, _generateAnimationName2.default)(++renderer.uniqueKeyframeIdentifier, renderer.rendererId); var processedKeyframe = (0, _felaUtils.processStyleWithPlugins)(renderer, resolvedKeyframe, _felaUtils.KEYFRAME_TYPE, props); var cssKeyframe = (0, _cssifyKeyframe2.default)(processedKeyframe, animationName, renderer.keyframePrefixes); var change = { type: _felaUtils.KEYFRAME_TYPE, keyframe: cssKeyframe, name: animationName }; renderer.cache[keyframeReference] = change; renderer._emitChange(change); } return renderer.cache[keyframeReference].name; }, renderFont: function renderFont(family, files) { var properties = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var localAlias = properties.localAlias, otherProperties = _objectWithoutProperties(properties, ['localAlias']); var fontReference = family + JSON.stringify(properties); var fontLocals = (0, _getFontLocals2.default)(localAlias); if (!renderer.cache.hasOwnProperty(fontReference)) { var fontFamily = (0, _toCSSString2.default)(family); var fontFace = _extends({}, otherProperties, { src: (0, _generateFontSource2.default)(files, fontLocals), fontFamily: fontFamily }); var cssFontFace = (0, _cssifyFontFace2.default)(fontFace); var change = { type: _felaUtils.FONT_TYPE, fontFace: cssFontFace, fontFamily: fontFamily }; renderer.cache[fontReference] = change; renderer._emitChange(change); } return renderer.cache[fontReference].fontFamily; }, renderStatic: function renderStatic(staticStyle, selector) { var staticReference = (0, _generateStaticReference2.default)(staticStyle, selector); if (!renderer.cache.hasOwnProperty(staticReference)) { var cssDeclarations = (0, _cssifyStaticStyle2.default)(staticStyle, renderer); var change = { type: _felaUtils.STATIC_TYPE, css: cssDeclarations, selector: selector }; renderer.cache[staticReference] = change; renderer._emitChange(change); } }, subscribe: function subscribe(callback) { renderer.listeners.push(callback); return { unsubscribe: function unsubscribe() { return renderer.listeners.splice(renderer.listeners.indexOf(callback), 1); } }; }, clear: function clear() { renderer.uniqueRuleIdentifier = 0; renderer.uniqueKeyframeIdentifier = 0; renderer.cache = {}; renderer._emitChange({ type: _felaUtils.CLEAR_TYPE }); }, _renderStyle: function _renderStyle() { var style = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var processedStyle = (0, _felaUtils.processStyleWithPlugins)(renderer, style, _felaUtils.RULE_TYPE, props); return renderer._renderStyleToClassNames(processedStyle).slice(1); }, _renderStyleToClassNames: function _renderStyleToClassNames(_ref) { var pseudo = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; var media = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; var support = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ''; var _className = _ref._className, style = _objectWithoutProperties(_ref, ['_className']); var classNames = _className ? ' ' + _className : ''; for (var property in style) { var value = style[property]; if ((0, _isobject2.default)(value)) { if ((0, _felaUtils.isNestedSelector)(property)) { classNames += renderer._renderStyleToClassNames(value, pseudo + (0, _felaUtils.normalizeNestedProperty)(property), media, support); } else if ((0, _felaUtils.isMediaQuery)(property)) { var combinedMediaQuery = (0, _felaUtils.generateCombinedMediaQuery)(media, property.slice(6).trim()); classNames += renderer._renderStyleToClassNames(value, pseudo, combinedMediaQuery, support); } else if ((0, _felaUtils.isSupport)(property)) { var combinedSupport = (0, _felaUtils.generateCombinedMediaQuery)(support, property.slice(9).trim()); classNames += renderer._renderStyleToClassNames(value, pseudo, media, combinedSupport); } else { console.warn('The object key "' + property + '" is not a valid nested key in Fela. \nMaybe you forgot to add a plugin to resolve it? \nCheck http://fela.js.org/docs/basics/Rules.html#styleobject for more information.'); } } else { var declarationReference = support + media + pseudo + property + value; if (!renderer.cache.hasOwnProperty(declarationReference)) { // we remove undefined values to enable // usage of optional props without side-effects if ((0, _felaUtils.isUndefinedValue)(value)) { renderer.cache[declarationReference] = { className: '' /* eslint-disable no-continue */ };continue; /* eslint-enable */ } var className = renderer.selectorPrefix + (0, _generateClassName2.default)(renderer.getNextRuleIdentifier, renderer.filterClassName); var declaration = (0, _cssifyDeclaration2.default)(property, value); var selector = (0, _felaUtils.generateCSSSelector)(className, pseudo); var change = { type: _felaUtils.RULE_TYPE, className: className, selector: selector, declaration: declaration, pseudo: pseudo, media: media, support: support }; renderer.cache[declarationReference] = change; renderer._emitChange(change); } var cachedClassName = renderer.cache[declarationReference].className; // only append if we got a class cached if (cachedClassName) { classNames += ' ' + cachedClassName; } } } return classNames; }, _emitChange: function _emitChange(change) { (0, _arrayEach2.default)(renderer.listeners, function (listener) { return listener(change); }); } }; // initial setup renderer.keyframePrefixes.push(''); if (config.enhancers) { (0, _arrayEach2.default)(config.enhancers, function (enhancer) { renderer = enhancer(renderer); }); } return renderer; }