UNPKG

glamor

Version:
1,012 lines (856 loc) 27.2 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.compose = exports.merge = exports.$ = exports.style = exports.presets = exports.keyframes = exports.fontFace = exports.insertGlobal = exports.insertRule = exports.plugins = exports.styleSheet = undefined; exports.speedy = speedy; exports.simulations = simulations; exports.simulate = simulate; exports.cssLabels = cssLabels; exports.isLikeRule = isLikeRule; exports.idFor = idFor; exports.css = css; exports.rehydrate = rehydrate; exports.flush = flush; exports.select = select; exports.parent = parent; exports.media = media; exports.pseudo = pseudo; exports.active = active; exports.any = any; exports.checked = checked; exports.disabled = disabled; exports.empty = empty; exports.enabled = enabled; exports._default = _default; exports.first = first; exports.firstChild = firstChild; exports.firstOfType = firstOfType; exports.fullscreen = fullscreen; exports.focus = focus; exports.hover = hover; exports.indeterminate = indeterminate; exports.inRange = inRange; exports.invalid = invalid; exports.lastChild = lastChild; exports.lastOfType = lastOfType; exports.left = left; exports.link = link; exports.onlyChild = onlyChild; exports.onlyOfType = onlyOfType; exports.optional = optional; exports.outOfRange = outOfRange; exports.readOnly = readOnly; exports.readWrite = readWrite; exports.required = required; exports.right = right; exports.root = root; exports.scope = scope; exports.target = target; exports.valid = valid; exports.visited = visited; exports.dir = dir; exports.lang = lang; exports.not = not; exports.nthChild = nthChild; exports.nthLastChild = nthLastChild; exports.nthLastOfType = nthLastOfType; exports.nthOfType = nthOfType; exports.after = after; exports.before = before; exports.firstLetter = firstLetter; exports.firstLine = firstLine; exports.selection = selection; exports.backdrop = backdrop; exports.placeholder = placeholder; exports.cssFor = cssFor; exports.attribsFor = attribsFor; var _objectAssign = require('object-assign'); var _objectAssign2 = _interopRequireDefault(_objectAssign); var _sheet = require('./sheet.js'); var _CSSPropertyOperations = require('./CSSPropertyOperations'); var _clean = require('./clean.js'); var _clean2 = _interopRequireDefault(_clean); var _plugins = require('./plugins'); var _hash = require('./hash'); var _hash2 = _interopRequireDefault(_hash); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } 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; } /* stylesheet */ var styleSheet = exports.styleSheet = new _sheet.StyleSheet(); // an isomorphic StyleSheet shim. hides all the nitty gritty. // /**************** LIFTOFF IN 3... 2... 1... ****************/ styleSheet.inject(); //eslint-disable-line indent // /**************** TO THE MOOOOOOON ****************/ // convenience function to toggle speedy function speedy(bool) { return styleSheet.speedy(bool); } // plugins // we include these by default var plugins = exports.plugins = styleSheet.plugins = new _plugins.PluginSet([_plugins.prefixes, _plugins.contentWrap, _plugins.fallbacks]); plugins.media = new _plugins.PluginSet(); // neat! media, font-face, keyframes plugins.fontFace = new _plugins.PluginSet(); plugins.keyframes = new _plugins.PluginSet([_plugins.prefixes, _plugins.fallbacks]); // define some constants var isDev = process.env.NODE_ENV === 'development' || !process.env.NODE_ENV; var isTest = process.env.NODE_ENV === 'test'; var isBrowser = typeof window !== 'undefined'; /**** simulations ****/ // a flag to enable simulation meta tags on dom nodes // defaults to true in dev mode. recommend *not* to // toggle often. var canSimulate = isDev; // we use these flags for issuing warnings when simulate is called // in prod / in incorrect order var warned1 = false, warned2 = false; // toggles simulation activity. shouldn't be needed in most cases function simulations() { var bool = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; canSimulate = !!bool; } // use this on dom nodes to 'simulate' pseudoclasses // <div {...hover({ color: 'red' })} {...simulate('hover', 'visited')}>...</div> // you can even send in some weird ones, as long as it's in simple format // and matches an existing rule on the element // eg simulate('nthChild2', ':hover:active') etc function simulate() { for (var _len = arguments.length, pseudos = Array(_len), _key = 0; _key < _len; _key++) { pseudos[_key] = arguments[_key]; } pseudos = (0, _clean2.default)(pseudos); if (!pseudos) return {}; if (!canSimulate) { if (!warned1) { console.warn('can\'t simulate without once calling simulations(true)'); //eslint-disable-line no-console warned1 = true; } if (!isDev && !isTest && !warned2) { console.warn('don\'t use simulation outside dev'); //eslint-disable-line no-console warned2 = true; } return {}; } return pseudos.reduce(function (o, p) { return o['data-simulate-' + simple(p)] = '', o; }, {}); } /**** labels ****/ // toggle for debug labels. // *shouldn't* have to mess with this manually var hasLabels = isDev; function cssLabels(bool) { hasLabels = !!bool; } // takes a string, converts to lowercase, strips out nonalphanumeric. function simple(str) { var char = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; return str.toLowerCase().replace(/[^a-z0-9]/g, char); } // hashes a string to something 'unique' // we use this to generate ids for styles function hashify(obj) { var str = JSON.stringify(obj); var toRet = (0, _hash2.default)(str).toString(36); if (obj.label && obj.label.length > 0 && isDev) { return simple(obj.label.join('.'), '-') + '-' + toRet; } return toRet; } // of shape { 'data-css-<id>': '' } function isLikeRule(rule) { var keys = Object.keys(rule).filter(function (x) { return x !== 'toString'; }); if (keys.length !== 1) { return false; } return !!/data\-css\-([a-zA-Z0-9\-_]+)/.exec(keys[0]); } // extracts id from a { 'data-css-<id>': ''} like object function idFor(rule) { var keys = Object.keys(rule).filter(function (x) { return x !== 'toString'; }); if (keys.length !== 1) throw new Error('not a rule'); var regex = /data\-css\-([a-zA-Z0-9\-_]+)/; var match = regex.exec(keys[0]); if (!match) throw new Error('not a rule'); return match[1]; } // from https://github.com/j2css/j2c/blob/5d381c2d721d04b54fabe6a165d587247c3087cb/src/helpers.js#L28-L61 // "Tokenizes" the selectors into parts relevant for the next function. // Strings and comments are matched, but ignored afterwards. // This is not a full tokenizers. It only recognizes comas, parentheses, // strings and comments. // regexp generated by scripts/regexps.js then trimmed by hand var selectorTokenizer = /[(),]|"(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*'|\/\*[\s\S]*?\*\//g; /** * This will split a coma-separated selector list into individual selectors, * ignoring comas in strings, comments and in :pseudo-selectors(parameter, lists). * * @param {string} selector * @return {string[]} */ function splitSelector(selector) { if (selector.indexOf(',') === -1) { return [selector]; } var indices = [], res = [], inParen = 0, o; /*eslint-disable no-cond-assign*/ while (o = selectorTokenizer.exec(selector)) { /*eslint-enable no-cond-assign*/ switch (o[0]) { case '(': inParen++;break; case ')': inParen--;break; case ',': if (inParen) break;indices.push(o.index); } } for (o = indices.length; o--;) { res.unshift(selector.slice(indices[o] + 1)); selector = selector.slice(0, indices[o]); } res.unshift(selector); return res; } function selector(id, path) { if (!id) { return path.replace(/\&/g, ''); } if (!path) return '.css-' + id + ',[data-css-' + id + ']'; var x = splitSelector(path).map(function (x) { return x.indexOf('&') >= 0 ? [x.replace(/\&/mg, '.css-' + id), x.replace(/\&/mg, '[data-css-' + id + ']')].join(',') // todo - make sure each sub selector has an & : '.css-' + id + x + ',[data-css-' + id + ']' + x; }).join(','); if (canSimulate && /^\&\:/.exec(path) && !/\s/.exec(path)) { x += ',.css-' + id + '[data-simulate-' + simple(path) + '],[data-css-' + id + '][data-simulate-' + simple(path) + ']'; } return x; } // end https://github.com/j2css/j2c/blob/5d381c2d721d04b54fabe6a165d587247c3087cb/src/helpers.js#L28-L61 function toCSS(_ref) { var selector = _ref.selector, style = _ref.style; var result = plugins.transform({ selector: selector, style: style }); return result.selector + '{' + (0, _CSSPropertyOperations.createMarkupForStyles)(result.style) + '}'; } function deconstruct(style) { // we can be sure it's not infinitely nested here var plain = void 0, selects = void 0, medias = void 0, supports = void 0; Object.keys(style).forEach(function (key) { if (key.indexOf('&') >= 0) { selects = selects || {}; selects[key] = style[key]; } else if (key.indexOf('@media') === 0) { medias = medias || {}; medias[key] = deconstruct(style[key]); } else if (key.indexOf('@supports') === 0) { supports = supports || {}; supports[key] = deconstruct(style[key]); } else if (key === 'label') { if (style.label.length > 0) { plain = plain || {}; plain.label = hasLabels ? style.label.join('.') : ''; } } else { plain = plain || {}; plain[key] = style[key]; } }); return { plain: plain, selects: selects, medias: medias, supports: supports }; } function deconstructedStyleToCSS(id, style) { var css = []; // plugins here var plain = style.plain, selects = style.selects, medias = style.medias, supports = style.supports; if (plain) { css.push(toCSS({ style: plain, selector: selector(id) })); } if (selects) { Object.keys(selects).forEach(function (key) { return css.push(toCSS({ style: selects[key], selector: selector(id, key) })); }); } if (medias) { Object.keys(medias).forEach(function (key) { return css.push(key + '{' + deconstructedStyleToCSS(id, medias[key]).join('') + '}'); }); } if (supports) { Object.keys(supports).forEach(function (key) { return css.push(key + '{' + deconstructedStyleToCSS(id, supports[key]).join('') + '}'); }); } return css; } // this cache to track which rules have // been inserted into the stylesheet var inserted = styleSheet.inserted = {}; // and helpers to insert rules into said styleSheet function insert(spec) { if (!inserted[spec.id]) { inserted[spec.id] = true; var deconstructed = deconstruct(spec.style); var rules = deconstructedStyleToCSS(spec.id, deconstructed); inserted[spec.id] = isBrowser ? true : rules; rules.forEach(function (cssRule) { return styleSheet.insert(cssRule); }); } } // a simple cache to store generated rules var registered = styleSheet.registered = {}; function register(spec) { if (!registered[spec.id]) { registered[spec.id] = spec; } } function _getRegistered(rule) { if (isLikeRule(rule)) { var ret = registered[idFor(rule)]; if (ret == null) { throw new Error('[glamor] an unexpected rule cache miss occurred. This is probably a sign of multiple glamor instances in your app. See https://github.com/threepointone/glamor/issues/79'); } return ret; } return rule; } // todo - perf var ruleCache = {}; function toRule(spec) { register(spec); insert(spec); if (ruleCache[spec.id]) { return ruleCache[spec.id]; } var ret = _defineProperty({}, 'data-css-' + spec.id, hasLabels ? spec.label || '' : ''); Object.defineProperty(ret, 'toString', { enumerable: false, value: function value() { return 'css-' + spec.id; } }); ruleCache[spec.id] = ret; return ret; } function log() { //eslint-disable-line no-unused-vars console.log(this); //eslint-disable-line no-console return this; } function isSelector(key) { var possibles = [':', '.', '[', '>', ' '], found = false, ch = key.charAt(0); for (var i = 0; i < possibles.length; i++) { if (ch === possibles[i]) { found = true; break; } } return found || key.indexOf('&') >= 0; } function joinSelectors(a, b) { var as = splitSelector(a).map(function (a) { return !(a.indexOf('&') >= 0) ? '&' + a : a; }); var bs = splitSelector(b).map(function (b) { return !(b.indexOf('&') >= 0) ? '&' + b : b; }); return bs.reduce(function (arr, b) { return arr.concat(as.map(function (a) { return b.replace(/\&/g, a); })); }, []).join(','); } function joinMediaQueries(a, b) { return a ? '@media ' + a.substring(6) + ' and ' + b.substring(6) : b; } function isMediaQuery(key) { return key.indexOf('@media') === 0; } function isSupports(key) { return key.indexOf('@supports') === 0; } function joinSupports(a, b) { return a ? '@supports ' + a.substring(9) + ' and ' + b.substring(9) : b; } // flatten a nested array function flatten(inArr) { var arr = []; for (var i = 0; i < inArr.length; i++) { if (Array.isArray(inArr[i])) arr = arr.concat(flatten(inArr[i]));else arr = arr.concat(inArr[i]); } return arr; } var prefixedPseudoSelectors = { '::placeholder': ['::-webkit-input-placeholder', '::-moz-placeholder', '::-ms-input-placeholder'], ':fullscreen': [':-webkit-full-screen', ':-moz-full-screen', ':-ms-fullscreen'] // mutable! modifies dest. };function build(dest, _ref2) { var _ref2$selector = _ref2.selector, selector = _ref2$selector === undefined ? '' : _ref2$selector, _ref2$mq = _ref2.mq, mq = _ref2$mq === undefined ? '' : _ref2$mq, _ref2$supp = _ref2.supp, supp = _ref2$supp === undefined ? '' : _ref2$supp, _ref2$src = _ref2.src, src = _ref2$src === undefined ? {} : _ref2$src; if (!Array.isArray(src)) { src = [src]; } src = flatten(src); src.forEach(function (_src) { if (isLikeRule(_src)) { var reg = _getRegistered(_src); if (reg.type !== 'css') { throw new Error('cannot merge this rule'); } _src = reg.style; } _src = (0, _clean2.default)(_src); if (_src && _src.composes) { build(dest, { selector: selector, mq: mq, supp: supp, src: _src.composes }); } Object.keys(_src || {}).forEach(function (key) { if (isSelector(key)) { if (prefixedPseudoSelectors[key]) { prefixedPseudoSelectors[key].forEach(function (p) { return build(dest, { selector: joinSelectors(selector, p), mq: mq, supp: supp, src: _src[key] }); }); } build(dest, { selector: joinSelectors(selector, key), mq: mq, supp: supp, src: _src[key] }); } else if (isMediaQuery(key)) { build(dest, { selector: selector, mq: joinMediaQueries(mq, key), supp: supp, src: _src[key] }); } else if (isSupports(key)) { build(dest, { selector: selector, mq: mq, supp: joinSupports(supp, key), src: _src[key] }); } else if (key === 'composes') { // ignore, we already dealth with it } else { var _dest = dest; if (supp) { _dest[supp] = _dest[supp] || {}; _dest = _dest[supp]; } if (mq) { _dest[mq] = _dest[mq] || {}; _dest = _dest[mq]; } if (selector) { _dest[selector] = _dest[selector] || {}; _dest = _dest[selector]; } if (key === 'label') { if (hasLabels) { dest.label = dest.label.concat(_src.label); } } else { _dest[key] = _src[key]; } } }); }); } function _css(rules) { var style = { label: [] }; build(style, { src: rules }); // mutative! but worth it. var spec = { id: hashify(style), style: style, label: hasLabels ? style.label.join('.') : '', type: 'css' }; return toRule(spec); } var nullrule = { // 'data-css-nil': '' }; Object.defineProperty(nullrule, 'toString', { enumerable: false, value: function value() { return 'css-nil'; } }); var inputCaches = typeof WeakMap !== 'undefined' ? [nullrule, new WeakMap(), new WeakMap(), new WeakMap()] : [nullrule]; var warnedWeakMapError = false; function multiIndexCache(fn) { return function (args) { if (inputCaches[args.length]) { var coi = inputCaches[args.length]; var ctr = 0; while (ctr < args.length - 1) { if (!coi.has(args[ctr])) { coi.set(args[ctr], new WeakMap()); } coi = coi.get(args[ctr]); ctr++; } if (coi.has(args[args.length - 1])) { var ret = coi.get(args[ctr]); if (registered[ret.toString().substring(4)]) { // make sure it hasn't been flushed return ret; } } } var value = fn(args); if (inputCaches[args.length]) { var _ctr = 0, _coi = inputCaches[args.length]; while (_ctr < args.length - 1) { _coi = _coi.get(args[_ctr]); _ctr++; } try { _coi.set(args[_ctr], value); } catch (err) { if (isDev && !warnedWeakMapError) { var _console; warnedWeakMapError = true; (_console = console).warn.apply(_console, ['failed setting the WeakMap cache for args:'].concat(_toConsumableArray(args))); // eslint-disable-line no-console console.warn('this should NOT happen, please file a bug on the github repo.'); // eslint-disable-line no-console } } } return value; }; } var cachedCss = typeof WeakMap !== 'undefined' ? multiIndexCache(_css) : _css; function css() { for (var _len2 = arguments.length, rules = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { rules[_key2] = arguments[_key2]; } if (rules[0] && rules[0].length && rules[0].raw) { throw new Error('you forgot to include glamor/babel in your babel plugins.'); } rules = (0, _clean2.default)(rules); if (!rules) { return nullrule; } return cachedCss(rules); } css.insert = function (css) { var spec = { id: hashify(css), css: css, type: 'raw' }; register(spec); if (!inserted[spec.id]) { styleSheet.insert(spec.css); inserted[spec.id] = isBrowser ? true : [spec.css]; } }; var insertRule = exports.insertRule = css.insert; css.global = function (selector, style) { style = (0, _clean2.default)(style); if (style) { return css.insert(toCSS({ selector: selector, style: style })); } }; var insertGlobal = exports.insertGlobal = css.global; function insertKeyframe(spec) { if (!inserted[spec.id]) { var inner = Object.keys(spec.keyframes).map(function (kf) { var result = plugins.keyframes.transform({ id: spec.id, name: kf, style: spec.keyframes[kf] }); return result.name + '{' + (0, _CSSPropertyOperations.createMarkupForStyles)(result.style) + '}'; }).join(''); var rules = ['-webkit-', '-moz-', '-o-', ''].map(function (prefix) { return '@' + prefix + 'keyframes ' + (spec.name + '_' + spec.id) + '{' + inner + '}'; }); rules.forEach(function (rule) { return styleSheet.insert(rule); }); inserted[spec.id] = isBrowser ? true : rules; } } css.keyframes = function (name, kfs) { if (!kfs) { kfs = name, name = 'animation'; } // do not ignore empty keyframe definitions for now. kfs = (0, _clean2.default)(kfs) || {}; var spec = { id: hashify({ name: name, kfs: kfs }), type: 'keyframes', name: name, keyframes: kfs }; register(spec); insertKeyframe(spec); return name + '_' + spec.id; }; // we don't go all out for fonts as much, giving a simple font loading strategy // use a fancier lib if you need moar power css.fontFace = function (font) { font = (0, _clean2.default)(font); var spec = { id: hashify(font), type: 'font-face', font: font }; register(spec); insertFontFace(spec); return font.fontFamily; }; var fontFace = exports.fontFace = css.fontFace; var keyframes = exports.keyframes = css.keyframes; function insertFontFace(spec) { if (!inserted[spec.id]) { var rule = '@font-face{' + (0, _CSSPropertyOperations.createMarkupForStyles)(spec.font) + '}'; styleSheet.insert(rule); inserted[spec.id] = isBrowser ? true : [rule]; } } // rehydrate the insertion cache with ids sent from // renderStatic / renderStaticOptimized function rehydrate(ids) { // load up ids (0, _objectAssign2.default)(inserted, ids.reduce(function (o, i) { return o[i] = true, o; }, {})); // assume css loaded separately } // clears out the cache and empties the stylesheet // best for tests, though there might be some value for SSR. function flush() { inserted = styleSheet.inserted = {}; registered = styleSheet.registered = {}; ruleCache = {}; styleSheet.flush(); styleSheet.inject(); } var presets = exports.presets = { mobile: '(min-width: 400px)', Mobile: '@media (min-width: 400px)', phablet: '(min-width: 550px)', Phablet: '@media (min-width: 550px)', tablet: '(min-width: 750px)', Tablet: '@media (min-width: 750px)', desktop: '(min-width: 1000px)', Desktop: '@media (min-width: 1000px)', hd: '(min-width: 1200px)', Hd: '@media (min-width: 1200px)' }; var style = exports.style = css; function select(selector) { for (var _len3 = arguments.length, styles = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { styles[_key3 - 1] = arguments[_key3]; } if (!selector) { return style(styles); } return css(_defineProperty({}, selector, styles)); } var $ = exports.$ = select; function parent(selector) { for (var _len4 = arguments.length, styles = Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { styles[_key4 - 1] = arguments[_key4]; } return css(_defineProperty({}, selector + ' &', styles)); } var merge = exports.merge = css; var compose = exports.compose = css; function media(query) { for (var _len5 = arguments.length, rules = Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) { rules[_key5 - 1] = arguments[_key5]; } return css(_defineProperty({}, '@media ' + query, rules)); } function pseudo(selector) { for (var _len6 = arguments.length, styles = Array(_len6 > 1 ? _len6 - 1 : 0), _key6 = 1; _key6 < _len6; _key6++) { styles[_key6 - 1] = arguments[_key6]; } return css(_defineProperty({}, selector, styles)); } // allllll the pseudoclasses function active(x) { return pseudo(':active', x); } function any(x) { return pseudo(':any', x); } function checked(x) { return pseudo(':checked', x); } function disabled(x) { return pseudo(':disabled', x); } function empty(x) { return pseudo(':empty', x); } function enabled(x) { return pseudo(':enabled', x); } function _default(x) { return pseudo(':default', x); // note '_default' name } function first(x) { return pseudo(':first', x); } function firstChild(x) { return pseudo(':first-child', x); } function firstOfType(x) { return pseudo(':first-of-type', x); } function fullscreen(x) { return pseudo(':fullscreen', x); } function focus(x) { return pseudo(':focus', x); } function hover(x) { return pseudo(':hover', x); } function indeterminate(x) { return pseudo(':indeterminate', x); } function inRange(x) { return pseudo(':in-range', x); } function invalid(x) { return pseudo(':invalid', x); } function lastChild(x) { return pseudo(':last-child', x); } function lastOfType(x) { return pseudo(':last-of-type', x); } function left(x) { return pseudo(':left', x); } function link(x) { return pseudo(':link', x); } function onlyChild(x) { return pseudo(':only-child', x); } function onlyOfType(x) { return pseudo(':only-of-type', x); } function optional(x) { return pseudo(':optional', x); } function outOfRange(x) { return pseudo(':out-of-range', x); } function readOnly(x) { return pseudo(':read-only', x); } function readWrite(x) { return pseudo(':read-write', x); } function required(x) { return pseudo(':required', x); } function right(x) { return pseudo(':right', x); } function root(x) { return pseudo(':root', x); } function scope(x) { return pseudo(':scope', x); } function target(x) { return pseudo(':target', x); } function valid(x) { return pseudo(':valid', x); } function visited(x) { return pseudo(':visited', x); } // parameterized pseudoclasses function dir(p, x) { return pseudo(':dir(' + p + ')', x); } function lang(p, x) { return pseudo(':lang(' + p + ')', x); } function not(p, x) { // should this be a plugin? var selector = p.split(',').map(function (x) { return x.trim(); }).map(function (x) { return ':not(' + x + ')'; }); if (selector.length === 1) { return pseudo(':not(' + p + ')', x); } return select(selector.join(''), x); } function nthChild(p, x) { return pseudo(':nth-child(' + p + ')', x); } function nthLastChild(p, x) { return pseudo(':nth-last-child(' + p + ')', x); } function nthLastOfType(p, x) { return pseudo(':nth-last-of-type(' + p + ')', x); } function nthOfType(p, x) { return pseudo(':nth-of-type(' + p + ')', x); } // pseudoelements function after(x) { return pseudo('::after', x); } function before(x) { return pseudo('::before', x); } function firstLetter(x) { return pseudo('::first-letter', x); } function firstLine(x) { return pseudo('::first-line', x); } function selection(x) { return pseudo('::selection', x); } function backdrop(x) { return pseudo('::backdrop', x); } function placeholder(x) { // https://github.com/threepointone/glamor/issues/14 return css({ '::placeholder': x }); } /*** helpers for web components ***/ // https://github.com/threepointone/glamor/issues/16 function cssFor() { for (var _len7 = arguments.length, rules = Array(_len7), _key7 = 0; _key7 < _len7; _key7++) { rules[_key7] = arguments[_key7]; } rules = (0, _clean2.default)(rules); return rules ? rules.map(function (r) { var style = { label: [] }; build(style, { src: r }); // mutative! but worth it. return deconstructedStyleToCSS(hashify(style), deconstruct(style)).join(''); }).join('') : ''; } function attribsFor() { for (var _len8 = arguments.length, rules = Array(_len8), _key8 = 0; _key8 < _len8; _key8++) { rules[_key8] = arguments[_key8]; } rules = (0, _clean2.default)(rules); var htmlAttributes = rules ? rules.map(function (rule) { idFor(rule); // throwaway check for rule var key = Object.keys(rule)[0], value = rule[key]; return key + '="' + (value || '') + '"'; }).join(' ') : ''; return htmlAttributes; }