UNPKG

twrnc

Version:
232 lines (231 loc) 9.89 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.create = void 0; const resolveConfig_1 = __importDefault(require("tailwindcss/resolveConfig")); const cache_1 = __importDefault(require("./cache")); const UtilityParser_1 = __importDefault(require("./UtilityParser")); const color_1 = require("./resolve/color"); const parse_inputs_1 = require("./parse-inputs"); const helpers_1 = require("./helpers"); const plugin_1 = require("./plugin"); function create(customConfig, platform) { const config = (0, resolveConfig_1.default)(withContent(customConfig)); const device = {}; const pluginUtils = (0, plugin_1.getAddedUtilities)(config.plugins); const customStringUtils = {}; const customStyleUtils = Object.entries(pluginUtils) .map(([rawUtil, style]) => { const util = rawUtil.replace(/^\./, ``); if (typeof style === `string`) { // sacrifice functional purity to only iterate once customStringUtils[util] = style; return [util, { kind: `null` }]; } return [util, (0, helpers_1.complete)(style)]; }) .filter(([, ir]) => ir.kind !== `null`); patchCustomFontUtils(customConfig, customStyleUtils, config); function deriveCacheGroup() { return ([ device.colorScheme === `dark` ? `dark` : false, device.windowDimensions ? `w${device.windowDimensions.width}` : false, device.windowDimensions ? `h${device.windowDimensions.height}` : false, device.fontScale ? `fs${device.fontScale}` : false, device.pixelDensity === 2 ? `retina` : false, ] .filter(Boolean) .join(`--`) || `default`); } // eslint-disable-next-line @typescript-eslint/explicit-function-return-type const tailwindFn = (strings, ...values) => { let str = ``; strings.forEach((string, i) => { var _a; str += string + ((_a = values[i]) !== null && _a !== void 0 ? _a : ``); }); return style(str); }; const contextCaches = {}; let cache = new cache_1.default(); tailwindFn.memoBuster = ``; configureCache(); function configureCache() { const cacheGroup = deriveCacheGroup(); tailwindFn.memoBuster = `twrnc-memobuster-key--${cacheGroup}`; const existing = contextCaches[cacheGroup]; if (existing) { cache = existing; return; } const newCache = new cache_1.default(customStyleUtils); contextCaches[cacheGroup] = newCache; // set custom string utils into cache, so they are resolvable at all breakpoints for (const [key, value] of Object.entries(customStringUtils)) { newCache.setIr(key, (0, helpers_1.complete)(style(value))); } cache = newCache; } function style(...inputs) { let resolved = {}; const dependents = []; const ordered = []; const [utilities, userStyle] = (0, parse_inputs_1.parseInputs)(inputs); // check if we've seen this full set of classes before // if we have a cached copy, we can skip examining each utility const joined = utilities.join(` `); const cached = cache.getStyle(joined); if (cached) { return userStyle ? { ...cached, ...userStyle } : cached; } for (const utility of utilities) { let styleIr = cache.getIr(utility); if (!styleIr) { const parser = new UtilityParser_1.default(utility, config, cache, device, platform); styleIr = parser.parse(); } switch (styleIr.kind) { case `complete`: resolved = { ...resolved, ...styleIr.style }; cache.setIr(utility, styleIr); break; case `dependent`: dependents.push(styleIr); break; case `ordered`: ordered.push(styleIr); break; case `null`: cache.setIr(utility, styleIr); break; } } if (ordered.length > 0) { ordered.sort((a, b) => a.order - b.order); for (const orderedStyle of ordered) { switch (orderedStyle.styleIr.kind) { case `complete`: resolved = { ...resolved, ...orderedStyle.styleIr.style }; break; case `dependent`: dependents.push(orderedStyle.styleIr); break; } } } if (dependents.length > 0) { for (const dependent of dependents) { const error = dependent.complete(resolved); if (error) { (0, helpers_1.warn)(error); } } (0, color_1.removeOpacityHelpers)(resolved); } // cache the full set of classes for future re-renders // it's important we cache BEFORE merging in userStyle below if (joined !== ``) { cache.setStyle(joined, resolved); } if (userStyle) { resolved = { ...resolved, ...userStyle }; } return resolved; } function color(utils) { var _a, _b; const styleObj = style(utils .split(/\s+/g) .map((util) => util.replace(/^(bg|text|border)-/, ``)) .map((util) => `bg-${util}`) .join(` `)); if (typeof styleObj.backgroundColor === `string`) { return styleObj.backgroundColor; } else if ((_a = config.theme) === null || _a === void 0 ? void 0 : _a.colors) { return (_b = (0, color_1.configColor)(utils, config.theme.colors)) !== null && _b !== void 0 ? _b : undefined; } else { return undefined; } } tailwindFn.style = style; tailwindFn.color = color; tailwindFn.prefixMatch = (...prefixes) => { const joined = prefixes.sort().join(`:`); const cached = cache.getPrefixMatch(joined); if (cached !== undefined) { return cached; } const parser = new UtilityParser_1.default(`${joined}:flex`, config, cache, device, platform); const ir = parser.parse(); const prefixMatches = ir.kind !== `null`; cache.setPrefixMatch(joined, prefixMatches); return prefixMatches; }; tailwindFn.setWindowDimensions = (newDimensions) => { device.windowDimensions = newDimensions; configureCache(); }; tailwindFn.setFontScale = (newFontScale) => { device.fontScale = newFontScale; configureCache(); }; tailwindFn.setPixelDensity = (newPixelDensity) => { device.pixelDensity = newPixelDensity; configureCache(); }; tailwindFn.setColorScheme = (newColorScheme) => { device.colorScheme = newColorScheme; configureCache(); }; tailwindFn.getColorScheme = () => device.colorScheme; tailwindFn.updateDeviceContext = (window, fontScale, pixelDensity, colorScheme) => { device.windowDimensions = window; device.fontScale = fontScale; device.pixelDensity = pixelDensity; if (colorScheme !== `skip`) { device.colorScheme = colorScheme; } configureCache(); }; return tailwindFn; } exports.create = create; exports.default = create; function withContent(config) { return { ...config, // prevent warnings from tailwind about not having a `content` prop // we don't need one because we have our own jit parser which // does not rely on knowing content paths to search content: [`_no_warnings_please`], }; } // Allow override default font-<name> style // @TODO: long-term, i'd like to think of a more generic way to allow // custom configurations not to get masked by default utilities... function patchCustomFontUtils(customConfig, customStyleUtils, config) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p; if (((_a = customConfig.theme) === null || _a === void 0 ? void 0 : _a.fontWeight) || ((_c = (_b = customConfig.theme) === null || _b === void 0 ? void 0 : _b.extend) === null || _c === void 0 ? void 0 : _c.fontWeight)) { [ ...Object.entries((_e = (_d = customConfig.theme) === null || _d === void 0 ? void 0 : _d.fontWeight) !== null && _e !== void 0 ? _e : {}), ...Object.entries((_h = (_g = (_f = customConfig.theme) === null || _f === void 0 ? void 0 : _f.extend) === null || _g === void 0 ? void 0 : _g.fontWeight) !== null && _h !== void 0 ? _h : {}), ].forEach(([name, value]) => { customStyleUtils.push([`font-${name}`, (0, helpers_1.complete)({ fontWeight: String(value) })]); }); } if (`object` === typeof ((_j = config.theme) === null || _j === void 0 ? void 0 : _j.fontFamily)) { [ ...Object.entries((_l = (_k = customConfig.theme) === null || _k === void 0 ? void 0 : _k.fontFamily) !== null && _l !== void 0 ? _l : {}), ...Object.entries((_p = (_o = (_m = customConfig.theme) === null || _m === void 0 ? void 0 : _m.extend) === null || _o === void 0 ? void 0 : _o.fontFamily) !== null && _p !== void 0 ? _p : {}), ].forEach(([name, value]) => { const fontFamily = Array.isArray(value) ? value[0] : value; if (fontFamily) { customStyleUtils.push([`font-${name}`, (0, helpers_1.complete)({ fontFamily })]); } }); } }