tiwi
Version:
React library to create components with Tailwind styles baked in.
102 lines (101 loc) • 4.01 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildTiwi = buildTiwi;
const react_1 = require("react");
const tailwind_merge_1 = require("tailwind-merge");
const elements_js_1 = require("./elements.js");
const types_js_1 = require("./types.js");
//
// Variants helpers.
//
function variantsToArray(variants) {
if (!variants) {
return [];
}
if (typeof variants === "string") {
return [variants];
}
if (Array.isArray(variants)) {
return variants.filter(isString);
}
return Object.keys(variants).filter(k => variants[k] === true);
}
//
// Component factory.
//
function isTiwiComponent(Element) {
return Element && Element[types_js_1.tiwiComponentSymbol] === true;
}
function isString(value) {
return typeof value === "string";
}
function buildTiwiBase(createElement) {
return (Element) => {
return (classNames, ...variantDefinitions) => {
const AnyElement = Element;
const isTiwi = isTiwiComponent(Element);
const component = (0, react_1.forwardRef)((props, ref) => {
const { className, variants, ...otherProps } = props;
const flatVariants = variantsToArray(variants);
const flatVariantsString = flatVariants.join("::");
const mergedClassName = (0, react_1.useMemo)(() => {
const allClassNames = classNames.reduce((list, current, index) => {
const variantDefinition = variantDefinitions[index - 1];
if (variantDefinition) {
Object.keys(variantDefinition)
.filter(v => flatVariants.includes(v))
.forEach(v => {
const variantValue = variantDefinition[v];
if (!variantValue) {
return;
}
list.push(variantValue);
});
}
list.push(current);
return list;
}, []);
return (0, tailwind_merge_1.twMerge)([...allClassNames, className]) || undefined;
// Refresh on parent variables to make fast-refresh work in RN.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [classNames, variantDefinitions, className, flatVariantsString]);
if (isTiwi) {
return createElement(AnyElement, {
...otherProps,
ref: ref,
className: mergedClassName,
variants: variants,
});
}
return createElement(AnyElement, {
...otherProps,
ref: ref,
className: mergedClassName,
});
});
component[types_js_1.tiwiComponentSymbol] = true;
component.displayName = (() => {
if (typeof Element === "string") {
return (component.displayName = `tiwi.${Element}`);
}
const name = Element.displayName || Element.name || "";
return (component.displayName = `tiwi(${name})`);
})();
return component;
};
};
}
//
// Add intrinsic components to function.
//
function buildTiwi(createElement) {
const tiwiBase = buildTiwiBase(createElement);
if (typeof navigator === "object" && navigator.product === "ReactNative") {
return tiwiBase;
}
const intrinsicElementsFunctions = elements_js_1.allIntrinsicElements.reduce((result, DomElement) => {
result[DomElement] = tiwiBase(DomElement);
return result;
}, {});
return Object.assign(tiwiBase, intrinsicElementsFunctions);
}