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

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 (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +114 -2
  3. package/dist/context/baseContext.d.ts +5 -0
  4. package/dist/context/baseContext.js +8 -0
  5. package/dist/context/baseContext.js.map +1 -0
  6. package/dist/context/index.d.ts +20 -0
  7. package/dist/context/index.js +15 -0
  8. package/dist/context/index.js.map +1 -0
  9. package/dist/context/index.server.d.ts +9 -0
  10. package/dist/context/index.server.js +17 -0
  11. package/dist/context/index.server.js.map +1 -0
  12. package/dist/cross-file-resolver/index.d.ts +199 -0
  13. package/dist/cross-file-resolver/index.js +569 -0
  14. package/dist/cross-file-resolver/index.js.map +1 -0
  15. package/dist/index.d.ts +320 -0
  16. package/dist/index.js +2 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/internal.d.ts +452 -0
  19. package/dist/internal.js +363 -0
  20. package/dist/internal.js.map +1 -0
  21. package/dist/isolated-source-eval/index.d.ts +30 -0
  22. package/dist/isolated-source-eval/index.js +317 -0
  23. package/dist/isolated-source-eval/index.js.map +1 -0
  24. package/dist/isolated-source-eval/worker.js +59 -0
  25. package/dist/isolated-source-eval/worker.js.map +1 -0
  26. package/dist/jsx-dev-runtime.d.ts +7 -0
  27. package/dist/jsx-dev-runtime.js +2 -0
  28. package/dist/jsx-dev-runtime.js.map +1 -0
  29. package/dist/jsx-runtime.d.ts +38 -0
  30. package/dist/jsx-runtime.js +2 -0
  31. package/dist/jsx-runtime.js.map +1 -0
  32. package/dist/loaders/turbo-loader.d.ts +15 -0
  33. package/dist/loaders/turbo-loader.js +816 -0
  34. package/dist/loaders/turbo-loader.js.map +1 -0
  35. package/dist/loaders/vite-plugin.d.ts +103 -0
  36. package/dist/loaders/vite-plugin.js +885 -0
  37. package/dist/loaders/vite-plugin.js.map +1 -0
  38. package/dist/loaders/webpack-loader.d.ts +12 -0
  39. package/dist/loaders/webpack-loader.js +710 -0
  40. package/dist/loaders/webpack-loader.js.map +1 -0
  41. package/dist/rsbuild/index.d.ts +29 -0
  42. package/dist/rsbuild/index.js +51 -0
  43. package/dist/rsbuild/index.js.map +1 -0
  44. package/dist/static/chunk-DK3Fl9T5.js +1 -0
  45. package/dist/static/index.d.ts +28 -0
  46. package/dist/static/index.js +2 -0
  47. package/dist/static/index.js.map +1 -0
  48. package/dist/withYak/index.d.ts +112 -0
  49. package/dist/withYak/index.js +171 -0
  50. package/dist/withYak/index.js.map +1 -0
  51. package/loaders/lib/resolveCrossFileSelectors.ts +161 -0
  52. package/loaders/turbo-evaluator.ts +134 -0
  53. package/loaders/turbo-loader.ts +184 -0
  54. package/loaders/vite-plugin.ts +28 -0
  55. package/loaders/webpack-loader.ts +41 -0
  56. package/package.json +155 -3
  57. package/rsbuild/index.ts +91 -0
  58. package/runtime/__tests__/atoms.test.tsx +48 -0
  59. package/runtime/__tests__/attrs.test.tsx +490 -0
  60. package/runtime/__tests__/cssLiteral.test.tsx +503 -0
  61. package/runtime/__tests__/cssProp.test.tsx +392 -0
  62. package/runtime/__tests__/cssPropTest.tsx +227 -0
  63. package/runtime/__tests__/foldedJsxParity.test.tsx +117 -0
  64. package/runtime/__tests__/styled.test.tsx +653 -0
  65. package/runtime/__tests__/tsconfig.json +18 -0
  66. package/runtime/__tests__/typeTest.tsx +374 -0
  67. package/runtime/atoms.tsx +36 -0
  68. package/runtime/context/README.md +84 -0
  69. package/runtime/context/baseContext.tsx +5 -0
  70. package/runtime/context/index.server.tsx +22 -0
  71. package/runtime/context/index.tsx +36 -0
  72. package/runtime/cssLiteral.tsx +214 -0
  73. package/runtime/globalStyle.tsx +54 -0
  74. package/runtime/index.ts +37 -0
  75. package/runtime/internal.ts +42 -0
  76. package/runtime/internals/mergeClassNames.ts +23 -0
  77. package/runtime/internals/mergeCssProp.ts +69 -0
  78. package/runtime/internals/propMarkers.ts +20 -0
  79. package/runtime/internals/unitPostFix.ts +34 -0
  80. package/runtime/jsx-dev-runtime.ts +6 -0
  81. package/runtime/jsx-runtime.ts +48 -0
  82. package/runtime/keyframes.tsx +30 -0
  83. package/runtime/mocks/cssLiteral.ts +74 -0
  84. package/runtime/mocks/globalStyle.ts +14 -0
  85. package/runtime/mocks/keyframes.ts +29 -0
  86. package/runtime/mocks/styled.ts +8 -0
  87. package/runtime/publicStyledApi.ts +159 -0
  88. package/runtime/styled.tsx +372 -0
  89. package/runtime/styledDom.tsx +139 -0
  90. package/withYak/allow-global-css.ts +94 -0
  91. package/withYak/index.ts +268 -0
package/package.json CHANGED
@@ -1,6 +1,158 @@
1
1
  {
2
2
  "name": "@yak/react",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "10.0.0-rc.1",
4
+ "description": "@yak/react is a CSS-in-JS library for React: styled-components syntax with CSS extracted at build time. Works with Next.js, Vite and Rsbuild.",
5
+ "keywords": [
6
+ "css-in-js",
7
+ "next.js",
8
+ "react",
9
+ "styled-components",
10
+ "typescript"
11
+ ],
12
+ "homepage": "https://yak.js.org/",
13
+ "bugs": {
14
+ "url": "https://github.com/DigitecGalaxus/next-yak/issues"
15
+ },
16
+ "license": "MIT",
17
+ "author": {
18
+ "name": "Jan Nicklas"
19
+ },
20
+ "maintainers": [
21
+ {
22
+ "name": "Luca Schneider"
23
+ }
24
+ ],
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/DigitecGalaxus/next-yak.git"
28
+ },
29
+ "files": [
30
+ "dist",
31
+ "loaders",
32
+ "runtime",
33
+ "withYak",
34
+ "rsbuild",
35
+ "LICENSE"
36
+ ],
37
+ "type": "module",
38
+ "sideEffects": false,
39
+ "types": "./dist/",
40
+ "exports": {
41
+ ".": {
42
+ "types": "./dist/index.d.ts",
43
+ "default": "./dist/index.js"
44
+ },
45
+ "./static": {
46
+ "types": "./dist/static/index.d.ts",
47
+ "default": "./dist/static/index.js"
48
+ },
49
+ "./internal": {
50
+ "types": "./dist/internal.d.ts",
51
+ "default": "./dist/internal.js"
52
+ },
53
+ "./withYak": {
54
+ "types": "./dist/withYak/index.d.ts",
55
+ "default": "./dist/withYak/index.js"
56
+ },
57
+ "./context/baseContext": {
58
+ "types": "./dist/context/baseContext.d.ts",
59
+ "default": "./dist/context/baseContext.js"
60
+ },
61
+ "./context": {
62
+ "react-server": {
63
+ "types": "./dist/context/index.server.d.ts",
64
+ "default": "./dist/context/index.server.js"
65
+ },
66
+ "default": {
67
+ "types": "./dist/context/index.d.ts",
68
+ "default": "./dist/context/index.js"
69
+ }
70
+ },
71
+ "./jsx-runtime": {
72
+ "types": "./dist/jsx-runtime.d.ts",
73
+ "default": "./dist/jsx-runtime.js"
74
+ },
75
+ "./jsx-dev-runtime": {
76
+ "types": "./dist/jsx-dev-runtime.d.ts",
77
+ "default": "./dist/jsx-dev-runtime.js"
78
+ },
79
+ "./loaders/webpack-loader": "./dist/loaders/webpack-loader.js",
80
+ "./vite": {
81
+ "types": "./dist/loaders/vite-plugin.d.ts",
82
+ "default": "./dist/loaders/vite-plugin.js"
83
+ },
84
+ "./cross-file-resolver": {
85
+ "types": "./dist/cross-file-resolver/index.d.ts",
86
+ "default": "./dist/cross-file-resolver/index.js"
87
+ },
88
+ "./isolated-source-eval": {
89
+ "types": "./dist/isolated-source-eval/index.d.ts",
90
+ "default": "./dist/isolated-source-eval/index.js"
91
+ },
92
+ "./rsbuild": {
93
+ "types": "./dist/rsbuild/index.d.ts",
94
+ "default": "./dist/rsbuild/index.js"
95
+ }
96
+ },
97
+ "publishConfig": {
98
+ "access": "public"
99
+ },
100
+ "dependencies": {
101
+ "@babel/parser": "^8.0.7",
102
+ "@swc/core": "~1.16.18",
103
+ "@yak/swc": "10.0.0-rc.1"
104
+ },
105
+ "devDependencies": {
106
+ "@rsbuild/core": "2.2.13",
107
+ "@testing-library/react": "16.3.3",
108
+ "@types/jest": "30.0.0",
109
+ "@types/node": "26.6.5",
110
+ "@types/react": "19.3.0",
111
+ "@types/react-dom": "19.3.0",
112
+ "@types/webpack": "5.28.5",
113
+ "jsdom": "30.1.3",
114
+ "next": "16.4.2",
115
+ "react": "19.3.1",
116
+ "tsdown": "0.23.1",
117
+ "typescript": "6.0.3",
118
+ "vite": "8.3.4",
119
+ "vitest": "5.0.5",
120
+ "yak-internals": "0.0.0"
121
+ },
122
+ "peerDependencies": {
123
+ "@rsbuild/core": ">=2.0.0",
124
+ "@types/react": ">=19",
125
+ "next": ">=16.4.0",
126
+ "react": ">=19.0.0",
127
+ "vite": ">=7.0.0"
128
+ },
129
+ "peerDependenciesMeta": {
130
+ "@rsbuild/core": {
131
+ "optional": true
132
+ },
133
+ "@types/react": {
134
+ "optional": true
135
+ },
136
+ "next": {
137
+ "optional": true
138
+ },
139
+ "vite": {
140
+ "optional": true
141
+ },
142
+ "react": {
143
+ "optional": true
144
+ }
145
+ },
146
+ "engines": {
147
+ "node": ">=22.18.0"
148
+ },
149
+ "scripts": {
150
+ "build": "tsdown",
151
+ "watch": "tsdown --watch",
152
+ "test": "vitest run",
153
+ "test:snapshots": "vitest run -u",
154
+ "test:types:code": "tsc -p tsconfig.json",
155
+ "test:types:test": "tsc -p ./runtime/__tests__/tsconfig.json",
156
+ "test:watch": "vitest --watch"
157
+ }
6
158
  }
