@busiverse/ui 0.2.11 → 0.2.13
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 +16 -0
- package/dist/chunk-UWSNRCQW.js +89 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/styles.css +57 -0
- package/dist/theme/BusiverseThemeProvider.d.ts +12 -0
- package/dist/theme/BusiverseThemeProvider.d.ts.map +1 -0
- package/dist/theme/ThemeModeSelect.d.ts +10 -0
- package/dist/theme/ThemeModeSelect.d.ts.map +1 -0
- package/dist/theme/index.d.ts +3 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme-public.d.ts +2 -0
- package/dist/theme-public.d.ts.map +1 -0
- package/dist/theme-public.js +11 -0
- package/package.json +11 -4
package/README.md
CHANGED
|
@@ -277,3 +277,19 @@ The frontend should not duplicate BUSIVERSE brand assets in `public/`; brand ass
|
|
|
277
277
|
## Theme contract
|
|
278
278
|
|
|
279
279
|
`@busiverse/ui@0.2.10` owns the shared BUSIVERSE light/dark CSS contract. Apps should place `light` or `dark` on `document.documentElement`; `system` mode should resolve to one of those classes. Do not hard-code `className="dark ..."` on page wrappers, because it prevents light mode from working.
|
|
280
|
+
|
|
281
|
+
## BUSIVERSE theme contract
|
|
282
|
+
|
|
283
|
+
This frontend uses the shared BUSIVERSE theme contract from `@busiverse/ui`.
|
|
284
|
+
|
|
285
|
+
- Theme choices are `light`, `dark`, and `system`.
|
|
286
|
+
- The shared storage key is `busiverse-theme`.
|
|
287
|
+
- The DOM theme class is owned by `next-themes` through `attribute="class"`.
|
|
288
|
+
- App pages must not hard-code `className="dark ..."` wrappers.
|
|
289
|
+
- `vite.config.ts` must keep `loadEnv`; do not remove it while adding build or chunking improvements.
|
|
290
|
+
- Existing `VITE_*` environment variable names must not be renamed without approval.
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
## Theme contract
|
|
294
|
+
|
|
295
|
+
Use `BusiverseThemeProvider` from `@busiverse/ui/theme` in every separately deployed frontend. The only approved storage key is `busiverse-theme`, and every app must expose Light, Dark, and System through `ThemeModeSelect`. Do not create per-frontend theme storage keys or binary-only toggles.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn
|
|
3
|
+
} from "./chunk-PYZVP4NI.js";
|
|
4
|
+
|
|
5
|
+
// src/theme/BusiverseThemeProvider.tsx
|
|
6
|
+
import { ThemeProvider } from "next-themes";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
var BUSIVERSE_THEME_STORAGE_KEY = "busiverse-theme";
|
|
9
|
+
function BusiverseThemeProvider({
|
|
10
|
+
children,
|
|
11
|
+
defaultTheme = "system",
|
|
12
|
+
storageKey = BUSIVERSE_THEME_STORAGE_KEY,
|
|
13
|
+
enableSystem = true,
|
|
14
|
+
disableTransitionOnChange = true
|
|
15
|
+
}) {
|
|
16
|
+
return /* @__PURE__ */ jsx(
|
|
17
|
+
ThemeProvider,
|
|
18
|
+
{
|
|
19
|
+
attribute: "class",
|
|
20
|
+
defaultTheme,
|
|
21
|
+
enableSystem,
|
|
22
|
+
storageKey,
|
|
23
|
+
disableTransitionOnChange,
|
|
24
|
+
children
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// src/theme/ThemeModeSelect.tsx
|
|
30
|
+
import { useTheme } from "next-themes";
|
|
31
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
32
|
+
var MODES = [
|
|
33
|
+
{
|
|
34
|
+
value: "light",
|
|
35
|
+
label: "Light",
|
|
36
|
+
title: "Use light mode",
|
|
37
|
+
icon: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", className: "h-4 w-4", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
38
|
+
/* @__PURE__ */ jsx2("circle", { cx: "12", cy: "12", r: "4" }),
|
|
39
|
+
/* @__PURE__ */ jsx2("path", { d: "M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41" })
|
|
40
|
+
] })
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
value: "dark",
|
|
44
|
+
label: "Dark",
|
|
45
|
+
title: "Use dark mode",
|
|
46
|
+
icon: /* @__PURE__ */ jsx2("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", className: "h-4 w-4", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx2("path", { d: "M20.99 12.43A8.5 8.5 0 1 1 11.57 3a6.5 6.5 0 0 0 9.42 9.43Z" }) })
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
value: "system",
|
|
50
|
+
label: "System",
|
|
51
|
+
title: "Follow system theme",
|
|
52
|
+
icon: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", className: "h-4 w-4", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
53
|
+
/* @__PURE__ */ jsx2("rect", { x: "3", y: "4", width: "18", height: "12", rx: "2" }),
|
|
54
|
+
/* @__PURE__ */ jsx2("path", { d: "M8 20h8M12 16v4" })
|
|
55
|
+
] })
|
|
56
|
+
}
|
|
57
|
+
];
|
|
58
|
+
function ThemeModeSelect({ className, buttonClassName, label = "Theme", compact = false }) {
|
|
59
|
+
const { theme = "system", setTheme, resolvedTheme } = useTheme();
|
|
60
|
+
const currentMode = theme === "light" || theme === "dark" || theme === "system" ? theme : "system";
|
|
61
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("busiverse-theme-mode-select", className), role: "group", "aria-label": label, "data-theme-mode": currentMode, "data-resolved-theme": resolvedTheme ?? currentMode, children: [
|
|
62
|
+
!compact && /* @__PURE__ */ jsx2("span", { className: "busiverse-theme-mode-label", children: label }),
|
|
63
|
+
/* @__PURE__ */ jsx2("div", { className: "busiverse-theme-mode-options", children: MODES.map((mode) => {
|
|
64
|
+
const active = currentMode === mode.value;
|
|
65
|
+
return /* @__PURE__ */ jsxs(
|
|
66
|
+
"button",
|
|
67
|
+
{
|
|
68
|
+
type: "button",
|
|
69
|
+
title: mode.title,
|
|
70
|
+
"aria-pressed": active,
|
|
71
|
+
className: cn("busiverse-theme-mode-button", { "is-active": active }, buttonClassName),
|
|
72
|
+
onClick: () => setTheme(mode.value),
|
|
73
|
+
children: [
|
|
74
|
+
mode.icon,
|
|
75
|
+
!compact && /* @__PURE__ */ jsx2("span", { children: mode.label }),
|
|
76
|
+
compact && /* @__PURE__ */ jsx2("span", { className: "busiverse-sr-only", children: mode.label })
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
mode.value
|
|
80
|
+
);
|
|
81
|
+
}) })
|
|
82
|
+
] });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export {
|
|
86
|
+
BUSIVERSE_THEME_STORAGE_KEY,
|
|
87
|
+
BusiverseThemeProvider,
|
|
88
|
+
ThemeModeSelect
|
|
89
|
+
};
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,WAAW,CAAC;AAC1B,cAAc,OAAO,CAAC;AACtB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,WAAW,CAAC;AAC1B,cAAc,OAAO,CAAC;AACtB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAE3B,cAAc,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BUSIVERSE_THEME_STORAGE_KEY,
|
|
3
|
+
BusiverseThemeProvider,
|
|
4
|
+
ThemeModeSelect
|
|
5
|
+
} from "./chunk-UWSNRCQW.js";
|
|
1
6
|
import {
|
|
2
7
|
Badge,
|
|
3
8
|
Card,
|
|
@@ -345,6 +350,7 @@ function UserMenu() {
|
|
|
345
350
|
export {
|
|
346
351
|
AppShell,
|
|
347
352
|
AuthSessionProvider,
|
|
353
|
+
BUSIVERSE_THEME_STORAGE_KEY,
|
|
348
354
|
Badge,
|
|
349
355
|
BusiverseBrandHead,
|
|
350
356
|
BusiverseGithubIcon,
|
|
@@ -353,6 +359,7 @@ export {
|
|
|
353
359
|
BusiverseLogo,
|
|
354
360
|
BusiverseMailIcon,
|
|
355
361
|
BusiverseSocialIcon,
|
|
362
|
+
BusiverseThemeProvider,
|
|
356
363
|
BusiverseXIcon,
|
|
357
364
|
Button,
|
|
358
365
|
Card,
|
|
@@ -383,6 +390,7 @@ export {
|
|
|
383
390
|
StatCard,
|
|
384
391
|
StatusPill,
|
|
385
392
|
Textarea,
|
|
393
|
+
ThemeModeSelect,
|
|
386
394
|
TimeSeriesTable,
|
|
387
395
|
UsageQuotaBar,
|
|
388
396
|
UserMenu,
|
package/dist/styles.css
CHANGED
|
@@ -487,3 +487,60 @@ img, svg { max-width: 100%; display: block; }
|
|
|
487
487
|
.light .bg-slate-950,
|
|
488
488
|
.light .bg-slate-900,
|
|
489
489
|
.light .bg-\[hsl\(var\(--base-bg\)\)\] { background-color: hsl(var(--background)) !important; }
|
|
490
|
+
|
|
491
|
+
.busiverse-theme-mode-select {
|
|
492
|
+
display: inline-flex;
|
|
493
|
+
align-items: center;
|
|
494
|
+
gap: .5rem;
|
|
495
|
+
color: hsl(var(--foreground));
|
|
496
|
+
}
|
|
497
|
+
.busiverse-theme-mode-label {
|
|
498
|
+
font-size: .75rem;
|
|
499
|
+
font-weight: 600;
|
|
500
|
+
letter-spacing: .04em;
|
|
501
|
+
text-transform: uppercase;
|
|
502
|
+
color: hsl(var(--muted-foreground));
|
|
503
|
+
}
|
|
504
|
+
.busiverse-theme-mode-options {
|
|
505
|
+
display: inline-flex;
|
|
506
|
+
align-items: center;
|
|
507
|
+
gap: .25rem;
|
|
508
|
+
border-radius: 9999px;
|
|
509
|
+
border: 1px solid hsl(var(--border));
|
|
510
|
+
background: hsl(var(--card) / .72);
|
|
511
|
+
padding: .25rem;
|
|
512
|
+
backdrop-filter: blur(16px);
|
|
513
|
+
}
|
|
514
|
+
.busiverse-theme-mode-button {
|
|
515
|
+
display: inline-flex;
|
|
516
|
+
align-items: center;
|
|
517
|
+
justify-content: center;
|
|
518
|
+
gap: .375rem;
|
|
519
|
+
min-height: 2rem;
|
|
520
|
+
border-radius: 9999px;
|
|
521
|
+
border: 0;
|
|
522
|
+
background: transparent;
|
|
523
|
+
color: hsl(var(--muted-foreground));
|
|
524
|
+
padding: .375rem .625rem;
|
|
525
|
+
font: inherit;
|
|
526
|
+
font-size: .8125rem;
|
|
527
|
+
font-weight: 600;
|
|
528
|
+
cursor: pointer;
|
|
529
|
+
transition: color var(--motion-default) var(--ease-standard), background var(--motion-default) var(--ease-standard), box-shadow var(--motion-default) var(--ease-standard), transform var(--motion-fast) var(--ease-standard);
|
|
530
|
+
}
|
|
531
|
+
.busiverse-theme-mode-button:hover {
|
|
532
|
+
color: hsl(var(--foreground));
|
|
533
|
+
background: hsl(var(--muted) / .70);
|
|
534
|
+
}
|
|
535
|
+
.busiverse-theme-mode-button:active {
|
|
536
|
+
transform: scale(.98);
|
|
537
|
+
}
|
|
538
|
+
.busiverse-theme-mode-button:focus-visible {
|
|
539
|
+
outline: 2px solid var(--color-brand-blue);
|
|
540
|
+
outline-offset: 2px;
|
|
541
|
+
}
|
|
542
|
+
.busiverse-theme-mode-button.is-active {
|
|
543
|
+
color: hsl(var(--primary-foreground));
|
|
544
|
+
background: linear-gradient(90deg, #2563EB 0%, #7C3AED 100%);
|
|
545
|
+
box-shadow: 0 12px 32px rgb(37 99 235 / .20);
|
|
546
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export declare const BUSIVERSE_THEME_STORAGE_KEY = "busiverse-theme";
|
|
3
|
+
export type BusiverseThemeMode = "light" | "dark" | "system";
|
|
4
|
+
export interface BusiverseThemeProviderProps {
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
defaultTheme?: BusiverseThemeMode;
|
|
7
|
+
storageKey?: string;
|
|
8
|
+
enableSystem?: boolean;
|
|
9
|
+
disableTransitionOnChange?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function BusiverseThemeProvider({ children, defaultTheme, storageKey, enableSystem, disableTransitionOnChange, }: BusiverseThemeProviderProps): React.JSX.Element;
|
|
12
|
+
//# sourceMappingURL=BusiverseThemeProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BusiverseThemeProvider.d.ts","sourceRoot":"","sources":["../../src/theme/BusiverseThemeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,eAAO,MAAM,2BAA2B,oBAAoB,CAAC;AAC7D,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE7D,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,YAAuB,EACvB,UAAwC,EACxC,YAAmB,EACnB,yBAAgC,GACjC,EAAE,2BAA2B,qBAY7B"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type BusiverseThemeMode = "light" | "dark" | "system";
|
|
3
|
+
export interface ThemeModeSelectProps {
|
|
4
|
+
className?: string;
|
|
5
|
+
buttonClassName?: string;
|
|
6
|
+
label?: string;
|
|
7
|
+
compact?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function ThemeModeSelect({ className, buttonClassName, label, compact }: ThemeModeSelectProps): React.JSX.Element;
|
|
10
|
+
//# sourceMappingURL=ThemeModeSelect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThemeModeSelect.d.ts","sourceRoot":"","sources":["../../src/theme/ThemeModeSelect.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE7D,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAqCD,wBAAgB,eAAe,CAAC,EAAE,SAAS,EAAE,eAAe,EAAE,KAAe,EAAE,OAAe,EAAE,EAAE,oBAAoB,qBA4BrH"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-public.d.ts","sourceRoot":"","sources":["../src/theme-public.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@busiverse/ui",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.13",
|
|
4
4
|
"author": "Joel Julius Okoromi <okmarq@gmail.com> (https://busiversehq.com)",
|
|
5
5
|
"description": "BUSIVERSE shared React UI, design tokens, pricing, i18n, auth helpers, and product shell. Network-neutral core; Gateway transport is app-injected.",
|
|
6
6
|
"type": "module",
|
|
@@ -56,11 +56,16 @@
|
|
|
56
56
|
"types": "./dist/assets-public.d.ts",
|
|
57
57
|
"import": "./dist/assets-public.js",
|
|
58
58
|
"default": "./dist/assets-public.js"
|
|
59
|
+
},
|
|
60
|
+
"./theme": {
|
|
61
|
+
"types": "./dist/theme-public.d.ts",
|
|
62
|
+
"import": "./dist/theme-public.js",
|
|
63
|
+
"default": "./dist/theme-public.js"
|
|
59
64
|
}
|
|
60
65
|
},
|
|
61
66
|
"scripts": {
|
|
62
67
|
"clean": "node scripts/clean.mjs",
|
|
63
|
-
"build": "npm run clean && tsup src/index.ts src/tailwind-public.ts src/brand.ts src/i18n-public.ts src/billing.ts src/social.ts src/marketing.ts src/assets-public.ts --format esm --target es2022 && tsc -p tsconfig.build.json && node scripts/copy-static.mjs",
|
|
68
|
+
"build": "npm run clean && tsup src/index.ts src/tailwind-public.ts src/brand.ts src/i18n-public.ts src/billing.ts src/social.ts src/marketing.ts src/assets-public.ts src/theme-public.ts --format esm --target es2022 && tsc -p tsconfig.build.json && node scripts/copy-static.mjs",
|
|
64
69
|
"typecheck": "tsc --noEmit",
|
|
65
70
|
"pack:local": "npm pack",
|
|
66
71
|
"prepublishOnly": "npm run typecheck && npm run build && npm pack --dry-run"
|
|
@@ -68,7 +73,8 @@
|
|
|
68
73
|
"peerDependencies": {
|
|
69
74
|
"react": "^19.2.7",
|
|
70
75
|
"react-dom": "^19.2.7",
|
|
71
|
-
"tailwindcss": "^4.3.1"
|
|
76
|
+
"tailwindcss": "^4.3.1",
|
|
77
|
+
"next-themes": "^0.4.6"
|
|
72
78
|
},
|
|
73
79
|
"devDependencies": {
|
|
74
80
|
"@types/react": "19.2.17",
|
|
@@ -77,7 +83,8 @@
|
|
|
77
83
|
"react-dom": "19.2.7",
|
|
78
84
|
"tailwindcss": "4.3.1",
|
|
79
85
|
"tsup": "8.5.1",
|
|
80
|
-
"typescript": "6.0.3"
|
|
86
|
+
"typescript": "6.0.3",
|
|
87
|
+
"next-themes": "0.4.6"
|
|
81
88
|
},
|
|
82
89
|
"publishConfig": {
|
|
83
90
|
"registry": "https://registry.npmjs.org/",
|