@kbach/react 1.0.0-beta.4 → 1.0.0-beta.6

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.
package/README.md CHANGED
@@ -32,14 +32,11 @@ export default defineConfig({
32
32
 
33
33
  ```tsx
34
34
  // main.tsx
35
- import { initKbach } from '@kbach/react';
36
35
  import { createRoot } from 'react-dom/client';
37
36
  import App from './App';
38
37
  import './kbach.css';
39
38
 
40
- initKbach().then(() => {
41
- createRoot(document.getElementById('root')!).render(<App />);
42
- });
39
+ createRoot(document.getElementById('root')!).render(<App />);
43
40
  ```
44
41
 
45
42
  ```tsx
@@ -48,6 +45,101 @@ initKbach().then(() => {
48
45
  </div>
49
46
  ```
50
47
 
48
+ That's the whole setup — the Vite plugin config plus a `kbach.css` with the
49
+ two marker comments. No `initKbach()`/async step before your first render:
50
+ `className` here is a plain string prop, resolved entirely by the CSS
51
+ `@kbach/react/vite` already generated at build time, same as any other
52
+ static stylesheet — nothing here calls into the WASM engine at render time,
53
+ so there's nothing to await.
54
+
55
+ `initKbach()` (still exported from `@kbach/react`) is only needed for two
56
+ opt-in features that genuinely do call into the Rust/WASM engine at
57
+ runtime: the dynamic [`kb()`](#dynamic-classes) function, and the optional
58
+ `@kbach/react/jsx-runtime` (a `jsxImportSource` override that intercepts
59
+ *every* element's `className` automatically instead of relying on the
60
+ static build). If you use either, `await initKbach()` once before your
61
+ first render, same as before.
62
+
63
+ ## React Router
64
+
65
+ Nothing beyond the Quick Start above — React Router is a client-side
66
+ routing library with no build-tool coupling of its own, so it layers on
67
+ top of the exact same Vite + `kbach.css` setup with zero extra
68
+ configuration, whether you're on the framework mode (`createBrowserRouter`)
69
+ or the classic `<BrowserRouter>` component form:
70
+
71
+ ```tsx
72
+ // main.tsx
73
+ import { createRoot } from 'react-dom/client';
74
+ import { RouterProvider, createBrowserRouter } from 'react-router';
75
+ import './kbach.css';
76
+ import Home from './routes/home';
77
+ import About from './routes/about';
78
+
79
+ const router = createBrowserRouter([
80
+ { path: '/', Component: Home },
81
+ { path: '/about', Component: About },
82
+ ]);
83
+
84
+ createRoot(document.getElementById('root')!).render(<RouterProvider router={router} />);
85
+ ```
86
+
87
+ Every route's own components use `className` exactly like any other
88
+ component — routing has no effect on how Kbach resolves classes, since
89
+ resolution already happened at build time, before routing even enters the
90
+ picture.
91
+
92
+ ## Next.js
93
+
94
+ Next.js uses webpack/Turbopack, not Vite, so `@kbach/react/vite` doesn't
95
+ apply — use `@kbach/react/postcss` instead, which does the exact same
96
+ build-time class-string scanning and CSS generation (they share the same
97
+ underlying engine), just wired into PostCSS, which both of Next.js's
98
+ bundlers already run for you with zero extra config.
99
+
100
+ ```js
101
+ // postcss.config.js
102
+ module.exports = {
103
+ plugins: {
104
+ '@kbach/react/postcss': {},
105
+ },
106
+ };
107
+ ```
108
+
109
+ ```css
110
+ /* app/globals.css (App Router) or styles/globals.css (Pages Router) */
111
+ /* kbach:start */
112
+ /* kbach:end */
113
+ ```
114
+
115
+ ```tsx
116
+ // app/layout.tsx
117
+ import './globals.css';
118
+
119
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
120
+ return (
121
+ <html lang="en">
122
+ <body>{children}</body>
123
+ </html>
124
+ );
125
+ }
126
+ ```
127
+
128
+ Plain `className="..."` strings on Server Components work with zero extra
129
+ setup — the CSS already exists at build time, same as any other static
130
+ stylesheet. Hook-based exports (`useTheme`, `useColors`, `<ThemeProvider>`)
131
+ already carry their own `'use client'` directive, so importing them into a
132
+ Client Component just works; importing one into a Server Component is a
133
+ compile-time error the same way importing `useState` into one would be —
134
+ that's React's own rule, not a Kbach limitation.
135
+
136
+ `root`/`theme`/`config`/`include`/`safelist` options all match
137
+ `@kbach/react/vite`'s exactly (see `KbachPluginOptions`, above) — `root`
138
+ additionally defaults to `process.cwd()` rather than a bundler-resolved
139
+ project root, since PostCSS has no equivalent to Vite's own resolved
140
+ `root` to read; pass it explicitly if your `postcss.config.js` doesn't
141
+ live at your project root (e.g. a monorepo app).
142
+
51
143
  ## Dark mode
52
144
 
53
145
  ```tsx
@@ -77,16 +169,20 @@ setTheme({
77
169
  ## Dynamic classes
78
170
 
79
171
  Classes that appear literally in your source are resolved at build time.
80
- For classes assembled from truly dynamic data, use `kb()`:
172
+ For classes assembled from truly dynamic data, use `kb()` — this is the
173
+ one thing in this package that genuinely calls into the WASM engine at
174
+ runtime, so `await initKbach()` once at startup before the first `kb()`
175
+ call (or before rendering, if you can't guarantee it runs first otherwise):
81
176
 
82
177
  ```ts
83
- import { kb } from '@kbach/react';
178
+ import { initKbach, kb } from '@kbach/react';
84
179
 
180
+ await initKbach();
85
181
  const className = kb(`bg-${userColor}-6`);
86
182
  ```
87
183
 
88
184
  Prefer a `safelist` entry in the plugin config when the possible values are
89
- known ahead of time — keeps everything static.
185
+ known ahead of time — keeps everything static, no `initKbach()` needed.
90
186
 
91
187
  ## Reading colors as values
92
188