next-yak
Version:
next-yak is a CSS-in-JS solution tailored for Next.js that seamlessly combines the expressive power of styled-components syntax with efficient build-time extraction of CSS using Next.js's built-in CSS configuration
60 lines (56 loc) • 1.64 kB
text/typescript
import type { css as cssInternal, PropsToClassNameFn } from "../cssLiteral.js";
export type { ComponentStyles, CSSInterpolation } from "../cssLiteral.js";
/**
* Allows to use CSS styles in a styled or css block
*
* e.g.
*
* ```tsx
* const Component = styled.div`
* color: black;
* ${({$active}) => $active && css`color: red;`}
* `;
* ```
*/
export const css: typeof cssInternal = (
styles: TemplateStringsArray,
...args: unknown[]
) => {
const dynamicCssFunctions: PropsToClassNameFn[] = [];
for (const arg of args as Array<string | Function | object>) {
// Dynamic CSS e.g.
// css`${props => props.active && css`color: red;`}`
// compiled -> css((props: { active: boolean }) => props.active && css("yak31e4"))
if (typeof arg === "function") {
dynamicCssFunctions.push(arg as unknown as PropsToClassNameFn);
}
}
if (dynamicCssFunctions.length === 0) {
return {
className: "",
style: undefined,
};
}
return ((props: unknown) => {
for (let i = 0; i < dynamicCssFunctions.length; i++) {
// run the dynamic expressions and ignore the return value
// the execution is important to ensure that the user code is executed
// the same way as in the real runtime
executeDynamicExpressionRecursively(props, dynamicCssFunctions[i]);
}
return {
className: "",
style: undefined,
};
}) as any;
};
function executeDynamicExpressionRecursively(
props: unknown,
expression: PropsToClassNameFn,
) {
let result = expression(props);
while (typeof result === "function") {
result = result(props);
}
return result;
}