@yak/react 0.0.0-stage → 10.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +102 -2
  3. package/dist/context/baseContext.cjs +9 -0
  4. package/dist/context/baseContext.cjs.map +1 -0
  5. package/dist/context/baseContext.d.cts +6 -0
  6. package/dist/context/baseContext.d.ts +6 -0
  7. package/dist/context/baseContext.js +8 -0
  8. package/dist/context/baseContext.js.map +1 -0
  9. package/dist/context/index.cjs +45 -0
  10. package/dist/context/index.cjs.map +1 -0
  11. package/dist/context/index.d.cts +21 -0
  12. package/dist/context/index.d.ts +21 -0
  13. package/dist/context/index.js +15 -0
  14. package/dist/context/index.js.map +1 -0
  15. package/dist/context/index.server.cjs +47 -0
  16. package/dist/context/index.server.cjs.map +1 -0
  17. package/dist/context/index.server.d.cts +10 -0
  18. package/dist/context/index.server.d.ts +10 -0
  19. package/dist/context/index.server.js +17 -0
  20. package/dist/context/index.server.js.map +1 -0
  21. package/dist/cross-file-resolver/index.d.ts +199 -0
  22. package/dist/cross-file-resolver/index.js +535 -0
  23. package/dist/cross-file-resolver/index.js.map +1 -0
  24. package/dist/index.cjs +2 -0
  25. package/dist/index.cjs.map +1 -0
  26. package/dist/index.d.cts +320 -0
  27. package/dist/index.d.ts +320 -0
  28. package/dist/index.js +2 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/internal.cjs +544 -0
  31. package/dist/internal.cjs.map +1 -0
  32. package/dist/internal.d.cts +452 -0
  33. package/dist/internal.d.ts +452 -0
  34. package/dist/internal.js +363 -0
  35. package/dist/internal.js.map +1 -0
  36. package/dist/isolated-source-eval/index.d.ts +30 -0
  37. package/dist/isolated-source-eval/index.js +317 -0
  38. package/dist/isolated-source-eval/index.js.map +1 -0
  39. package/dist/isolated-source-eval/worker.js +59 -0
  40. package/dist/isolated-source-eval/worker.js.map +1 -0
  41. package/dist/jsx-dev-runtime.cjs +2 -0
  42. package/dist/jsx-dev-runtime.cjs.map +1 -0
  43. package/dist/jsx-dev-runtime.d.cts +7 -0
  44. package/dist/jsx-dev-runtime.d.ts +7 -0
  45. package/dist/jsx-dev-runtime.js +2 -0
  46. package/dist/jsx-dev-runtime.js.map +1 -0
  47. package/dist/jsx-runtime.cjs +2 -0
  48. package/dist/jsx-runtime.cjs.map +1 -0
  49. package/dist/jsx-runtime.d.cts +38 -0
  50. package/dist/jsx-runtime.d.ts +38 -0
  51. package/dist/jsx-runtime.js +2 -0
  52. package/dist/jsx-runtime.js.map +1 -0
  53. package/dist/loaders/turbo-loader.cjs +803 -0
  54. package/dist/loaders/turbo-loader.cjs.map +1 -0
  55. package/dist/loaders/turbo-loader.d.cts +15 -0
  56. package/dist/loaders/vite-plugin.d.ts +111 -0
  57. package/dist/loaders/vite-plugin.js +878 -0
  58. package/dist/loaders/vite-plugin.js.map +1 -0
  59. package/dist/loaders/webpack-loader.cjs +697 -0
  60. package/dist/loaders/webpack-loader.cjs.map +1 -0
  61. package/dist/loaders/webpack-loader.d.cts +12 -0
  62. package/dist/rsbuild/index.d.ts +29 -0
  63. package/dist/rsbuild/index.js +52 -0
  64. package/dist/rsbuild/index.js.map +1 -0
  65. package/dist/static/chunk-DK3Fl9T5.js +1 -0
  66. package/dist/static/index.cjs +2 -0
  67. package/dist/static/index.cjs.map +1 -0
  68. package/dist/static/index.d.cts +28 -0
  69. package/dist/static/index.d.ts +28 -0
  70. package/dist/static/index.js +2 -0
  71. package/dist/static/index.js.map +1 -0
  72. package/dist/withYak/index.cjs +208 -0
  73. package/dist/withYak/index.cjs.map +1 -0
  74. package/dist/withYak/index.d.cts +121 -0
  75. package/dist/withYak/index.d.ts +121 -0
  76. package/dist/withYak/index.js +177 -0
  77. package/dist/withYak/index.js.map +1 -0
  78. package/loaders/lib/resolveCrossFileSelectors.ts +162 -0
  79. package/loaders/turbo-evaluator.ts +134 -0
  80. package/loaders/turbo-loader.ts +180 -0
  81. package/loaders/vite-plugin.ts +28 -0
  82. package/loaders/webpack-loader.ts +44 -0
  83. package/package.json +214 -3
  84. package/rsbuild/index.ts +92 -0
  85. package/runtime/__tests__/atoms.test.tsx +48 -0
  86. package/runtime/__tests__/attrs.test.tsx +490 -0
  87. package/runtime/__tests__/cssLiteral.test.tsx +503 -0
  88. package/runtime/__tests__/cssProp.test.tsx +392 -0
  89. package/runtime/__tests__/cssPropTest.tsx +227 -0
  90. package/runtime/__tests__/foldedJsxParity.test.tsx +117 -0
  91. package/runtime/__tests__/styled.test.tsx +653 -0
  92. package/runtime/__tests__/tsconfig.json +18 -0
  93. package/runtime/__tests__/typeTest.tsx +374 -0
  94. package/runtime/atoms.tsx +36 -0
  95. package/runtime/context/README.md +84 -0
  96. package/runtime/context/baseContext.tsx +5 -0
  97. package/runtime/context/index.server.tsx +22 -0
  98. package/runtime/context/index.tsx +36 -0
  99. package/runtime/cssLiteral.tsx +214 -0
  100. package/runtime/globalStyle.tsx +54 -0
  101. package/runtime/index.ts +37 -0
  102. package/runtime/internal.ts +42 -0
  103. package/runtime/internals/mergeClassNames.ts +23 -0
  104. package/runtime/internals/mergeCssProp.ts +69 -0
  105. package/runtime/internals/propMarkers.ts +20 -0
  106. package/runtime/internals/unitPostFix.ts +34 -0
  107. package/runtime/jsx-dev-runtime.ts +6 -0
  108. package/runtime/jsx-runtime.ts +48 -0
  109. package/runtime/keyframes.tsx +30 -0
  110. package/runtime/mocks/cssLiteral.ts +74 -0
  111. package/runtime/mocks/globalStyle.ts +14 -0
  112. package/runtime/mocks/keyframes.ts +29 -0
  113. package/runtime/mocks/styled.ts +8 -0
  114. package/runtime/publicStyledApi.ts +159 -0
  115. package/runtime/styled.tsx +372 -0
  116. package/runtime/styledDom.tsx +139 -0
  117. package/withYak/allow-global-css.ts +94 -0
  118. package/withYak/index.ts +282 -0
