Skip to content

Commit a535aaa

Browse files
committed
chore:updated AST Parser, added tests
1 parent 5416a77 commit a535aaa

File tree

3 files changed

+37
-7
lines changed

3 files changed

+37
-7
lines changed

AGENTS.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ Use these tips when working with the codebase or generating examples.
77

88
## How React Zero-UI works
99

10-
1. `useUI()` writes to `document.body.dataset` using keys you specify.
10+
1. `useUI()` writes to `document.body.dataset` using keys you specify.
1111

1212
```tsx
1313
const [staleValue, setValue] = useUI<'open' | 'closed'>('sidebar', 'closed');
1414
```
1515

1616
- `key` → becomes `data-{key}` on `<body>` (e.g., `sidebar``data-sidebar="closed"`).
17-
- `defaultValue` → used for SSR to avoid FOUC.
17+
- `defaultValue` → used for SSR to avoid FOUC. Added to the body as a data-attribute. at build time.
1818
- The first value is **always stale** — do NOT rely on it for reactive updates.
1919

2020
2. Consumption is done strictly with tailwind variant classNames:
@@ -56,10 +56,22 @@ const [, setTheme] = useUI<'light' | 'dark'>('theme', 'light');
5656
<div className="theme-light:bg-white theme-dark:bg-black" />
5757
```
5858

59+
## Example: Scoping Styles
60+
61+
```tsx
62+
const [, setTheme] = useUI<'light' | 'dark'>('theme', 'light');
63+
// Simply pass a ref to the element
64+
<div ref={setTheme.ref} className="theme-light:bg-white theme-dark:bg-black" />
65+
66+
```
67+
68+
Now the data-* will flip on that element, and the styles will be scoped to that element, or its children.
69+
5970
---
6071

6172
## What NOT to do
6273

74+
- ❌ Do not pass anything to the StateKey or InitialValue that is not a string or does not resolve to a string.
6375
- ❌ Don't use `useUI()` for business logic or data fetching
6476
- ❌ Don't rely on the first tuple value for reactivity
6577
- ❌ Don't use camelCase keys (will break variant generation)

packages/core/src/postcss/ast-parsing.cts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ export function extractVariants(filePath: string): VariantData[] {
186186

187187
// console.log(`[CACHE] MISS: ${filePath} (parsing...)`);
188188
// Parse the file
189-
const ast = parse(source, { sourceType: 'module', plugins: ['jsx', 'typescript', 'decorators-legacy'], sourceFilename: filePath });
189+
const ast = parse(source, { sourceType: 'module', plugins: ['jsx', 'typescript', 'decorators-legacy', 'topLevelAwait'], sourceFilename: filePath });
190190

191191
// Collect useUI setters
192192
const setters = collectUseUISetters(ast, source);
@@ -209,7 +209,7 @@ export function extractVariants(filePath: string): VariantData[] {
209209
}
210210

211211
// Parse and cache...
212-
const ast = parse(source, { sourceType: 'module', plugins: ['jsx', 'typescript', 'decorators-legacy'], sourceFilename: filePath });
212+
const ast = parse(source, { sourceType: 'module', plugins: ['jsx', 'typescript', 'decorators-legacy', 'topLevelAwait'], sourceFilename: filePath });
213213
const setters = collectUseUISetters(ast, source);
214214
if (!setters.length) return [];
215215

packages/core/src/postcss/index.cts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { processVariants, buildCss, generateAttributesFile, isZeroUiInitialized
66
import { runZeroUiInit } from '../cli/postInstall.cjs';
77
import type { Result, Root } from 'postcss';
88

9+
const DEV = process.env.NODE_ENV !== 'production';
10+
911
const plugin = (): { postcssPlugin: string; Once: (root: Root, { result }: { result: Result }) => Promise<void> } => {
1012
return {
1113
postcssPlugin: 'postcss-react-zero-ui',
@@ -36,9 +38,25 @@ const plugin = (): { postcssPlugin: string; Once: (root: Root, { result }: { res
3638

3739
// Generate body attributes file and TypeScript definitions
3840
await generateAttributesFile(finalVariants, initialValues);
39-
} catch (error: unknown) {
40-
const errorMessage = error instanceof Error ? error.message : String(error);
41-
throw new Error(`[Zero-UI] PostCSS plugin error: ${errorMessage}`);
41+
} catch (err: unknown) {
42+
const msg = err instanceof Error ? err.message : String(err);
43+
44+
// ⏩ 1. Always surface the real stack in the dev console
45+
if (DEV) console.error(err);
46+
47+
// ⏩ 2. Warn (dev) or throw (prod)
48+
if (DEV) {
49+
result.warn(`[Zero-UI] ${msg}`, { plugin: 'postcss-react-zero-ui' });
50+
} else {
51+
throw new Error(`[Zero-UI] PostCSS plugin error: ${msg}`);
52+
}
53+
const e = err as { loc?: { file?: string } } & Error;
54+
// ⏩ 3. Keep the file hot-watched so a save un-bricks the build
55+
if (e?.loc?.file) {
56+
result.messages.push({ type: 'dependency', plugin: 'postcss-react-zero-ui', file: e.loc.file, parent: result.opts.from });
57+
}
58+
59+
return; // bail out without killing dev-server
4260
}
4361
},
4462
};

0 commit comments

Comments
 (0)