@xzibit/ui 0.3.0 → 0.3.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.
- package/CHANGELOG.md +50 -0
- package/README.md +17 -1
- package/dist/index.cjs +2 -0
- package/dist/index.js +2 -0
- package/dist/metafile-cjs.json +1 -0
- package/dist/metafile-esm.json +1 -0
- package/package.json +7 -6
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@xzibit/ui` are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/) loosely; versioning follows [SemVer](https://semver.org/).
|
|
4
4
|
|
|
5
|
+
## [0.3.1] — 2026-05-24
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- **`'use client'` directives now ship in the bundled output.** Source files for `TopBar`, `AppsDropdown`, `BackToLauncher`, and `useApps` now carry a top-of-file `'use client'` directive, and the build (tsup + new `esbuild-plugin-preserve-directives`) preserves these directives in both ESM and CJS output. Previous versions (v0.1.0 – v0.3.0) stripped the directives at build time, which caused Next.js App Router to attempt server-side rendering of `useState`-bearing components and crash during prerender (`TypeError: (0 , d.useState) is not a function`).
|
|
10
|
+
|
|
11
|
+
Concretely: any consumer importing `TopBar` (or `AppsDropdown` / `BackToLauncher` / `useApps`) directly into a Server Component (default for `app/layout.tsx` and `app/page.tsx` files in Next.js 13+) would fail at build time with an exit-code-1 prerender error. ERP Overview Phase 1.11–1.13 deployments all hit this and silently failed Vercel deploys for three consecutive ships (live site continued serving the Phase 1.10 cached build, which masked the failures from reporting).
|
|
12
|
+
|
|
13
|
+
After upgrading to v0.3.1, no consumer-side workaround is required. Direct import into Server Components works.
|
|
14
|
+
|
|
15
|
+
### Why this happened
|
|
16
|
+
|
|
17
|
+
esbuild's default behaviour is to strip top-of-file directives during bundling. tsup wraps esbuild and inherits this default. Without an explicit plugin (`esbuild-plugin-preserve-directives`), source-file `'use client'` declarations disappear from the dist output, leaving consumers to wrap the imports themselves in a local `'use client'` re-export module — the workaround ERP Overview shipped as Phase 1.14's `src/components/TopBarClient.tsx`.
|
|
18
|
+
|
|
19
|
+
### Build config change
|
|
20
|
+
|
|
21
|
+
- **NEW** `tsup.config.ts` replaces the inline `tsup src/index.ts --format cjs,esm --dts --clean` script. Equivalent flags, plus `esbuildPlugins: [preserveDirectives()]`.
|
|
22
|
+
- **NEW devDependency:** `esbuild-plugin-preserve-directives@^0.0.11`.
|
|
23
|
+
- `scripts.build` simplified to `tsup` (reads `tsup.config.ts`); same for `dev`.
|
|
24
|
+
|
|
25
|
+
### Consumer migration after v0.3.1 lands
|
|
26
|
+
|
|
27
|
+
If you previously created a local `'use client'` wrapper for `TopBar` (or any other v0.3.0 export), you can now delete the wrapper and import directly from `@xzibit/ui` into your Server Component layout. See ERP Overview SHA `9fb78a4` for the pre-fix workaround pattern; SHA after Phase 1.15 will show the post-fix clean pattern.
|
|
28
|
+
|
|
29
|
+
### Backward compatible
|
|
30
|
+
|
|
31
|
+
API surface unchanged from v0.3.0. Same exports, same prop signatures, same default behaviour. v0.3.1 is a strict bug-fix release.
|
|
32
|
+
|
|
33
|
+
### Acceptance test (for future package work)
|
|
34
|
+
|
|
35
|
+
In a fresh Next.js 14+ App Router scaffold, place this in `app/layout.tsx`:
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
import { TopBar } from '@xzibit/ui';
|
|
39
|
+
export default function RootLayout({ children }) {
|
|
40
|
+
return (
|
|
41
|
+
<html lang="en">
|
|
42
|
+
<body>
|
|
43
|
+
<TopBar appName="Test App" />
|
|
44
|
+
<main style={{ marginTop: 44 }}>{children}</main>
|
|
45
|
+
</body>
|
|
46
|
+
</html>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Then `npm run build` must complete without a `useState is not a function` error and Vercel must report READY. This is the canonical regression test for the v0.3.1 fix.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
5
55
|
## [0.3.0] — 2026-05-24
|
|
6
56
|
|
|
7
57
|
### Added
|
package/README.md
CHANGED
|
@@ -14,10 +14,26 @@ Shared chrome components for the Xzibit Apps portfolio. Single source of truth
|
|
|
14
14
|
npm install @xzibit/ui
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
Peer dependencies: `react@^18`, `react-dom@^18`.
|
|
17
|
+
Peer dependencies: `react@^18 || ^19`, `react-dom@^18 || ^19`.
|
|
18
18
|
|
|
19
19
|
(Recommended companion: `@xzibit/tokens` for CSS variable values — without it, components fall back to inline hex defaults.)
|
|
20
20
|
|
|
21
|
+
### Next.js App Router compatibility (v0.3.1+)
|
|
22
|
+
|
|
23
|
+
`TopBar`, `AppsDropdown`, `BackToLauncher`, and `useApps` are Client Components — they carry a `'use client'` directive in the bundled output (preserved through tsup via `esbuild-plugin-preserve-directives`). You can import them directly into Server Components (e.g. `app/layout.tsx` and `app/page.tsx`) without wrapping them in a local `'use client'` re-export. Next.js sees the directive at the package boundary and renders them client-side automatically.
|
|
24
|
+
|
|
25
|
+
`ContentContainer` and `XzibitMark` have no client-only code (no hooks, no event handlers) — they're server-safe and unmarked.
|
|
26
|
+
|
|
27
|
+
Versions v0.1.0 – v0.3.0 shipped without preserved directives. Consumers on those versions need a local wrapper:
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
// src/components/TopBarClient.tsx — only needed on v0.1.0 – v0.3.0
|
|
31
|
+
'use client';
|
|
32
|
+
export { TopBar } from '@xzibit/ui';
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
…then import the wrapper instead of the package directly. **Upgrade to v0.3.1+ and delete the wrapper.**
|
|
36
|
+
|
|
21
37
|
---
|
|
22
38
|
|
|
23
39
|
## Use
|
package/dist/index.cjs
CHANGED
package/dist/index.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"inputs":{"src/XzibitMark.tsx":{"bytes":1644,"imports":[{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/BackToLauncher.tsx":{"bytes":2222,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/XzibitMark.tsx","kind":"import-statement","original":"./XzibitMark"},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/types.ts":{"bytes":2534,"imports":[],"format":"esm"},"src/useApps.ts":{"bytes":2717,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/types.ts","kind":"import-statement","original":"./types"}],"format":"esm"},"src/AppsDropdown.tsx":{"bytes":8128,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/useApps.ts","kind":"import-statement","original":"./useApps"},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/TopBar.tsx":{"bytes":3910,"imports":[{"path":"src/BackToLauncher.tsx","kind":"import-statement","original":"./BackToLauncher"},{"path":"src/AppsDropdown.tsx","kind":"import-statement","original":"./AppsDropdown"},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/ContentContainer.tsx":{"bytes":2945,"imports":[{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/index.ts":{"bytes":912,"imports":[{"path":"src/TopBar.tsx","kind":"import-statement","original":"./TopBar"},{"path":"src/BackToLauncher.tsx","kind":"import-statement","original":"./BackToLauncher"},{"path":"src/AppsDropdown.tsx","kind":"import-statement","original":"./AppsDropdown"},{"path":"src/XzibitMark.tsx","kind":"import-statement","original":"./XzibitMark"},{"path":"src/useApps.ts","kind":"import-statement","original":"./useApps"},{"path":"src/ContentContainer.tsx","kind":"import-statement","original":"./ContentContainer"},{"path":"src/types.ts","kind":"import-statement","original":"./types"}],"format":"esm"}},"outputs":{"dist/index.cjs":{"imports":[{"path":"react","kind":"require-call","external":true},{"path":"react/jsx-runtime","kind":"require-call","external":true},{"path":"react/jsx-runtime","kind":"require-call","external":true},{"path":"react","kind":"require-call","external":true},{"path":"react","kind":"require-call","external":true},{"path":"react/jsx-runtime","kind":"require-call","external":true},{"path":"react/jsx-runtime","kind":"require-call","external":true},{"path":"react/jsx-runtime","kind":"require-call","external":true}],"exports":[],"entryPoint":"src/index.ts","inputs":{"src/index.ts":{"bytesInOutput":337},"src/BackToLauncher.tsx":{"bytesInOutput":1929},"src/XzibitMark.tsx":{"bytesInOutput":1335},"src/AppsDropdown.tsx":{"bytesInOutput":7830},"src/useApps.ts":{"bytesInOutput":1230},"src/types.ts":{"bytesInOutput":255},"src/TopBar.tsx":{"bytesInOutput":3499},"src/ContentContainer.tsx":{"bytesInOutput":575}},"bytes":18231}}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"inputs":{"src/XzibitMark.tsx":{"bytes":1644,"imports":[{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/BackToLauncher.tsx":{"bytes":2222,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/XzibitMark.tsx","kind":"import-statement","original":"./XzibitMark"},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/types.ts":{"bytes":2534,"imports":[],"format":"esm"},"src/useApps.ts":{"bytes":2717,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/types.ts","kind":"import-statement","original":"./types"}],"format":"esm"},"src/AppsDropdown.tsx":{"bytes":8128,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"src/useApps.ts","kind":"import-statement","original":"./useApps"},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/TopBar.tsx":{"bytes":3910,"imports":[{"path":"src/BackToLauncher.tsx","kind":"import-statement","original":"./BackToLauncher"},{"path":"src/AppsDropdown.tsx","kind":"import-statement","original":"./AppsDropdown"},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/ContentContainer.tsx":{"bytes":2945,"imports":[{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"format":"esm"},"src/index.ts":{"bytes":912,"imports":[{"path":"src/TopBar.tsx","kind":"import-statement","original":"./TopBar"},{"path":"src/BackToLauncher.tsx","kind":"import-statement","original":"./BackToLauncher"},{"path":"src/AppsDropdown.tsx","kind":"import-statement","original":"./AppsDropdown"},{"path":"src/XzibitMark.tsx","kind":"import-statement","original":"./XzibitMark"},{"path":"src/useApps.ts","kind":"import-statement","original":"./useApps"},{"path":"src/ContentContainer.tsx","kind":"import-statement","original":"./ContentContainer"},{"path":"src/types.ts","kind":"import-statement","original":"./types"}],"format":"esm"}},"outputs":{"dist/index.js":{"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true},{"path":"react/jsx-runtime","kind":"import-statement","external":true}],"exports":["AppsDropdown","BackToLauncher","ContentContainer","TopBar","XzibitMark","normalizeApp","useApps"],"entryPoint":"src/index.ts","inputs":{"src/BackToLauncher.tsx":{"bytesInOutput":1796},"src/XzibitMark.tsx":{"bytesInOutput":1159},"src/AppsDropdown.tsx":{"bytesInOutput":7266},"src/useApps.ts":{"bytesInOutput":1171},"src/types.ts":{"bytesInOutput":255},"src/TopBar.tsx":{"bytesInOutput":3171},"src/index.ts":{"bytesInOutput":0},"src/ContentContainer.tsx":{"bytesInOutput":544}},"bytes":15707}}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xzibit/ui",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Shared chrome components for the Xzibit Apps portfolio. v0.1: TopBar + BackToLauncher + AppsDropdown + XzibitMark + useApps hook. Single source of truth for portfolio chrome — tweak once, every app picks it up on next deploy.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Xzibit Apps",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"topbar"
|
|
38
38
|
],
|
|
39
39
|
"scripts": {
|
|
40
|
-
"build": "tsup
|
|
41
|
-
"dev": "tsup
|
|
40
|
+
"build": "tsup",
|
|
41
|
+
"dev": "tsup --watch",
|
|
42
42
|
"prepublishOnly": "npm run build"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
@@ -46,11 +46,12 @@
|
|
|
46
46
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"
|
|
50
|
-
"tsup": "^8.0.0",
|
|
49
|
+
"@types/node": "^20.0.0",
|
|
51
50
|
"@types/react": "^18.0.0",
|
|
52
51
|
"@types/react-dom": "^18.0.0",
|
|
53
|
-
"
|
|
52
|
+
"esbuild-plugin-preserve-directives": "^0.0.11",
|
|
53
|
+
"tsup": "^8.0.0",
|
|
54
|
+
"typescript": "^5.0.0"
|
|
54
55
|
},
|
|
55
56
|
"publishConfig": {
|
|
56
57
|
"access": "public"
|