@@ -0,0 +1,91 @@
1
+ import { fileURLToPath } from "node:url";
2
+ import type { RsbuildPlugin } from "@rsbuild/core";
3
+ import {
4
+ buildYakPluginOptions,
5
+ resolveYakContext,
6
+ type YakConfigOptions,
7
+ } from "../withYak/index.js";
8
+
9
+ // Rspack's loader context is webpack-compatible but does NOT implement
10
+ // `this.loadModule` (the webpack API the webpack-loader relies on). It does
11
+ // provide `this.fs.readFile`, `this.getResolve` and `this.addDependency` — which
12
+ // is exactly what the turbopack loader uses — so the turbopack loader runs as-is
13
+ // on Rspack. The compiled loader lives next to this file under dist/
14
+ // (dist/rsbuild/index.js and dist/loaders/turbo-loader.js are siblings).
15
+ const rspackLoaderPath = fileURLToPath(new URL("../loaders/turbo-loader.js", import.meta.url));
16
+
17
+ /**
18
+ * Rsbuild plugin for @yak/react.
19
+ *
20
+ * Wires the yak-swc transform as an Rspack `pre` loader that runs the
21
+ * compile-time CSS extraction in-loader and inlines the result as a
22
+ * `data:text/css;base64,` import (the same strategy as the Turbopack loader).
23
+ * Running it as a `pre` loader keeps yak-swc out of Rsbuild's own
24
+ * `builtin:swc-loader`, so it composes cleanly with that pass (TS/JSX, React
25
+ * Fast Refresh, and the React Compiler).
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * // rsbuild.config.ts
30
+ * import { defineConfig } from "@rsbuild/core";
31
+ * import { pluginReact } from "@rsbuild/plugin-react";
32
+ * import { pluginYak } from "@yak/react/rsbuild";
33
+ *
34
+ * export default defineConfig({
35
+ * plugins: [pluginReact(), pluginYak()],
36
+ * });
37
+ * ```
38
+ */
39
+ export function pluginYak(yakOptions: YakConfigOptions = {}): RsbuildPlugin {
40
+ return {
41
+ name: "@yak/react",
42
+ setup(api) {
43
+ api.modifyRspackConfig((config) => {
44
+ const rootContext = api.context.rootPath;
45
+ const yakPluginOptions = {
46
+ ...buildYakPluginOptions(yakOptions, rootContext),
47
+ importMode: {
48
+ value: "data:text/css;base64,",
49
+ encoding: "Base64",
50
+ },
51
+ };
52
+
53
+ config.module ??= {};
54
+ config.module.rules ??= [];
55
+ config.module.rules.push(
56
+ {
57
+ test: /\.(c|m)?[jt]sx?$/,
58
+ exclude: /[\\/]node_modules[\\/]/,
59
+ enforce: "pre",
60
+ use: [
61
+ {
62
+ loader: rspackLoaderPath,
63
+ options: { yakOptions, yakPluginOptions },
64
+ },
65
+ ],
66
+ },
67
+ // The extracted CSS is inlined as a `data:text/css;base64,` import.
68
+ // Rspack parses unknown data URIs as JavaScript, so tell it these are
69
+ // CSS modules. `css/auto` keeps Rspack's native CSS handling for them.
70
+ {
71
+ mimetype: "text/css",
72
+ type: "css/auto",
73
+ },
74
+ );
75
+
76
+ // Custom context file (`yak.context.{ts,tsx,js,jsx}`) for server-aware
77
+ // theming, mirroring the webpack/turbopack integrations.
78
+ const yakContext = resolveYakContext(yakOptions.contextPath, rootContext);
79
+ if (yakContext) {
80
+ config.resolve ??= {};
81
+ config.resolve.alias = {
82
+ ...config.resolve.alias,
83
+ "@yak/react/context/baseContext": yakContext,
84
+ };
85
+ }
86
+ });
87
+ },
88
+ };
89
+ }
90
+
91
+ export type { YakConfigOptions };
@@ -0,0 +1,48 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { atoms } from "../atoms";
3
+ import { ClassNames, css } from "../cssLiteral";
4
+ import type { RuntimeStyleProcessor } from "../publicStyledApi";
5
+
6
+ const classNamesOf = (processor: unknown, props: Record<string, unknown> = {}) => {
7
+ const classNames = new ClassNames();
8
+ (processor as RuntimeStyleProcessor<unknown>)(props, classNames, {});
9
+ return classNames.value;
10
+ };
11
+
12
+ describe("atoms", () => {
13
+ it("collects static classes, however they are grouped", () => {
14
+ expect(classNamesOf(atoms("a b c"))).toBe("a b c");
15
+ expect(classNamesOf(atoms("a", "b", "c"))).toBe("a b c");
16
+ expect(classNamesOf(atoms("a b", "c"))).toBe("a b c");
17
+ });
18
+
19
+ it("skips falsy atoms", () => {
20
+ expect(classNamesOf(atoms("a", false, "b"))).toBe("a b");
21
+ expect(classNamesOf(atoms(false))).toBe("");
22
+ expect(classNamesOf(atoms())).toBe("");
23
+ });
24
+
25
+ it("runs dynamic atoms after the static ones", () => {
26
+ const processor = atoms<{ $active?: boolean }>("a", (props, classNames) => {
27
+ if (props.$active) classNames.add("active");
28
+ });
29
+ expect(classNamesOf(processor, { $active: true })).toBe("a active");
30
+ expect(classNamesOf(processor, { $active: false })).toBe("a");
31
+ });
32
+
33
+ it("keeps classes a dynamic atom removes removable", () => {
34
+ const processor = atoms("a b", (_props, classNames) => {
35
+ classNames.delete("a");
36
+ });
37
+ expect(classNamesOf(processor)).toBe("b");
38
+ });
39
+
40
+ it("is static on its own but dynamic once css() wraps it", () => {
41
+ // styled`` compiles to css("yak123", atoms(...)) and gates its fast path on
42
+ // the outer processor, so atoms' own $dynamic is not read today. Pinned to
43
+ // catch a fold of static atoms that would make the fast path reachable
44
+ expect((atoms("a") as unknown as { $dynamic: boolean }).$dynamic).toBe(false);
45
+ // @ts-expect-error calling with a class name string mimics the compiled css form
46
+ expect((css("yak123", atoms("a")) as unknown as { $dynamic: boolean }).$dynamic).toBe(true);
47
+ });
48
+ });