@@ -0,0 +1,214 @@
1
+ import type { YakTheme } from "./index.ts";
2
+ import { ClassNameCollector, RuntimeStyleProcessor } from "./publicStyledApi.js";
3
+
4
+ export const yakComponentSymbol = Symbol("yak");
5
+
6
+ /**
7
+ * String-backed ClassNameCollector used by the render path
8
+ *
9
+ * `add` is a plain string append and does not deduplicate, so the collector is
10
+ * a multiset - the same class may appear twice, e.g. `atoms("a b", "a")` → `"a b a"`.
11
+ * `has`/`delete` cover the rare path where a runtime function inspects or
12
+ * removes classes; `delete` removes every occurrence
13
+ */
14
+ export class ClassNames implements ClassNameCollector {
15
+ value: string;
16
+ constructor(initial?: string) {
17
+ this.value = initial || "";
18
+ }
19
+ add(className: string) {
20
+ this.value += (this.value && " ") + className;
21
+ }
22
+ has(className: string) {
23
+ return (" " + this.value + " ").includes(" " + className + " ");
24
+ }
25
+ delete(className: string) {
26
+ if (this.has(className)) {
27
+ this.value = this.value
28
+ .split(" ")
29
+ .filter((existing) => existing !== className)
30
+ .join(" ");
31
+ }
32
+ }
33
+ }
34
+
35
+ export type ComponentStyles<TProps> = (props: TProps) => {
36
+ className: string;
37
+ style?: {
38
+ [key: string]: string;
39
+ };
40
+ };
41
+
42
+ export type CSSInterpolation<TProps> =
43
+ | string
44
+ | number
45
+ | undefined
46
+ | null
47
+ | false
48
+ | ComponentStyles<TProps>
49
+ | {
50
+ // type only identifier to allow targeting components
51
+ // e.g. styled.svg`${Button}:hover & { fill: red; }`
52
+ [yakComponentSymbol]: any;
53
+ }
54
+ | ((props: TProps) => CSSInterpolation<TProps>);
55
+
56
+ type CSSStyles<TProps = {}> = {
57
+ style: { [key: string]: string | ((props: TProps) => string) };
58
+ };
59
+
60
+ type CSSFunction = <TProps = {}>(
61
+ styles: TemplateStringsArray,
62
+ ...values: CSSInterpolation<TProps & { theme: YakTheme }>[]
63
+ ) => ComponentStyles<TProps>;
64
+
65
+ export type NestedRuntimeStyleProcessor = (
66
+ props: unknown,
67
+ classNames: ClassNameCollector,
68
+ style: React.CSSProperties,
69
+ ) =>
70
+ | {
71
+ className?: string;
72
+ style?: React.CSSProperties;
73
+ }
74
+ | void
75
+ | NestedRuntimeStyleProcessor;
76
+
77
+ /**
78
+ * css() runtime factory of css``
79
+ *
80
+ * /!\ @yak/react transpiles css`` and styled``
81
+ *
82
+ * This changes the typings of the css`` and styled`` functions.
83
+ * During development the user of @yak/react wants to work with the
84
+ * typings BEFORE compilation.
85
+ *
86
+ * Therefore this is only an internal function only and it must be cast to any
87
+ * before exported to the user.
88
+ *
89
+ * The internal functioning of css`` is to return a single callback function that runs all functions
90
+ * (or creates new ones if needed) that are passed as arguments. These functions receive the props, classNames, and style object as arguments
91
+ * and operate directly on the classNames and style objects.
92
+ */
93
+ export function css<TProps>(
94
+ styles: TemplateStringsArray,
95
+ ...values: CSSInterpolation<NoInfer<TProps> & { theme: YakTheme }>[]
96
+ ): ComponentStyles<TProps>;
97
+ export function css<TProps>(...args: Array<any>): RuntimeStyleProcessor<TProps> {
98
+ // Normally this could be an array of strings passed, but as we transpile the usage of css`` ourselves, we control the arguments
99
+ // and ensure that only the first argument is a string (class name of the non-dynamic styles)
100
+ let className: string | undefined;
101
+ const dynamicCssFunctions: NestedRuntimeStyleProcessor[] = [];
102
+ for (const arg of args as Array<string | CSSFunction | CSSStyles<any>>) {
103
+ // A CSS-module class name which got auto generated during build from static css
104
+ // e.g. css`color: red;`
105
+ // compiled -> css("yak31e4")
106
+ if (typeof arg === "string") {
107
+ className = arg;
108
+ }
109
+ // Dynamic CSS e.g.
110
+ // css`${props => props.active && css`color: red;`}`
111
+ // compiled -> css((props: { active: boolean }) => props.active && css("yak31e4"))
112
+ else if (typeof arg === "function") {
113
+ dynamicCssFunctions.push(arg as unknown as NestedRuntimeStyleProcessor);
114
+ }
115
+ // Dynamic CSS with css variables e.g.
116
+ // css`transform: translate(${props => props.x}, ${props => props.y});`
117
+ // compiled -> css("yak31e4", { style: { "--yakVarX": props => props.x }, "--yakVarY": props => props.y }})
118
+ else if (typeof arg === "object" && "style" in arg) {
119
+ dynamicCssFunctions.push((props, _, style) => {
120
+ for (const key in arg.style) {
121
+ const value = arg.style[key];
122
+ if (typeof value === "function") {
123
+ // @ts-expect-error CSSProperties don't allow css variables
124
+ style[key] = String(
125
+ // The value for a css value can be a theme dependent function e.g.:
126
+ // const borderColor = (props: { theme: { mode: "dark" | "light" } }) => props.theme === "dark" ? "black" : "white";
127
+ // css`border-color: ${borderColor};`
128
+ // Therefore the value has to be extracted recursively
129
+ recursivePropExecution(props, value),
130
+ );
131
+ } else {
132
+ // @ts-expect-error CSSProperties don't allow css variables
133
+ style[key] = String(value);
134
+ }
135
+ }
136
+ });
137
+ }
138
+ }
139
+
140
+ // Non Dynamic CSS
141
+ // This is just an optimization for the common case where there are no dynamic css functions
142
+ // `$dynamic: false` lets the styled runtime skip theme lookup and
143
+ // style-object allocation entirely for static components
144
+ if (dynamicCssFunctions.length === 0) {
145
+ return Object.assign(
146
+ (_: unknown, classNames: ClassNameCollector) => {
147
+ if (className) {
148
+ classNames.add(className);
149
+ }
150
+ },
151
+ { $dynamic: false },
152
+ );
153
+ }
154
+
155
+ return Object.assign(
156
+ (props: TProps, classNames: ClassNameCollector, allStyles: React.CSSProperties) => {
157
+ if (className) {
158
+ classNames.add(className);
159
+ }
160
+ for (let i = 0; i < dynamicCssFunctions.length; i++) {
161
+ unwrapProps(props, dynamicCssFunctions[i], classNames, allStyles);
162
+ }
163
+ },
164
+ { $dynamic: true },
165
+ );
166
+ }
167
+
168
+ // Dynamic CSS with runtime logic
169
+ const unwrapProps = (
170
+ props: unknown,
171
+ fn: NestedRuntimeStyleProcessor,
172
+ classNames: ClassNameCollector,
173
+ style: React.CSSProperties,
174
+ ) => {
175
+ let result = fn(props, classNames, style);
176
+ while (result) {
177
+ if (typeof result === "function") {
178
+ result = result(props, classNames, style);
179
+ continue;
180
+ } else if (typeof result === "object") {
181
+ if ("className" in result && result.className) {
182
+ classNames.add(result.className);
183
+ }
184
+ if ("style" in result && result.style) {
185
+ for (const key in result.style) {
186
+ // This is hard for typescript to infer
187
+ style[key as keyof React.CSSProperties] = result.style[
188
+ key as keyof React.CSSProperties
189
+ ] as any;
190
+ }
191
+ }
192
+ }
193
+ break;
194
+ }
195
+ };
196
+
197
+ const recursivePropExecution = (props: unknown, fn: (props: unknown) => any): string | number => {
198
+ const result = fn(props);
199
+ if (typeof result === "function") {
200
+ return recursivePropExecution(props, result);
201
+ }
202
+ // the `process.env` lookup is a real per-call cost for unbundled Node
203
+ // consumers, so it must stay behind the typeof guards on the invalid path
204
+ if (typeof result !== "string" && typeof result !== "number" && !(result instanceof String)) {
205
+ if (process.env.NODE_ENV === "development") {
206
+ throw new Error(
207
+ `Dynamic CSS functions must return a string or number but returned ${JSON.stringify(
208
+ result,
209
+ )}\n\nDynamic CSS function: ${fn.toString()}\n`,
210
+ );
211
+ }
212
+ }
213
+ return result;
214
+ };
@@ -0,0 +1,54 @@
1
+ import type { ComponentStyles } from "./cssLiteral.js";
2
+ import type { YakComponent } from "./publicStyledApi.js";
3
+
4
+ /**
5
+ * Values that may be interpolated into a `globalStyle` template.
6
+ *
7
+ * Only build-time values are allowed — constants, `keyframes` animation names,
8
+ * static `css` mixins and styled-component selectors. Runtime functions
9
+ * (`${(props) => ...}`) are intentionally excluded: a global rule has no element
10
+ * to attach a CSS variable to. Declare a CSS custom property instead and toggle
11
+ * it via an attribute/class on the root element.
12
+ */
13
+ export type GlobalStyleInterpolation = string | number | ComponentStyles<{}> | YakComponent<any>;
14
+
15
+ /**
16
+ * Declares global, unscoped styles that ride the same zero-runtime extraction
17
+ * pipeline as `styled` and `keyframes`.
18
+ *
19
+ * Global styles are **part of the stylesheet, not part of the render tree**.
20
+ * They apply exactly when the module declaring them is included in the bundle —
21
+ * typically by importing it from a layout or entry point. They cannot be
22
+ * conditionally mounted; express conditions in CSS (`@media`, `@supports`,
23
+ * `:root[data-theme]`, `:has()`) or through CSS custom properties.
24
+ *
25
+ * @usage
26
+ *
27
+ * ```tsx
28
+ * import { globalStyle, keyframes } from "@yak/react";
29
+ *
30
+ * const fadeIn = keyframes`
31
+ * from { opacity: 0; }
32
+ * `;
33
+ *
34
+ * globalStyle`
35
+ * :root {
36
+ * --spacing: 4px;
37
+ * }
38
+ *
39
+ * body {
40
+ * margin: 0;
41
+ * }
42
+ *
43
+ * ::view-transition-new(root) {
44
+ * animation: ${fadeIn} 200ms ease;
45
+ * }
46
+ * `;
47
+ * ```
48
+ */
49
+ export const globalStyle = (
50
+ _styles: TemplateStringsArray,
51
+ ..._values: Array<GlobalStyleInterpolation>
52
+ ): void => {
53
+ return undefined;
54
+ };
@@ -0,0 +1,37 @@
1
+ /**
2
+ * This file contains the typings for the public API for @yak/react and testing mocks
3
+ *
4
+ * IMPORTANT: In production builds, imports to this file should be replaced by the Babel plugin.
5
+ * If you're seeing this code in a production environment, your build process may not be configured correctly.
6
+ *
7
+ * Purpose:
8
+ * 1. Provide a test-friendly version of the @yak/react API
9
+ * 2. Offer type definitions for the public API
10
+ *
11
+ * Usage in tests:
12
+ * - Import from "@yak/react" as usual in your test files
13
+ * - These mock implementations will be used instead of the actual runtime
14
+ *
15
+ * Warning for production:
16
+ * - If these exports are used in a production build, styles will not be applied correctly
17
+ * - Ensure your build process is configured to use the @yak/react SWC plugin
18
+ *
19
+ * For maintainers:
20
+ * - Keep this API surface in sync with the actual implementation in @yak/react/internal
21
+ * - Ensure mock implementations here are suitable for testing purposes
22
+ */
23
+
24
+ // the following export is not relative as "@yak/react/context"
25
+ // links to one file for react server components and
26
+ // to another file for classic react components
27
+ export { useTheme, YakThemeProvider } from "@yak/react/context";
28
+ export type { YakTheme } from "./context/index.tsx";
29
+
30
+ export type { GenericYakComponentOf, YakComponent } from "./publicStyledApi.ts";
31
+
32
+ export { atoms } from "./atoms.js";
33
+ export { css } from "./mocks/cssLiteral.js";
34
+ export { keyframes } from "./mocks/keyframes.js";
35
+ export { styled } from "./mocks/styled.js";
36
+ export { globalStyle } from "./mocks/globalStyle.js";
37
+ export type { GlobalStyleInterpolation } from "./mocks/globalStyle.js";
@@ -0,0 +1,42 @@
1
+ /**
2
+ * IMPORTANT: This file contains the internal implementation of @yak/react's core APIs.
3
+ *
4
+ * Purpose:
5
+ * - Provides the actual runtime implementations for styled, css, keyframes, etc.
6
+ * - Referenced only by the compiled code "@yak/react/internal"
7
+ *
8
+ * Usage:
9
+ * - DO NOT import from this file directly in your application code.
10
+ * - Always use `import { ... } from "@yak/react"` in your source files.
11
+ * - The Babel plugin will automatically transform those imports to use this internal module.
12
+ *
13
+ * Why this exists:
14
+ * 1. Allows for cleaner separation between the public API and internal implementation
15
+ * 2. Enables better typing for both pre-compilation (user code) and post-compilation scenarios
16
+ * 3. Easier testing and snapshot comparisons without hashes (in index.ts)
17
+ * 4. Makes @yak/react work out-of-the-box with testing frameworks like Jest and Vitest
18
+ *
19
+ * Note for maintainers:
20
+ * - Ensure that types from this file are not published to avoid exposing internal APIs.
21
+ *
22
+ * @internal This module is not intended for direct usage and may change without notice.
23
+ */
24
+
25
+ export { css } from "./cssLiteral.js";
26
+ export { styled } from "./styled.js";
27
+ export { atoms } from "./atoms.js";
28
+ export { keyframes } from "./keyframes.js";
29
+ export { globalStyle } from "./globalStyle.js";
30
+
31
+ // the following export is not relative as "@yak/react/context"
32
+ // links to one file for react server components and
33
+ // to another file for classic react components
34
+ export { useTheme, YakThemeProvider } from "@yak/react/context";
35
+
36
+ // runtime internals (helpers which get injected by the compiler)
37
+ export { unitPostFix as __yak_unitPostFix } from "./internals/unitPostFix.js";
38
+ export { mergeCssProp as __yak_mergeCssProp } from "./internals/mergeCssProp.js";
39
+ export { mergeClassNames as __yak_mergeClassNames } from "./internals/mergeClassNames.js";
40
+
41
+ // export shorthand for DOM styled components (e.g. for styled.div)
42
+ export * from "./styledDom.js";
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Merges two optional class name values with a space.
3
+ *
4
+ * Used by the styled runtime to combine incoming and generated class names,
5
+ * and injected by the compiler (as `__yak_mergeClassNames`) when it replaces
6
+ * a JSX usage of a fully static styled component with a plain DOM element:
7
+ * ```tsx
8
+ * const Card = styled.div`color: red;`;
9
+ * <Card className={active && "active"} />
10
+ * ```
11
+ * becomes
12
+ * ```tsx
13
+ * <div className={__yak_mergeClassNames("yX", active && "active")} />
14
+ * ```
15
+ */
16
+ export const mergeClassNames = (
17
+ a: string | false | null | undefined,
18
+ b: string | false | null | undefined,
19
+ ) => {
20
+ if (!a) return b || undefined;
21
+ if (!b) return a;
22
+ return a + " " + b;
23
+ };
@@ -0,0 +1,69 @@
1
+ import { ClassNames } from "../cssLiteral.js";
2
+ import { RuntimeStyleProcessor } from "../publicStyledApi.js";
3
+
4
+ /**
5
+ * This is an internal helper function to merge relevant props of a native element with a css prop.
6
+ * It's automatically added when using the `css` prop in a JSX element.
7
+ * e.g.:
8
+ * ```tsx
9
+ * <p
10
+ * className="foo"
11
+ * css={css`
12
+ * color: green;
13
+ * `}
14
+ * {...{ style: { padding: "30px" }}}
15
+ * />
16
+ * ```
17
+ * compiles to
18
+ * ```tsx
19
+ * <p {...__yak_mergeCssProp(css("yakCss1"), { className: "foo" }, { style: { padding: "30px" } })} />
20
+ * ```
21
+ * The css value comes first, then every merged source in JSX order, so a
22
+ * later source wins as it would in one object literal.
23
+ */
24
+ export const mergeCssProp = (
25
+ cssProp: RuntimeStyleProcessor<unknown> | false | null | undefined,
26
+ ...sources: (Record<string, unknown> | null | undefined)[]
27
+ ) => {
28
+ // React props are plain values, so the sources are merged up front
29
+ const result: Record<string, unknown> & {
30
+ className?: string;
31
+ style?: Record<string, string>;
32
+ } = Object.assign({}, ...sources);
33
+
34
+ const classNames = new ClassNames(result.className);
35
+ const existingStyle = result.style;
36
+ const style = existingStyle ? { ...existingStyle } : {};
37
+
38
+ // only a style function applies styles. A falsy css prop applies none,
39
+ // e.g. `css={on && css`...`}` with `on` false
40
+ if (typeof cssProp === "function") {
41
+ cssProp({}, classNames, style);
42
+ } else if (cssProp) {
43
+ // The swc plugin rejects a value which can not apply styles at build time,
44
+ // so this only runs where it can not see one during build time.
45
+ if (process.env.NODE_ENV === "development") {
46
+ const received: unknown = cssProp;
47
+ throw new Error(
48
+ `The css prop only applies styles written in place, but received ${
49
+ Array.isArray(received) ? "an array" : `a value of type ${typeof received}`
50
+ }.\n\nCombine several styles in one template instead of an array: css={css\`\${first} \${second}\`}\nWrite declarations in a template instead of an object: css={css\`color: red;\`}`,
51
+ );
52
+ }
53
+ }
54
+
55
+ // Forward all other props (onClick, aria-*, id, …) untouched and only
56
+ // override className/style with the merged result
57
+ if (Object.keys(style).length > 0) {
58
+ result.style = style;
59
+ } else {
60
+ delete result.style;
61
+ }
62
+ if (classNames.value) {
63
+ result.className = classNames.value;
64
+ } else {
65
+ delete result.className;
66
+ }
67
+
68
+ return result;
69
+ };
@@ -0,0 +1,20 @@
1
+ /** Internal markers used by the render path */
2
+
3
+ /**
4
+ * Set on props once the attrs functions have been folded in, so a nested yak
5
+ * wrapper further out the chain does not merge the same attrs twice
6
+ */
7
+ export const ATTRS_MERGED = "$__a" as const;
8
+
9
+ /**
10
+ * Set on props once the runtime style processor has run, so an outer yak
11
+ * component that receives already-processed props skips the collector entirely
12
+ */
13
+ export const RUNTIME_STYLES_DONE = "$__r" as const;
14
+
15
+ /**
16
+ * Carries the constant `.attrs({...})` object on the merged attrs function,
17
+ * marking it theme-independent so the fast render path can apply it without
18
+ * executing anything. Lives on the function, never on props
19
+ */
20
+ export const STATIC_ATTRS = "$sa" as const;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Internal helper called by transformed code - Do not use directly
3
+ *
4
+ * Takes a function and a css unit and returns the result of the function concatenated with the unit
5
+ *
6
+ * ```tsx
7
+ * import { styled } from "@yak/react";
8
+ *
9
+ * const Button = styled.button<{ $width?: boolean }>`
10
+ * width: ${({ $width }) => $width}px;
11
+ * `;
12
+ * ```
13
+ *
14
+ * Which will be transformed to:
15
+ * ```tsx
16
+ * import { styled } from "@yak/react/internals";
17
+ *
18
+ * const Button = styled.button<{ $width?: boolean }>(
19
+ * "button", {
20
+ * width: unitPostFix({ $width }) => $width, "px")
21
+ * });
22
+ */
23
+ export const unitPostFix = (arg: unknown, unit: string) => {
24
+ switch (typeof arg) {
25
+ case "function":
26
+ return (props: any) => unitPostFix(arg(props), unit);
27
+ case "number":
28
+ case "string":
29
+ return `${arg}${unit}`;
30
+ // Ignore falsy values
31
+ default:
32
+ return undefined;
33
+ }
34
+ };
@@ -0,0 +1,6 @@
1
+ import ReactJSXRuntimeDev from "react/jsx-dev-runtime";
2
+
3
+ const Fragment = ReactJSXRuntimeDev.Fragment;
4
+ const jsxDEV = ReactJSXRuntimeDev.jsxDEV;
5
+
6
+ export { Fragment, jsxDEV };
@@ -0,0 +1,48 @@
1
+ import ReactJSXRuntime from "react/jsx-runtime";
2
+ import type { ComponentStyles } from "./mocks/cssLiteral.js";
3
+
4
+ /**
5
+ * A falsy css prop applies no styles, which keeps conditional shapes like
6
+ * `css={on && css`...`}` or `css={on ? css`...` : undefined}` well typed
7
+ */
8
+ type CSSProp = ComponentStyles<Record<keyof any, never>> | false | null | undefined;
9
+
10
+ // Only return the css prop if the "className" and "style" properties are present
11
+ // This was inspired from emotion
12
+ // https://github.com/emotion-js/emotion/blob/cce67ec6b2fc94261028b4f4778aae8c3d6c5fd6/packages/react/src/jsx-namespace.ts#L9C6-L9C28
13
+ type WithConditionalCSSProp<P> = "className" | "style" extends keyof P
14
+ ? string extends P["className" & keyof P]
15
+ ? Record<string, any> extends P["style" & keyof P]
16
+ ? { css?: CSSProp }
17
+ : {}
18
+ : {}
19
+ : {};
20
+
21
+ const Fragment = ReactJSXRuntime.Fragment;
22
+ const jsx = ReactJSXRuntime.jsx;
23
+ const jsxs = ReactJSXRuntime.jsxs;
24
+
25
+ export declare namespace YakJSX {
26
+ export type Element = React.JSX.Element;
27
+ export type ElementType = React.JSX.ElementType;
28
+ export type ElementClass = React.JSX.ElementClass;
29
+ export type ElementAttributesProperty = React.JSX.ElementAttributesProperty;
30
+ export type ElementChildrenAttribute = React.JSX.ElementChildrenAttribute;
31
+
32
+ // Add the CSS prop to all components that can receive "className" and "style"
33
+ export type LibraryManagedAttributes<C, P> = P extends unknown
34
+ ? WithConditionalCSSProp<P> & React.JSX.LibraryManagedAttributes<C, P>
35
+ : never;
36
+
37
+ export type IntrinsicAttributes = React.JSX.IntrinsicAttributes;
38
+ export type IntrinsicClassAttributes<T> = React.JSX.IntrinsicClassAttributes<T>;
39
+
40
+ export type IntrinsicElements = {
41
+ [K in keyof React.JSX.IntrinsicElements]: React.JSX.IntrinsicElements[K] & {
42
+ // Add the CSS prop to all native elements e.g. "div" or "span"
43
+ css?: CSSProp;
44
+ };
45
+ };
46
+ }
47
+
48
+ export { Fragment, jsx, jsxs, type YakJSX as JSX };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Allows to use CSS keyframe animations in a styled or css block
3
+ *
4
+ * @usage
5
+ *
6
+ * ```tsx
7
+ * import { styled, keyframes } from "@yak/react";
8
+ *
9
+ * const rotate = keyframes`
10
+ * from {
11
+ * transform: rotate(0deg);
12
+ * }
13
+ * to {
14
+ * transform: rotate(360deg);
15
+ * }
16
+ * `;
17
+ *
18
+ * const Spinner = styled.div`
19
+ * animation: ${rotate} 1s linear infinite;
20
+ * `;
21
+ * ```
22
+ */
23
+ export const keyframes = <T extends (string | number | bigint)[] = never>(
24
+ styles: TemplateStringsArray,
25
+ ..._dynamic: T
26
+ ): string => {
27
+ // during compilation all args of keyframe are compiled
28
+ // to a string which references the animation name
29
+ return styles as any as string;
30
+ };
@@ -0,0 +1,74 @@
1
+ import type { css as cssInternal, NestedRuntimeStyleProcessor } from "../cssLiteral.js";
2
+
3
+ export type { ComponentStyles } from "../cssLiteral.js";
4
+
5
+ /**
6
+ * Allows to use CSS styles in a styled or css block
7
+ *
8
+ * e.g.
9
+ *
10
+ * ```tsx
11
+ * const Component = styled.div`
12
+ * color: black;
13
+ * ${({$active}) => $active && css`color: red;`}
14
+ * `;
15
+ * ```
16
+ */
17
+ export const css: typeof cssInternal = (styles: TemplateStringsArray, ...args: unknown[]) => {
18
+ // When called in yak files as a template tag (without SWC transformation),
19
+ // return { __yak: rawCss } so the cross-file resolver can
20
+ // extract the mixin value from evaluated .yak files.
21
+ if (Array.isArray(styles) && "raw" in styles) {
22
+ let rawCss = styles[0];
23
+ for (let i = 0; i < args.length; i++) {
24
+ const interpolation = args[i];
25
+ rawCss +=
26
+ interpolation && typeof interpolation === "object" && "__yak" in interpolation
27
+ ? (interpolation as { __yak: string }).__yak
28
+ : String(interpolation);
29
+ rawCss += styles[i + 1];
30
+ }
31
+ return { __yak: rawCss } as any;
32
+ }
33
+
34
+ const dynamicCssFunctions: NestedRuntimeStyleProcessor[] = [];
35
+ for (const arg of args as Array<string | Function | object>) {
36
+ // Dynamic CSS e.g.
37
+ // css`${props => props.active && css`color: red;`}`
38
+ // compiled -> css((props: { active: boolean }) => props.active && css("yak31e4"))
39
+ if (typeof arg === "function") {
40
+ dynamicCssFunctions.push(arg as unknown as NestedRuntimeStyleProcessor);
41
+ }
42
+ }
43
+ if (dynamicCssFunctions.length === 0) {
44
+ return {
45
+ className: "",
46
+ style: undefined,
47
+ };
48
+ }
49
+ return ((props: unknown) => {
50
+ for (let i = 0; i < dynamicCssFunctions.length; i++) {
51
+ // run the dynamic expressions and ignore the return value
52
+ // the execution is important to ensure that the user code is executed
53
+ // the same way as in the real runtime
54
+ executeDynamicExpressionRecursively(props, dynamicCssFunctions[i]);
55
+ }
56
+ return {
57
+ className: "",
58
+ style: undefined,
59
+ };
60
+ }) as any;
61
+ };
62
+
63
+ function executeDynamicExpressionRecursively(
64
+ props: unknown,
65
+ expression: NestedRuntimeStyleProcessor,
66
+ ) {
67
+ const classNames = new Set<string>();
68
+ const style = {};
69
+ let result = expression(props, classNames, style);
70
+ while (typeof result === "function") {
71
+ result = result(props, classNames, style);
72
+ }
73
+ return result;
74
+ }
@@ -0,0 +1,14 @@
1
+ import type { globalStyle as globalStyleInternal } from "../globalStyle.js";
2
+
3
+ export type { GlobalStyleInterpolation } from "../globalStyle.js";
4
+
5
+ /**
6
+ * Test-friendly mock of `globalStyle`.
7
+ *
8
+ * `globalStyle` has no runtime behaviour — the SWC plugin extracts its CSS at
9
+ * build time and replaces the call with a no-op. The mock mirrors that: it does
10
+ * nothing so yak files can be imported in Jest/Vitest without the compiler.
11
+ */
12
+ export const globalStyle: typeof globalStyleInternal = (_styles, ..._values) => {
13
+ // no-op in the mock
14
+ };