@viliha/vui-ui 1.5.3 → 1.5.4
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 +15 -0
- package/package.json +1 -1
- package/src/chart.tsx +23 -3
- package/template/.env.example +3 -0
- package/template/app/_components/app-sidebar.tsx +3 -2
- package/template/app/_components/logo.tsx +2 -1
- package/template/app/_components/wordmark.tsx +3 -2
- package/template/lib/seo.ts +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,21 @@ backward-compatible features, **major** for breaking changes.
|
|
|
7
7
|
|
|
8
8
|
To upgrade, see [Upgrading](./AGENT.md#upgrading) in the agent guide.
|
|
9
9
|
|
|
10
|
+
## 1.5.4 — 2026-07-24
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `NEXT_PUBLIC_APP_NAME` env var (in the scaffold) renames the app — the sidebar,
|
|
15
|
+
wordmark, auth screens, and page titles now read from one place (`SITE.name`)
|
|
16
|
+
instead of a hard-coded "Vui Starter".
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- `ChartContainer` no longer triggers Recharts' "width(0) and height(0) … should
|
|
21
|
+
be greater than 0" warning when it renders inside a hidden container (e.g. a
|
|
22
|
+
kept-alive inactive tab). It waits for a measured size before mounting the
|
|
23
|
+
`ResponsiveContainer`.
|
|
24
|
+
|
|
10
25
|
## 1.5.3 — 2026-07-24
|
|
11
26
|
|
|
12
27
|
### Added
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@viliha/vui-ui",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.4",
|
|
4
4
|
"description": "Vui UI — a clean, token-driven React admin/CRM component library built on Tailwind CSS v4, shadcn-style patterns, and Radix Icons. Ships as TypeScript source (Just-in-Time), compiled by the consuming app.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Suman Bonakurthi",
|
package/src/chart.tsx
CHANGED
|
@@ -35,18 +35,38 @@ export function ChartContainer({
|
|
|
35
35
|
Object.entries(config).map(([key, v]) => [`--color-${key}`, v.color]),
|
|
36
36
|
) as React.CSSProperties;
|
|
37
37
|
|
|
38
|
+
// Only mount the ResponsiveContainer once the wrapper has a real size.
|
|
39
|
+
// Keep-alive tabs render inactive pages with `display:none` (0×0), which makes
|
|
40
|
+
// Recharts warn "width(0) and height(0) … should be greater than 0"; gating on
|
|
41
|
+
// an observed size avoids that and mounts the chart the moment the tab shows.
|
|
42
|
+
const ref = React.useRef<HTMLDivElement>(null);
|
|
43
|
+
const [sized, setSized] = React.useState(false);
|
|
44
|
+
React.useEffect(() => {
|
|
45
|
+
const el = ref.current;
|
|
46
|
+
if (!el) return;
|
|
47
|
+
const ro = new ResizeObserver(([entry]) => {
|
|
48
|
+
const r = entry?.contentRect;
|
|
49
|
+
setSized(!!r && r.width > 0 && r.height > 0);
|
|
50
|
+
});
|
|
51
|
+
ro.observe(el);
|
|
52
|
+
return () => ro.disconnect();
|
|
53
|
+
}, []);
|
|
54
|
+
|
|
38
55
|
return (
|
|
39
56
|
<ChartConfigContext.Provider value={config}>
|
|
40
57
|
<div
|
|
58
|
+
ref={ref}
|
|
41
59
|
style={cssVars}
|
|
42
60
|
className={cn(
|
|
43
61
|
"aspect-video w-full text-xs [&_.recharts-cartesian-grid_line]:stroke-border/60 [&_.recharts-text]:fill-muted-foreground",
|
|
44
62
|
className,
|
|
45
63
|
)}
|
|
46
64
|
>
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
65
|
+
{sized && (
|
|
66
|
+
<ResponsiveContainer width="100%" height="100%">
|
|
67
|
+
{children}
|
|
68
|
+
</ResponsiveContainer>
|
|
69
|
+
)}
|
|
50
70
|
</div>
|
|
51
71
|
</ChartConfigContext.Provider>
|
|
52
72
|
);
|
package/template/.env.example
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
# All are optional; defaults are used when unset. NEXT_PUBLIC_ vars are read at
|
|
3
3
|
# build time and inlined into the exported site.
|
|
4
4
|
|
|
5
|
+
# App / brand name shown in the sidebar, wordmark, auth screens, and page titles.
|
|
6
|
+
NEXT_PUBLIC_APP_NAME="Vui Starter"
|
|
7
|
+
|
|
5
8
|
NEXT_PUBLIC_COMPANY_NAME="VILIHA PTE. LTD."
|
|
6
9
|
# Optional — links the company name in the footer:
|
|
7
10
|
NEXT_PUBLIC_COMPANY_URL="https://viliha.com"
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
} from "@radix-ui/react-icons";
|
|
14
14
|
|
|
15
15
|
import { cn } from "@/lib/utils";
|
|
16
|
+
import { SITE } from "@/lib/seo";
|
|
16
17
|
import { Menu as MenuPanel } from "@viliha/vui-ui/menu";
|
|
17
18
|
import { Logo } from "./logo";
|
|
18
19
|
import { QuickActionsLauncher } from "./quick-actions";
|
|
@@ -369,13 +370,13 @@ function SidebarBody({
|
|
|
369
370
|
collapsed ? "w-9 shrink-0 justify-center px-0" : "flex-1",
|
|
370
371
|
)}
|
|
371
372
|
aria-label="Switch workspace"
|
|
372
|
-
title={collapsed ?
|
|
373
|
+
title={collapsed ? SITE.name : undefined}
|
|
373
374
|
>
|
|
374
375
|
<Logo variant="mark" className="h-6 w-6 shrink-0" />
|
|
375
376
|
{!collapsed && (
|
|
376
377
|
<>
|
|
377
378
|
<span className="min-w-0 flex-1 truncate text-lg font-bold tracking-tight text-foreground">
|
|
378
|
-
|
|
379
|
+
{SITE.name}
|
|
379
380
|
</span>
|
|
380
381
|
<ChevronsUpDown className="size-4 shrink-0 text-muted-foreground" />
|
|
381
382
|
</>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Image from "next/image";
|
|
2
2
|
|
|
3
3
|
import { cn } from "@/lib/utils";
|
|
4
|
+
import { SITE } from "@/lib/seo";
|
|
4
5
|
|
|
5
6
|
type LogoProps = {
|
|
6
7
|
/** Kept for call-site compatibility; the mark is the same either way. */
|
|
@@ -32,7 +33,7 @@ export function Logo({ className }: LogoProps) {
|
|
|
32
33
|
<svg
|
|
33
34
|
viewBox="0 0 24 24"
|
|
34
35
|
role="img"
|
|
35
|
-
aria-label=
|
|
36
|
+
aria-label={SITE.name}
|
|
36
37
|
className={cn("h-6 w-6", className)}
|
|
37
38
|
>
|
|
38
39
|
<rect width="24" height="24" rx="6" fill="var(--brand-indigo)" />
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Link from "next/link";
|
|
2
2
|
|
|
3
3
|
import { cn } from "@/lib/utils";
|
|
4
|
+
import { SITE } from "@/lib/seo";
|
|
4
5
|
import { Logo } from "./logo";
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -29,14 +30,14 @@ export function Wordmark({
|
|
|
29
30
|
textClassName,
|
|
30
31
|
)}
|
|
31
32
|
>
|
|
32
|
-
|
|
33
|
+
{SITE.name}
|
|
33
34
|
</span>
|
|
34
35
|
</>
|
|
35
36
|
);
|
|
36
37
|
const classes = cn("flex items-center gap-2", className);
|
|
37
38
|
|
|
38
39
|
return href ? (
|
|
39
|
-
<Link href={href} aria-label=
|
|
40
|
+
<Link href={href} aria-label={SITE.name} className={classes}>
|
|
40
41
|
{content}
|
|
41
42
|
</Link>
|
|
42
43
|
) : (
|
package/template/lib/seo.ts
CHANGED
|
@@ -3,7 +3,9 @@ import type { Metadata } from "next";
|
|
|
3
3
|
/** Single source of truth for site-wide SEO. Deployed as a static export to a
|
|
4
4
|
* custom domain (see ../CNAME), so URLs are absolute against SITE.url. */
|
|
5
5
|
export const SITE = {
|
|
6
|
-
name
|
|
6
|
+
// App/brand name shown in the sidebar, wordmark, auth screens, and page
|
|
7
|
+
// titles. Override per deployment via env (NEXT_PUBLIC_ = inlined at build).
|
|
8
|
+
name: process.env.NEXT_PUBLIC_APP_NAME ?? "Vui Starter",
|
|
7
9
|
tagline: "React Admin & CRM Design System",
|
|
8
10
|
url: "https://vui.viliha.com",
|
|
9
11
|
description:
|