UNPKG

oncss

Version:

A CSS framework for modern web development.

317 lines (313 loc) 12.2 kB
'use strict'; var youid = require('youid'); // const _global: any = typeof window !== 'undefined' ? window : global; // _global.Factory = _global.Factory || new Map<string, CSSFactoryType>(); // export const CSSFactory = _global.Factory as Map<string, CSSFactoryType> const caches = new Map(); const ONCSS_CACHE = { set(cacheId, cachekey, value) { let cache = caches.get(cacheId); if (!cache) { cache = new Map(); caches.set(cacheId, cache); } cache.set(cachekey, value); }, get(cacheId, cachekey) { let cache = caches.get(cacheId); if (cache) { return cache.get(cachekey); } }, has(cacheId, cachekey) { let cache = caches.get(cacheId); if (cache) { return cache.has(cachekey); } return false; }, delete(cacheId, cachekey) { let cache = caches.get(cacheId); if (cache) { cache.delete(cachekey); } }, caches() { return caches; } }; const number_val_props = [ "fontWeight", "font-weight", "lineHeight", "line-height", "opacity", "zIndex", "z-index", "flex", "order", "flexGrow", "flex-grow", "flexShrink", "flex-shrink", "flexBasis", "flex-basis", "columns", "perspective", "stroke-dashoffset" ]; const formatCSSProp = (prop) => prop.split(/(?=[A-Z])/).join("-").toLowerCase(); const formatCSSValue = (prop, val) => typeof val === 'number' && !number_val_props.includes(prop) ? `${val}px` : val; const PREFIXES = ['webkit', 'moz', 'ms', 'o']; let _declaration; const PREFIXCACHE = new Map(); const cssPrefix = (prop, value) => { value = formatCSSValue(prop, value); prop = formatCSSProp(prop); if (typeof window === 'undefined') { return { prop, value }; } const declaration = _declaration || (_declaration = document.createElement("div").style); value = value === null || value === void 0 ? void 0 : value.toString(); // Check if the property and value work as is if (declaration.setProperty(prop, value), declaration.getPropertyValue(prop) === value) { return { prop, value }; } // Check cached property and value prefix const cached = PREFIXCACHE.get(prop); if (cached) { return { prop: cached._prop, value: `${cached._vprefix}${value}` }; } let _prop = prop; let _value = value; let _vprefix = ''; // Try property prefixes const camelCaseProp = prop.includes('-') ? prop.replace(/-([a-z])/g, (_, c) => c.toUpperCase()) : prop; for (const prefix of PREFIXES) { if (declaration[`${prefix}${camelCaseProp}`] !== undefined) { _prop = `-${prefix}-${prop}`; break; } } // Check if prefixed property works with the value declaration.setProperty(_prop, value); if (!declaration.getPropertyValue(_prop)) { for (const prefix of PREFIXES) { const prefixedValue = `-${prefix}-${value}`; if (declaration.setProperty(_prop, prefixedValue), declaration.getPropertyValue(_prop) === prefixedValue) { _value = prefixedValue; _vprefix = `-${prefix}-`; break; } } } PREFIXCACHE.set(prop, { _prop, _vprefix }); return { prop: _prop, value: _value }; }; const resolveStyleContainer = (input) => { if (typeof window === 'undefined') { return { document: undefined, container: undefined }; } // Default → current document if (!input) { return { document, container: document.head, }; } // If input is a Document (works across iframes) if ("nodeType" in input && input.nodeType === 9) { return { document: input, container: input.head || input.getElementsByTagName("head")[0], }; } // If input is an HTMLElement → use its owner document if ("ownerDocument" in input && input instanceof HTMLElement) { return { document: input.ownerDocument, container: input, }; } throw new Error("Invalid input: must be Document or HTMLElement"); }; const style = (_css, cls, opt, dept = 1) => { var _a, _b, _c; let cachekey; let classname = cls; const cacheId = (opt === null || opt === void 0 ? void 0 : opt.cacheId) || "global"; if (!cls) { cachekey = ((_a = opt === null || opt === void 0 ? void 0 : opt.selector) !== null && _a !== void 0 ? _a : "") + JSON.stringify(_css, (_key, value) => typeof value === "function" ? value.toString() : value); const has = ONCSS_CACHE.get(cacheId, cachekey); if (has) { has.cache = true; return has; } classname = `${(opt === null || opt === void 0 ? void 0 : opt.classPrefix) || ""}x${youid(cachekey)}`; } else if (typeof cls !== 'string') { throw new Error(`Invalid class name: ${cls}`); } let stack = [`${classname}{`]; let medias = {}; let skiped = {}; for (let prop in _css) { let val = _css[prop]; let firstChar = prop.charAt(0); if (firstChar === '&') { let ncls = prop.replace(/&/g, classname); const r = style(val, ncls, opt, dept + 1); if (opt === null || opt === void 0 ? void 0 : opt.skipProps) { skiped = Object.assign(Object.assign({}, skiped), r.skiped); } stack.push(r.stack); } else if (firstChar === '@') { if (prop.startsWith("@global") || prop.startsWith("@keyframes")) { let _css = ''; for (let selector in val) { let r = style(val[selector], selector, opt, dept + 1); _css += r.stack; if (opt === null || opt === void 0 ? void 0 : opt.skipProps) { skiped = Object.assign(Object.assign({}, skiped), r.skiped); } } if (prop.startsWith("@keyframes")) { stack.push(`${prop}{${_css}}`); } else { stack.push(_css); } } else { let r = style(val, classname, opt, dept + 1); const atcss = prop + "{" + r.stack + "}"; stack.push(atcss); if (opt === null || opt === void 0 ? void 0 : opt.skipProps) { skiped = Object.assign(Object.assign({}, skiped), r.skiped); } } } else { if ((opt === null || opt === void 0 ? void 0 : opt.skipProps) && opt.skipProps(prop, val, dept)) { if (!(classname in skiped)) skiped[classname] = []; skiped[classname].push(prop); continue; } if (typeof val === 'function' || Array.isArray(val)) { continue; } if (typeof val === 'object') { for (let media in val) { if (typeof val[media] === 'object' || typeof val[media] === 'function' || Array.isArray(val[media])) { throw new Error(`Invalid css value: ${val[media]}`); } let breakpoint = media; let isNumber = !isNaN(parseInt(breakpoint)); if (!isNumber) { if ((opt === null || opt === void 0 ? void 0 : opt.breakpoints) && !isNaN(parseInt(opt.breakpoints[media]))) { breakpoint = opt.breakpoints[media].toString(); } else { throw new Error(`Invalid breakpoint prop: ${media}`); } } let _css = { [prop]: val[media] }; let r = style(_css, classname, opt, dept); let _style = r.stack; let mediakey = `@media (min-width: ${breakpoint}px)`; medias[mediakey] = medias[mediakey] ? medias[mediakey] + _style : _style; if (opt === null || opt === void 0 ? void 0 : opt.skipProps) { skiped = Object.assign(Object.assign({}, skiped), r.skiped); } } } else { if (opt === null || opt === void 0 ? void 0 : opt.getProps) { let _props = opt.getProps(prop, val, _css, dept); if (_props) { let r = style(_props, classname, Object.assign(Object.assign({}, opt), { getProps: undefined })); if (opt === null || opt === void 0 ? void 0 : opt.skipProps) { skiped = Object.assign(Object.assign({}, skiped), r.skiped); } stack.push(r.stack); continue; } } if ((opt === null || opt === void 0 ? void 0 : opt.aliases) && opt.aliases[prop]) { let _props = opt.aliases[prop](val); if (_props) { let r = style(_props, classname, Object.assign(Object.assign({}, opt), { aliases: undefined }), dept); r.stack = r.stack.replace(`${classname}{`, '').replace(`}`, ''); stack[0] += r.stack; continue; } } if (opt === null || opt === void 0 ? void 0 : opt.getValue) { val = opt.getValue(prop, val, _css, dept); } let p = cssPrefix(prop, val); stack[0] += `${p.prop}:${p.value};`; } } } stack[0] += "}"; if (stack[0] === `${classname}{}`) { stack[0] = ""; } stack = stack.join(''); for (let media in medias) { stack += `${media}{${medias[media].replace(new RegExp(`}\\${classname}\\{`, 'g'), '')}}`; } if (cachekey) { const d = resolveStyleContainer(opt === null || opt === void 0 ? void 0 : opt.container); const selector = (_b = opt === null || opt === void 0 ? void 0 : opt.selector) !== null && _b !== void 0 ? _b : "."; stack = stack.replace(new RegExp(classname, 'g'), `${selector}${classname}`); const r = { cache: false, cachekey, selector, classname: classname, css: stack, cssraw: _css, skiped, cacheId, getStyleTag: () => { var _a; return (_a = d.container) === null || _a === void 0 ? void 0 : _a.querySelector(`style[data-href="${classname}"]`); }, deleteStyle: () => { const tag = r.getStyleTag(); tag && tag.remove(); }, inject: () => { var _a, _b; const tag = r.getStyleTag() || ((_a = d.document) === null || _a === void 0 ? void 0 : _a.createElement("style")); if (tag && !(tag === null || tag === void 0 ? void 0 : tag.innerHTML)) { tag.innerHTML = r.css; tag.setAttribute(`data-href`, classname); (_b = d.container) === null || _b === void 0 ? void 0 : _b.appendChild(tag); } return tag; }, refresh: () => { r.deleteStyle(); return r.inject(); } }; ONCSS_CACHE.set(cacheId, cachekey, r); let inject = (_c = opt === null || opt === void 0 ? void 0 : opt.injectStyle) !== null && _c !== void 0 ? _c : true; if (inject && d.document) { r.inject(); } return r; } return { stack, skiped }; }; exports.ONCSS_CACHE = ONCSS_CACHE; exports.cssPrefix = cssPrefix; exports.formatCSSProp = formatCSSProp; exports.formatCSSValue = formatCSSValue; exports.style = style; //# sourceMappingURL=core.cjs.map