UNPKG

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

1 lines 34.8 kB
{"version":3,"file":"index.cjs","names":["css","css","styled","css","INTERNAL.ATTRS_MERGED","INTERNAL.RUNTIME_STYLES_DONE","StyledFactory"],"sources":["../runtime/cssLiteral.tsx","../runtime/atoms.tsx","../runtime/mocks/cssLiteral.ts","../runtime/mocks/keyframes.ts","../runtime/internals/propMarkers.ts","../runtime/internals/mergeClassNames.ts","../runtime/styled.tsx","../runtime/mocks/styled.ts","../runtime/mocks/globalStyle.ts"],"sourcesContent":["import type { YakTheme } from \"./index.ts\";\nimport { ClassNameCollector, RuntimeStyleProcessor } from \"./publicStyledApi.js\";\n\nexport const yakComponentSymbol = Symbol(\"yak\");\n\n/**\n * String-backed ClassNameCollector used by the render path\n *\n * `add` is a plain string append and does not deduplicate, so the collector is\n * a multiset - the same class may appear twice, e.g. `atoms(\"a b\", \"a\")` → `\"a b a\"`.\n * `has`/`delete` cover the rare path where a runtime function inspects or\n * removes classes; `delete` removes every occurrence\n */\nexport class ClassNames implements ClassNameCollector {\n value: string;\n constructor(initial?: string) {\n this.value = initial || \"\";\n }\n add(className: string) {\n this.value += (this.value && \" \") + className;\n }\n has(className: string) {\n return (\" \" + this.value + \" \").includes(\" \" + className + \" \");\n }\n delete(className: string) {\n if (this.has(className)) {\n this.value = this.value\n .split(\" \")\n .filter((existing) => existing !== className)\n .join(\" \");\n }\n }\n}\n\nexport type ComponentStyles<TProps> = (props: TProps) => {\n className: string;\n style?: {\n [key: string]: string;\n };\n};\n\nexport type CSSInterpolation<TProps> =\n | string\n | number\n | undefined\n | null\n | false\n | ComponentStyles<TProps>\n | {\n // type only identifier to allow targeting components\n // e.g. styled.svg`${Button}:hover & { fill: red; }`\n [yakComponentSymbol]: any;\n }\n | ((props: TProps) => CSSInterpolation<TProps>);\n\ntype CSSStyles<TProps = {}> = {\n style: { [key: string]: string | ((props: TProps) => string) };\n};\n\ntype CSSFunction = <TProps = {}>(\n styles: TemplateStringsArray,\n ...values: CSSInterpolation<TProps & { theme: YakTheme }>[]\n) => ComponentStyles<TProps>;\n\nexport type NestedRuntimeStyleProcessor = (\n props: unknown,\n classNames: ClassNameCollector,\n style: React.CSSProperties,\n) =>\n | {\n className?: string;\n style?: React.CSSProperties;\n }\n | void\n | NestedRuntimeStyleProcessor;\n\n/**\n * css() runtime factory of css``\n *\n * /!\\ next-yak transpiles css`` and styled``\n *\n * This changes the typings of the css`` and styled`` functions.\n * During development the user of next-yak wants to work with the\n * typings BEFORE compilation.\n *\n * Therefore this is only an internal function only and it must be cast to any\n * before exported to the user.\n *\n * The internal functioning of css`` is to return a single callback function that runs all functions\n * (or creates new ones if needed) that are passed as arguments. These functions receive the props, classNames, and style object as arguments\n * and operate directly on the classNames and style objects.\n */\nexport function css<TProps>(\n styles: TemplateStringsArray,\n ...values: CSSInterpolation<NoInfer<TProps> & { theme: YakTheme }>[]\n): ComponentStyles<TProps>;\nexport function css<TProps>(...args: Array<any>): RuntimeStyleProcessor<TProps> {\n // Normally this could be an array of strings passed, but as we transpile the usage of css`` ourselves, we control the arguments\n // and ensure that only the first argument is a string (class name of the non-dynamic styles)\n let className: string | undefined;\n const dynamicCssFunctions: NestedRuntimeStyleProcessor[] = [];\n for (const arg of args as Array<string | CSSFunction | CSSStyles<any>>) {\n // A CSS-module class name which got auto generated during build from static css\n // e.g. css`color: red;`\n // compiled -> css(\"yak31e4\")\n if (typeof arg === \"string\") {\n className = arg;\n }\n // Dynamic CSS e.g.\n // css`${props => props.active && css`color: red;`}`\n // compiled -> css((props: { active: boolean }) => props.active && css(\"yak31e4\"))\n else if (typeof arg === \"function\") {\n dynamicCssFunctions.push(arg as unknown as NestedRuntimeStyleProcessor);\n }\n // Dynamic CSS with css variables e.g.\n // css`transform: translate(${props => props.x}, ${props => props.y});`\n // compiled -> css(\"yak31e4\", { style: { \"--yakVarX\": props => props.x }, \"--yakVarY\": props => props.y }})\n else if (typeof arg === \"object\" && \"style\" in arg) {\n dynamicCssFunctions.push((props, _, style) => {\n for (const key in arg.style) {\n const value = arg.style[key];\n if (typeof value === \"function\") {\n // @ts-expect-error CSSProperties don't allow css variables\n style[key] = String(\n // The value for a css value can be a theme dependent function e.g.:\n // const borderColor = (props: { theme: { mode: \"dark\" | \"light\" } }) => props.theme === \"dark\" ? \"black\" : \"white\";\n // css`border-color: ${borderColor};`\n // Therefore the value has to be extracted recursively\n recursivePropExecution(props, value),\n );\n } else {\n // @ts-expect-error CSSProperties don't allow css variables\n style[key] = String(value);\n }\n }\n });\n }\n }\n\n // Non Dynamic CSS\n // This is just an optimization for the common case where there are no dynamic css functions\n // `$dynamic: false` lets the styled runtime skip theme lookup and\n // style-object allocation entirely for static components\n if (dynamicCssFunctions.length === 0) {\n return Object.assign(\n (_: unknown, classNames: ClassNameCollector) => {\n if (className) {\n classNames.add(className);\n }\n },\n { $dynamic: false },\n );\n }\n\n return Object.assign(\n (props: TProps, classNames: ClassNameCollector, allStyles: React.CSSProperties) => {\n if (className) {\n classNames.add(className);\n }\n for (let i = 0; i < dynamicCssFunctions.length; i++) {\n unwrapProps(props, dynamicCssFunctions[i], classNames, allStyles);\n }\n },\n { $dynamic: true },\n );\n}\n\n// Dynamic CSS with runtime logic\nconst unwrapProps = (\n props: unknown,\n fn: NestedRuntimeStyleProcessor,\n classNames: ClassNameCollector,\n style: React.CSSProperties,\n) => {\n let result = fn(props, classNames, style);\n while (result) {\n if (typeof result === \"function\") {\n result = result(props, classNames, style);\n continue;\n } else if (typeof result === \"object\") {\n if (\"className\" in result && result.className) {\n classNames.add(result.className);\n }\n if (\"style\" in result && result.style) {\n for (const key in result.style) {\n // This is hard for typescript to infer\n style[key as keyof React.CSSProperties] = result.style[\n key as keyof React.CSSProperties\n ] as any;\n }\n }\n }\n break;\n }\n};\n\nconst recursivePropExecution = (props: unknown, fn: (props: unknown) => any): string | number => {\n const result = fn(props);\n if (typeof result === \"function\") {\n return recursivePropExecution(props, result);\n }\n // the `process.env` lookup is a real per-call cost for unbundled Node\n // consumers, so it must stay behind the typeof guards on the invalid path\n if (typeof result !== \"string\" && typeof result !== \"number\" && !(result instanceof String)) {\n if (process.env.NODE_ENV === \"development\") {\n throw new Error(\n `Dynamic CSS functions must return a string or number but returned ${JSON.stringify(\n result,\n )}\\n\\nDynamic CSS function: ${fn.toString()}\\n`,\n );\n }\n }\n return result;\n};\n","import { ClassNames, ComponentStyles, css } from \"./cssLiteral.js\";\nimport { RuntimeStyleProcessor } from \"./publicStyledApi.js\";\n\n/**\n * Allows to use atomic CSS classes in a styled or css block\n *\n * @usage\n *\n * ```tsx\n * import { styled, atoms } from \"next-yak\";\n *\n * const Button = styled.button<{ $primary?: boolean }>`\n * ${atoms(\"text-teal-600\", \"text-base\", \"rounded-md\")}\n * ${props => props.$primary && atoms(\"shadow-md\")}\n * `;\n * ```\n */\nexport const atoms = <T,>(\n ...atoms: (string | RuntimeStyleProcessor<T> | false)[]\n): ComponentStyles<T> => {\n const staticClasses = new ClassNames();\n const dynamicFunctions: RuntimeStyleProcessor<T>[] = [];\n\n for (const atom of atoms) {\n if (typeof atom === \"string\") {\n staticClasses.add(atom);\n } else if (typeof atom === \"function\") {\n dynamicFunctions.push(atom);\n }\n }\n\n // the collected classes are passed as css()'s static class name,\n // only the dynamic atoms stay functions\n // @ts-expect-error the internal implementation of css is not typed\n return css(staticClasses.value, ...dynamicFunctions);\n};\n","import type { css as cssInternal, NestedRuntimeStyleProcessor } from \"../cssLiteral.js\";\n\nexport type { ComponentStyles, CSSInterpolation } from \"../cssLiteral.js\";\n\n/**\n * Allows to use CSS styles in a styled or css block\n *\n * e.g.\n *\n * ```tsx\n * const Component = styled.div`\n * color: black;\n * ${({$active}) => $active && css`color: red;`}\n * `;\n * ```\n */\nexport const css: typeof cssInternal = (styles: TemplateStringsArray, ...args: unknown[]) => {\n // When called in yak files as a template tag (without SWC transformation),\n // return { __yak: rawCss } so the cross-file resolver can\n // extract the mixin value from evaluated .yak files.\n if (Array.isArray(styles) && \"raw\" in styles) {\n let rawCss = styles[0];\n for (let i = 0; i < args.length; i++) {\n const interpolation = args[i];\n rawCss +=\n interpolation && typeof interpolation === \"object\" && \"__yak\" in interpolation\n ? (interpolation as { __yak: string }).__yak\n : String(interpolation);\n rawCss += styles[i + 1];\n }\n return { __yak: rawCss } as any;\n }\n\n const dynamicCssFunctions: NestedRuntimeStyleProcessor[] = [];\n for (const arg of args as Array<string | Function | object>) {\n // Dynamic CSS e.g.\n // css`${props => props.active && css`color: red;`}`\n // compiled -> css((props: { active: boolean }) => props.active && css(\"yak31e4\"))\n if (typeof arg === \"function\") {\n dynamicCssFunctions.push(arg as unknown as NestedRuntimeStyleProcessor);\n }\n }\n if (dynamicCssFunctions.length === 0) {\n return {\n className: \"\",\n style: undefined,\n };\n }\n return ((props: unknown) => {\n for (let i = 0; i < dynamicCssFunctions.length; i++) {\n // run the dynamic expressions and ignore the return value\n // the execution is important to ensure that the user code is executed\n // the same way as in the real runtime\n executeDynamicExpressionRecursively(props, dynamicCssFunctions[i]);\n }\n return {\n className: \"\",\n style: undefined,\n };\n }) as any;\n};\n\nfunction executeDynamicExpressionRecursively(\n props: unknown,\n expression: NestedRuntimeStyleProcessor,\n) {\n const classNames = new Set<string>();\n const style = {};\n let result = expression(props, classNames, style);\n while (typeof result === \"function\") {\n result = result(props, classNames, style);\n }\n return result;\n}\n","import type { keyframes as keyframesInternal } from \"../keyframes.js\";\n\n/**\n * Allows to use CSS keyframe animations in a styled or css block\n *\n * @usage\n *\n * ```tsx\n * import { styled, keyframes } from \"next-yak\";\n *\n * const rotate = keyframes`\n * from {\n * transform: rotate(0deg);\n * }\n * to {\n * transform: rotate(360deg);\n * }\n * `;\n *\n * const Spinner = styled.div`\n * animation: ${rotate} 1s linear infinite;\n * `;\n * ```\n */\nexport const keyframes: typeof keyframesInternal = (_styles, ..._dynamic) => {\n // the keyframes function is a no-op in the mock\n // as it has no dynamic runtime behavior but only css\n return \"\";\n};\n","/** Internal markers used by the render path */\n\n/**\n * Set on props once the attrs functions have been folded in, so a nested yak\n * wrapper further out the chain does not merge the same attrs twice\n */\nexport const ATTRS_MERGED = \"$__a\" as const;\n\n/**\n * Set on props once the runtime style processor has run, so an outer yak\n * component that receives already-processed props skips the collector entirely\n */\nexport const RUNTIME_STYLES_DONE = \"$__r\" as const;\n\n/**\n * Carries the constant `.attrs({...})` object on the merged attrs function,\n * marking it theme-independent so the fast render path can apply it without\n * executing anything. Lives on the function, never on props\n */\nexport const STATIC_ATTRS = \"$sa\" as const;\n","/**\n * Merges two optional class name values with a space.\n *\n * Used by the styled runtime to combine incoming and generated class names,\n * and injected by the compiler (as `__yak_mergeClassNames`) when it replaces\n * a JSX usage of a fully static styled component with a plain DOM element:\n * ```tsx\n * const Card = styled.div`color: red;`;\n * <Card className={active && \"active\"} />\n * ```\n * becomes\n * ```tsx\n * <div className={__yak_mergeClassNames(\"yX\", active && \"active\")} />\n * ```\n */\nexport const mergeClassNames = (\n a: string | false | null | undefined,\n b: string | false | null | undefined,\n) => {\n if (!a) return b || undefined;\n if (!b) return a;\n return a + \" \" + b;\n};\n","import { css, CSSInterpolation, ClassNames, yakComponentSymbol } from \"./cssLiteral.js\";\nimport * as INTERNAL from \"./internals/propMarkers.js\";\nimport React from \"react\";\nimport type {\n Attrs,\n AttrsMerged,\n Styled,\n YakComponent,\n AttrsFunction,\n StyledFn,\n HtmlTags,\n Substitute,\n StyledLiteral,\n RuntimeStyleProcessor,\n} from \"./publicStyledApi.js\";\n\n// the following export is not relative as \"next-yak/context\"\n// links to one file for react server components and\n// to another file for classic react components\nimport { useTheme } from \"next-yak/context\";\nimport type { YakTheme } from \"./context/index.tsx\";\nimport { mergeClassNames } from \"./internals/mergeClassNames.js\";\n\n//\n// The `styled()` API without `styled.` syntax\n//\n// The API design is inspired by styled-components:\n// https://github.com/styled-components/styled-components/blob/main/packages/styled-components/src/constructors/styled.tsx\n// https://github.com/styled-components/styled-components/blob/main/packages/styled-components/src/models/StyledComponent.ts\n//\nconst styledFactory: StyledFn = (Component) =>\n Object.assign(yakStyled(Component), {\n attrs: (attrs: Attrs<any>) => yakStyled(Component, attrs),\n });\n\n/**\n * The `styled` method works perfectly on all of your own or any third-party component,\n * as long as they attach the passed className prop to a DOM element.\n *\n * @usage\n *\n * ```tsx\n * const StyledLink = styled(Link)`\n * color: #BF4F74;\n * font-weight: bold;\n * `;\n * ```\n */\nexport const styled = styledFactory as Styled;\n\n/**\n * Real shape of the yakComponentSymbol tuple, which the public `YakComponent`\n * keeps opaque as `[unknown, ...]`\n */\ntype YakComponentInternals = [\n self: React.FunctionComponent,\n attrsFn: AttrsFunction<any, any, any> | undefined,\n styleProcessor: RuntimeStyleProcessor<unknown>,\n target: React.FunctionComponent | string,\n];\n\nconst yakStyled: StyledInternal = (Component, attrs) => {\n const isYakComponent = typeof Component !== \"string\" && yakComponentSymbol in Component;\n\n // if the component that is wrapped is a yak component, we can extract it to render the underlying component directly\n // and we can also extract the attrs function and the dynamic style function to merge it with the current attrs function (or dynamic style function)\n // so that the sequence of the attrs functions is preserved\n const [, parentAttrsFn, parentRuntimeStylesFn, parentTarget] = isYakComponent\n ? (Component[yakComponentSymbol] as [\n YakComponent<unknown>,\n ExtractAttrsFunction<typeof attrs>,\n RuntimeStyleProcessor<unknown>,\n React.FunctionComponent | string,\n ])\n : [];\n\n // the ultimate render target of the whole styled(styled(...)) chain:\n // attrs and style processors are already merged at construction time, so\n // a chain of N levels renders the target directly in ONE wrapper instead\n // of re-entering every parent wrapper per element per render\n const targetComponent = (isYakComponent ? parentTarget : Component) as\n | React.FunctionComponent\n | string;\n\n const mergedAttrsFn = buildRuntimeAttrsProcessor(attrs, parentAttrsFn);\n const staticAttrs = (mergedAttrsFn as StaticAttrsCarrier | undefined)?.[INTERNAL.STATIC_ATTRS];\n\n return (styles, ...values) => {\n // combine all interpolated logic into a single function\n // e.g. styled.button`color: ${props => props.color}; margin: ${props => props.margin};`\n const runtimeStylesFn = css(\n styles,\n ...(values as CSSInterpolation<unknown>[]),\n ) as RuntimeStyleProcessor<unknown>;\n const runtimeStyleProcessor = buildRuntimeStylesProcessor(\n runtimeStylesFn,\n parentRuntimeStylesFn,\n );\n const Yak: React.FunctionComponent = (props) => {\n // fast path for components that contribute the same thing on every\n // render — no attrs at all, or a constant `.attrs({...})` which cannot\n // read the theme — and no dynamic styles. Contributes the chain's class\n // names and strips $-props; skips theme lookup, prop spreading and style\n // cloning entirely (this is NOT against the rule of hooks — the condition\n // is constant for the lifetime of the component)\n if ((!mergedAttrsFn || staticAttrs) && !runtimeStyleProcessor.$dynamic) {\n // props that already went through a yak wrapper keep their processed\n // className, and `source` then aliases `props` — so the class names are\n // written to the fresh, filtered object rather than back into props\n const source = (\n staticAttrs && !(INTERNAL.ATTRS_MERGED in props)\n ? combineProps(\n {\n ...(props as { className?: string; style?: React.CSSProperties }),\n // mark the props as processed\n [INTERNAL.ATTRS_MERGED]: true,\n },\n staticAttrs,\n )\n : props\n ) as { className?: string; style?: React.CSSProperties };\n const filteredProps = removeNonDomProperties(source) as {\n className?: string;\n };\n if (!(INTERNAL.RUNTIME_STYLES_DONE in source)) {\n const classNames = new ClassNames(source.className);\n runtimeStyleProcessor(source, classNames, undefined as unknown as React.CSSProperties);\n filteredProps.className = classNames.value || undefined;\n }\n const Target = targetComponent as React.ElementType;\n return <Target {...(filteredProps as React.ComponentProps<typeof Target>)} />;\n }\n\n // attrs functions and dynamic style functions receive the theme —\n // fully static components take the fast path above and never read the\n // theme context\n const theme = useTheme();\n\n // The first components which is not wrapped in a yak component will execute all attrs functions\n // starting from the innermost yak component to the outermost yak component (itself)\n const combinedProps =\n INTERNAL.ATTRS_MERGED in props\n ? ({\n theme,\n ...props,\n } as {\n theme: YakTheme;\n className?: string;\n style?: React.CSSProperties;\n })\n : // overwrite and merge the current props with the processed attrs\n combineProps(\n {\n theme,\n ...(props as {\n className?: string;\n style?: React.CSSProperties;\n }),\n // mark the props as processed\n [INTERNAL.ATTRS_MERGED]: true,\n },\n mergedAttrsFn?.({ theme, ...(props as any) }),\n );\n\n // execute all functions inside the style literal if not already executed\n // e.g. styled.button`color: ${props => props.color};`\n //\n // inner levels of a styled(Component) chain receive already-processed\n // props and skip this entirely — no collector, no style clone\n if (!(INTERNAL.RUNTIME_STYLES_DONE in combinedProps)) {\n const classNames = new ClassNames(combinedProps.className);\n // static processors never write style values, so the incoming style\n // object can be passed through without a defensive copy\n const styles = runtimeStyleProcessor.$dynamic\n ? { ...combinedProps.style }\n : combinedProps.style;\n runtimeStyleProcessor(combinedProps, classNames, styles as React.CSSProperties);\n // @ts-expect-error this is not typed correctly\n combinedProps[INTERNAL.RUNTIME_STYLES_DONE] = true;\n\n combinedProps.className = classNames.value || undefined;\n if (styles !== combinedProps.style) {\n combinedProps.style = styles;\n }\n }\n\n // delete the yak theme from the props\n // this must happen after the runtimeStyles are calculated\n // prevents passing the theme prop to the DOM element of a styled component\n const { theme: themeAfterAttr, ...combinedPropsWithoutTheme } = combinedProps;\n const propsBeforeFiltering =\n themeAfterAttr === theme ? combinedPropsWithoutTheme : combinedProps;\n\n // remove all props that start with a $ sign so they reach neither DOM\n // elements nor custom components — this also strips the internal\n // INTERNAL.ATTRS_MERGED/INTERNAL.RUNTIME_STYLES_DONE markers, which must not cross a\n // custom component boundary (a custom component may render another yak\n // component that has to process its own attrs/styles)\n const filteredProps = removeNonDomProperties(propsBeforeFiltering);\n\n // render the chain's target directly — parent wrappers contribute only\n // their (already merged) attrs and style processors\n const Target = targetComponent as React.ElementType;\n return <Target {...(filteredProps as React.ComponentProps<typeof Target>)} />;\n };\n\n // Direct write instead of Object.assign (faster & smaller)\n const taggedYak = Yak as React.FunctionComponent & {\n [yakComponentSymbol]: YakComponentInternals;\n };\n taggedYak[yakComponentSymbol] = [Yak, mergedAttrsFn, runtimeStyleProcessor, targetComponent];\n return taggedYak;\n };\n};\n\n/**\n * Remove all entries that start with a $ sign\n *\n * This allows to have props that are used for internal styling purposes\n * but are not be passed to the DOM element\n */\nconst removeNonDomProperties = <T extends Record<string, unknown>>(obj: T): T => {\n const result = {} as T;\n for (const key in obj) {\n if (!key.startsWith(\"$\") && obj[key] !== undefined) {\n result[key] = obj[key];\n }\n }\n return result;\n};\n\n/**\n * merge props and processed props (including class names and styles)\n * e.g.:\\\n * `{ className: \"a\", foo: 1 }` and `{ className: \"b\", bar: 2 }` \\\n * => `{ className: \"a b\", foo: 1, bar: 2 }`\n */\nconst combineProps = <\n T extends {\n className?: string;\n style?: React.CSSProperties;\n },\n TOther extends\n | {\n className?: string;\n style?: React.CSSProperties;\n }\n | null\n | undefined,\n>(\n props: T,\n newProps: TOther,\n) =>\n newProps\n ? (props.className === newProps.className || !newProps.className) &&\n (props.style === newProps.style || !newProps.style)\n ? // shortcut if no style and class merging is necessary\n {\n ...props,\n ...newProps,\n }\n : // merge class names and styles\n {\n ...props,\n ...newProps,\n className: mergeClassNames(props.className, newProps.className),\n style: { ...props.style, ...newProps.style },\n }\n : // if no new props are provided, no merging is necessary\n props;\n\n/**\n * Merges the attrs function of the current component with the attrs function of the parent component\n * in order to preserve the sequence of the attrs functions.\n * Note: In theory, the parentAttrsFn can have different types for TAttrsIn and TAttrsOut\n * but as this is only used internally, we can ignore and simplify this case\n * @param attrs The attrs object or function of the current component (if any)\n * @param parentAttrsFn The attrs function of the parent/wrapped component (if any)\n * @returns A function that receives the props and returns the transformed props\n */\nconst buildRuntimeAttrsProcessor = <\n T,\n TAttrsIn extends object,\n TAttrsOut extends AttrsMerged<T, TAttrsIn>,\n>(\n attrs?: Attrs<T, TAttrsIn, TAttrsOut>,\n parentAttrsFn?: AttrsFunction<T, TAttrsIn, TAttrsOut>,\n): AttrsFunction<T, TAttrsIn, TAttrsOut> | undefined => {\n const ownAttrsFn = attrs && (typeof attrs === \"function\" ? attrs : () => attrs);\n\n if (ownAttrsFn && parentAttrsFn) {\n return (props) => {\n const parentProps = parentAttrsFn(props);\n\n // overwrite and merge the parent props with the props received from the attrs function\n // after they went through the parent attrs function.\n //\n // This makes sure the linearity of the attrs functions is preserved and all attrs function receive\n // the whole props object calculated from the previous attrs functions\n return combineProps(parentProps, ownAttrsFn(combineProps(props, parentProps)));\n };\n }\n\n // A constant `.attrs({...})` is wrapped into `() => attrs`, which makes it\n // indistinguishable from `.attrs(props => ...)` at render time — so record the\n // object it will always return. Only the wrapper closure is tagged, never a\n // user-supplied attrs function.\n //\n // A `styled(StyledWithAttrs).attrs({...})` chain merges its levels per render\n // and is not tagged, which keeps a mutation of an attrs object observable\n if (ownAttrsFn && typeof attrs !== \"function\") {\n return Object.assign(ownAttrsFn, {\n [INTERNAL.STATIC_ATTRS]: attrs,\n } as StaticAttrsCarrier);\n }\n\n return ownAttrsFn || parentAttrsFn;\n};\n\n/**\n * The constant object a `.attrs({...})` processor always returns\n *\n * Kept local to this module — like the `yakComponentSymbol` tuple, it is an\n * implementation detail and must not reach the public `AttrsFunction` type\n */\ntype StaticAttrsCarrier = { [K in typeof INTERNAL.STATIC_ATTRS]?: object };\n\n/**\n * Merges the runtime style function of the current component with the runtime style function of the parent component\n * in order to preserve the sequence of the attrs functions.\n * @param runtimeStylesFn The current runtime styles function\n * @param parentRuntimeStylesFn The parent runtime styles function\n * @returns The merged runtime styles function\n */\nconst buildRuntimeStylesProcessor = <T,>(\n runtimeStylesFn: RuntimeStyleProcessor<T>,\n parentRuntimeStylesFn?: RuntimeStyleProcessor<T>,\n) => {\n if (runtimeStylesFn && parentRuntimeStylesFn) {\n const combined: RuntimeStyleProcessor<T> = Object.assign(\n (\n props: T,\n classNames: Parameters<RuntimeStyleProcessor<T>>[1],\n style: React.CSSProperties,\n ) => {\n parentRuntimeStylesFn(props, classNames, style);\n runtimeStylesFn(props, classNames, style);\n },\n // the chain is dynamic if any level is dynamic\n { $dynamic: runtimeStylesFn.$dynamic || parentRuntimeStylesFn.$dynamic },\n );\n return combined;\n }\n return runtimeStylesFn || parentRuntimeStylesFn;\n};\n\n/**\n * Internal function where attrs are passed to be processed\n */\nexport type StyledInternal = <\n T extends object,\n TAttrsIn extends object = {},\n TAttrsOut extends AttrsMerged<T, TAttrsIn> = AttrsMerged<T, TAttrsIn>,\n>(\n Component: React.FunctionComponent<T> | YakComponent<T> | HtmlTags | string,\n attrs?: Attrs<T, TAttrsIn, TAttrsOut>,\n) => StyledLiteral<Substitute<T, TAttrsIn>>;\n\n/**\n * Utility type to extract the AttrsFunction from the Attrs type\n */\nexport type ExtractAttrsFunction<T> = T extends (p: any) => any ? T : never;\n","import React from \"react\";\nimport { styled as StyledFactory } from \"../styled.js\";\n\nexport const styled = new Proxy(StyledFactory, {\n get(target, TagName: keyof React.JSX.IntrinsicElements) {\n return target(TagName);\n },\n}) as typeof StyledFactory;\n","import type { globalStyle as globalStyleInternal } from \"../globalStyle.js\";\n\nexport type { GlobalStyleInterpolation } from \"../globalStyle.js\";\n\n/**\n * Test-friendly mock of `globalStyle`.\n *\n * `globalStyle` has no runtime behaviour — the SWC plugin extracts its CSS at\n * build time and replaces the call with a no-op. The mock mirrors that: it does\n * nothing so yak files can be imported in Jest/Vitest without the compiler.\n */\nexport const globalStyle: typeof globalStyleInternal = (_styles, ..._values) => {\n // no-op in the mock\n};\n"],"mappings":"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"}