UNPKG

stylekit

Version:

In-browser CSS generation with variable binding and live updates

390 lines (301 loc) 9.57 kB
;(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ var stylekit = require('../'); window.init = function() { var styleSet = stylekit(); styleSet.vars.set('MAIN_COLOR', 'red'); styleSet.vars.set('SECONDARY_COLOR', 'pink'); var b1 = styleSet.block(); b1.appendCSS('h1 { color: $MAIN_COLOR; }'); b1.commit(); var b2 = styleSet.block(); b2.rule('div', { border: '5px solid $MAIN_COLOR', background: '$SECONDARY_COLOR', padding: '30px' }); b2.commit(); function bindInput(name, v) { var input = document.querySelector('input[name=' + name + ']'); input.value = styleSet.vars.get(v); document.querySelector('input[type=button]').addEventListener('click', function() { styleSet.vars.set(v, input.value); }); } bindInput('main', 'MAIN_COLOR'); bindInput('secondary', 'SECONDARY_COLOR'); } },{"../":2}],2:[function(require,module,exports){ var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {};var styleTag = require('style-tag'), builder = require('css-builder'), wmap = require('wmap'); var VAR_RE = /\$[\w-]+/g; // // function StyleSet(doc) { this._document = doc || global.document || document; this._blocks = []; this.vars = wmap(); this.vars.getInt = function(key) { var val = this.get(key); return (typeof val === 'undefined') ? Number.NaN : parseInt(val, 10); } this.vars.getFloat = function(key) { var val = this.get(key); return (typeof val === 'undefined') ? Number.NaN : parseFloat(val, 10); } } StyleSet.prototype.block = function() { var block = new StyleBlock(this); this._blocks.push(block); return block; } // // function StyleBlock(set) { this._styleSet = set; this._styleTag = null; this._unwatch = null; this._builder = null; this._css = ''; } StyleBlock.prototype.appendCSS = function(css) { this._checkMutable(); this._css += css; return this; } StyleBlock.prototype.commit = function() { if (this._styleTag !== null) return; if (this._builder) this._builder.commit(); this._watchReferencedVariables(); this._styleTag = styleTag(this._styleSet._document, this._cssWithVariableExpansion()); } StyleBlock.prototype.destroy = function() { if (this._styleTag) { this._styleTag.destroy(); this._styleTag = false; this._unwatch(); this._unwatch = null; } } StyleBlock.prototype.rule = function(selector, rs) { if (this._builder === null) { this._builder = builder({ append: this.appendCSS.bind(this) }); } return this._builder.rule(selector, rs); } StyleBlock.prototype._watchReferencedVariables = function() { var matches = this._css.match(VAR_RE) || [], referencedVariables = matches.map(function(v) { return v.substr(1); }); this._unwatch = this._styleSet.vars.watch(referencedVariables, function() { this._styleTag(this._cssWithVariableExpansion()); }.bind(this)); } StyleBlock.prototype._cssWithVariableExpansion = function() { var vars = this._styleSet.vars; var css = this._css; while (css.match(VAR_RE)) { css = css.replace(VAR_RE, function(m) { return vars.get(m.substr(1)); }); } return css; } StyleBlock.prototype._checkMutable = function() { if (this._styleTag !== null) { throw new Error("style block is immutable - style tag already created"); } } // // module.exports = function(doc) { return new StyleSet(doc); } },{"css-builder":3,"style-tag":4,"wmap":5}],3:[function(require,module,exports){ // StyleBlock.prototype.macro = function(name, fn) { // this._macros[name] = fn; // } // StyleBlock.prototype.expand = function(macro) { // var m = this._lookupMacro(macro); // var args = slice.call(arguments, 0); // args[0] = this; // m.apply(null, args); // } // StyleBlock.prototype._lookupMacro = function(macro) { // var m = this._macros[macro]; // if (!m) throw new Error("unknown macro: " + macro); // return m; // } module.exports = function(options) { options = options || {}; var buffer = '', _append = options.append || function(str) { buffer += str; }, rules = [], path = [], currSelector = null, lastSelector = null, b = options.builder || {}, frozen = false; function attrib(name, value) { frozen && throwFrozen(); append(currSelector, translateKey(name) + ': ' + value); return this; } function attribs(as) { frozen && throwFrozen(); for (var k in as) { attrib(k, as[k]); } return this; } function rule(selector, rs) { frozen && throwFrozen(); if (Array.isArray(rs)) { rs.forEach(function(r) { rule(selector, r); }, b); return; } var oldSelector = currSelector; path.push(selector); currSelector = path.join(' ').replace(/\s+\&/g, ''); if (typeof rs === 'string') { append(currSelector, rs); } else if (typeof rs === 'function') { rs(b); } else if (typeof rs === 'object') { for (var cssKey in rs) { var cssValue = rs[cssKey]; if (typeof cssValue === 'object') { rule(cssKey, cssValue); } else { attrib(cssKey, cssValue); } } } else { throw new TypeError("rule must be string, function or object"); } path.pop(); currSelector = oldSelector; return this; } function append(sel, css) { if (lastSelector === sel) { _append(' ' + css + ';'); } else { if (lastSelector !== null) { _append(" }\n"); } _append(sel + ' { ' + css + ';'); lastSelector = sel; } } function commit() { if (!frozen) { if (lastSelector) { _append(" }\n"); } frozen = true; } } function translateKey(k) { return k.replace(/[A-Z]/g, function(m) { return '-' + m[0].toLowerCase(); }); } function throwFrozen() { throw new Error("can't modify CSS builder - is frozen"); } b.attrib = attrib; b.attribs = attribs; b.rule = rule; b.commit = commit; b.toString = function() { commit(); return buffer; } return b; } },{}],4:[function(require,module,exports){ // adapted from // http://stackoverflow.com/questions/524696/how-to-create-a-style-tag-with-javascript module.exports = function(doc, initialCss) { if (typeof doc === 'string') { initialCss = doc; doc = null; } doc = doc || document; var head = doc.getElementsByTagName('head')[0], style = doc.createElement('style'); style.type = 'text/css'; head.appendChild(style); function set(css) { css = '' + (css || ''); if (style.styleSheet) { style.styleSheet.cssText = css; } else { while (style.childNodes.length) { style.removeChild(style.firstChild); } style.appendChild(doc.createTextNode(css)); } } set(initialCss || ''); set.el = style; set.destroy = function() { head.removeChild(style); } return set; } },{}],5:[function(require,module,exports){ function WMap(parent) { this._entries = {}; this._watchers = {}; } WMap.prototype.get = function(key) { return this._entries[key]; } WMap.prototype.set = function(key, value) { var vb = this._entries[key]; this._entries[key] = value; this._dispatch(key, vb, value); } WMap.prototype.remove = function(key) { var vb = this._entries[key]; delete this._entries[key]; this._dispatch(key, vb, undefined); } WMap.prototype.watch = function(keys, cb) { if (!Array.isArray(keys)) keys = [keys]; if (keys.length === 0) return function() {}; var ws = this._watchers; keys.forEach(function(k) { (k in ws) ? ws[k].push(cb) : (ws[k] = [cb]); }, this); return function() { keys.forEach(function(k) { var kws = ws[k]; for (var i = 0; i < kws.length; ++i) { if (kws[i] === cb) { kws.splice(i, 1); return; } } }); }; } WMap.prototype._dispatch = function(key, oldValue, newValue) { var ws = this._watchers[key]; if (!ws) return; ws.forEach(function(c) { c(key, oldValue, newValue); }); } module.exports = function() { return new WMap(); } },{}]},{},[1]) ;