@busiverse/ui 0.2.1 → 0.2.3

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
@@ -217,3 +217,28 @@ export const gateway = createGatewayClient({
217
217
  ```
218
218
 
219
219
  Font loading is also app-owned. The shared CSS does not import Google Fonts or any remote stylesheet. Each separately deployed Vercel frontend should self-host the BUSIVERSE fonts or load them explicitly at the app level.
220
+
221
+
222
+ ## v0.2.2 brand asset ownership
223
+
224
+ `@busiverse/ui` is now the owner of BUSIVERSE favicons, platform icons, social preview defaults, and logo assets. Consuming frontends should not duplicate BUSIVERSE favicon/logo assets in their own `public/` folders unless a deployment platform explicitly requires a static file before JavaScript loads.
225
+
226
+ Use `BusiverseBrandHead` once near the root of each frontend to inject the shared favicons, app manifest, Open Graph metadata, Twitter card metadata, and Microsoft tile metadata from package-owned assets.
227
+
228
+ ```tsx
229
+ import { BusiverseBrandHead } from "@busiverse/ui";
230
+
231
+ <BusiverseBrandHead
232
+ title="BUSIVERSE — Turn Ideas Into Operating Businesses"
233
+ description="BUSIVERSE combines AI automation, blockchain-backed trust, and modular business services to help teams launch and operate ventures faster."
234
+ />
235
+ ```
236
+
237
+ The package remains network-neutral: it does not call `fetch`, open sockets, or import remote fonts.
238
+
239
+
240
+ ## CSS ownership and app `index.css`
241
+
242
+ `@busiverse/ui/styles.css` owns BUSIVERSE brand tokens, shared component CSS, logo/brand helpers, pricing explorer styles, shadcn-compatible CSS variables, and marketing utility classes.
243
+
244
+ Each separately deployed Vercel frontend may still need a tiny app `src/index.css` when it uses Tailwind utility classes in its own source files. That file should be treated as the Tailwind build entrypoint/compatibility bridge only. It should not redefine BUSIVERSE brand tokens or duplicate component styling.
@@ -25,7 +25,23 @@ export declare const busiverseAssets: {
25
25
  readonly ico: string;
26
26
  readonly png16: string;
27
27
  readonly png32: string;
28
+ readonly png96: string;
28
29
  readonly appleTouchIcon: string;
30
+ readonly androidChrome192: string;
31
+ readonly androidChrome512: string;
32
+ readonly androidIcon192: string;
33
+ readonly msTile144: string;
34
+ };
35
+ readonly social: {
36
+ readonly xHeader: string;
37
+ readonly xProfile: string;
38
+ readonly linkedInCover: string;
39
+ readonly linkedInProfile: string;
40
+ readonly facebookCover: string;
41
+ readonly facebookProfile: string;
42
+ readonly instagramPost: string;
43
+ readonly instagramProfile: string;
29
44
  };
30
45
  };
46
+ export type BusiverseAssets = typeof busiverseAssets;
31
47
  //# sourceMappingURL=assets.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/assets/assets.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BlB,CAAC"}
1
+ {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/assets/assets.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4ClB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,OAAO,eAAe,CAAC"}
@@ -0,0 +1,16 @@
1
+ export interface BusiverseBrandHeadProps {
2
+ title?: string;
3
+ description?: string;
4
+ siteName?: string;
5
+ url?: string;
6
+ image?: string;
7
+ twitterSite?: string;
8
+ keywords?: string;
9
+ locale?: string;
10
+ themeColor?: string;
11
+ appleMobileWebAppTitle?: string;
12
+ applicationName?: string;
13
+ }
14
+ export declare function applyBusiverseBrandHead({ title, description, siteName, url, image, twitterSite, keywords, locale, themeColor, appleMobileWebAppTitle, applicationName, }?: BusiverseBrandHeadProps): void;
15
+ export declare function BusiverseBrandHead(props: BusiverseBrandHeadProps): null;
16
+ //# sourceMappingURL=BusiverseBrandHead.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BusiverseBrandHead.d.ts","sourceRoot":"","sources":["../../../src/components/brand/BusiverseBrandHead.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,uBAAuB;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AA6CD,wBAAgB,uBAAuB,CAAC,EACtC,KAAqB,EACrB,WAAiC,EACjC,QAAsB,EACtB,GAAG,EACH,KAAsC,EACtC,WAA2B,EAC3B,QAA8H,EAC9H,MAAgB,EAChB,UAAgC,EAChC,sBAAoC,EACpC,eAA6B,GAC9B,GAAE,uBAA4B,QAgC9B;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,QAkBhE"}
@@ -1,2 +1,3 @@
1
1
  export * from "./BusiverseLogo";
2
+ export * from "./BusiverseBrandHead";
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/brand/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/brand/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC"}
package/dist/index.js CHANGED
@@ -42,7 +42,22 @@ var busiverseAssets = {
42
42
  ico: new URL("./assets/favicon.io/favicon.ico", import.meta.url).href,
43
43
  png16: new URL("./assets/favicon.io/favicon-16x16.png", import.meta.url).href,
44
44
  png32: new URL("./assets/favicon.io/favicon-32x32.png", import.meta.url).href,
45
- appleTouchIcon: new URL("./assets/favicon.io/apple-touch-icon.png", import.meta.url).href
45
+ png96: new URL("./assets/favicon.io/favicon-96x96.png", import.meta.url).href,
46
+ appleTouchIcon: new URL("./assets/favicon.io/apple-touch-icon.png", import.meta.url).href,
47
+ androidChrome192: new URL("./assets/favicon.io/android-chrome-192x192.png", import.meta.url).href,
48
+ androidChrome512: new URL("./assets/favicon.io/android-chrome-512x512.png", import.meta.url).href,
49
+ androidIcon192: new URL("./assets/favicon.io/android-icon-192x192.png", import.meta.url).href,
50
+ msTile144: new URL("./assets/favicon.io/ms-icon-144x144.png", import.meta.url).href
51
+ },
52
+ social: {
53
+ xHeader: new URL("./assets/social/busiverse-twitter_x-header-2.7777777777777777x-darkbg.png", import.meta.url).href,
54
+ xProfile: new URL("./assets/social/busiverse-twitter_x-profile-picture-2.2222222222222223x-darkbg.png", import.meta.url).href,
55
+ linkedInCover: new URL("./assets/social/busiverse-linkedin-cover-photo-2.64x-darkbg.png", import.meta.url).href,
56
+ linkedInProfile: new URL("./assets/social/busiverse-linkedin-profile-picture-2.2222222222222223x-darkbg.png", import.meta.url).href,
57
+ facebookCover: new URL("./assets/social/busiverse-facebook-cover-photo-1.7333333333333334x-darkbg.png", import.meta.url).href,
58
+ facebookProfile: new URL("./assets/social/busiverse-facebook-profile-picture-1x-darkbg.png", import.meta.url).href,
59
+ instagramPost: new URL("./assets/social/busiverse-instagram-post-6x-darkbg.png", import.meta.url).href,
60
+ instagramProfile: new URL("./assets/social/busiverse-instagram-profile-picture-1.7777777777777777x-darkbg.png", import.meta.url).href
46
61
  }
47
62
  };
48
63
 
@@ -100,8 +115,109 @@ function BusiverseLogo({ variant = "horizontal", tone = "white", label = "BUSIVE
100
115
  );
101
116
  }
102
117
 
103
- // src/components/primitives/Button.tsx
118
+ // src/components/brand/BusiverseBrandHead.tsx
104
119
  import * as React from "react";
120
+ var DEFAULT_TITLE = "BUSIVERSE \u2014 Turn Ideas Into Operating Businesses";
121
+ var DEFAULT_DESCRIPTION = "BUSIVERSE combines AI automation, blockchain-backed trust, and modular business services to help teams launch and operate ventures faster.";
122
+ var DEFAULT_THEME_COLOR = "#020617";
123
+ function ensureMeta(selector, attributes) {
124
+ let node = document.head.querySelector(selector);
125
+ if (!node) {
126
+ node = document.createElement("meta");
127
+ document.head.appendChild(node);
128
+ }
129
+ Object.entries(attributes).forEach(([key, value]) => node?.setAttribute(key, value));
130
+ return node;
131
+ }
132
+ function ensureLink(selector, attributes) {
133
+ let node = document.head.querySelector(selector);
134
+ if (!node) {
135
+ node = document.createElement("link");
136
+ node.setAttribute("data-busiverse-ui-head", "true");
137
+ document.head.appendChild(node);
138
+ }
139
+ Object.entries(attributes).forEach(([key, value]) => node?.setAttribute(key, value));
140
+ return node;
141
+ }
142
+ function createManifestDataUrl(title, description, themeColor) {
143
+ const manifest = {
144
+ name: title,
145
+ short_name: "BUSIVERSE",
146
+ description,
147
+ start_url: "/",
148
+ scope: "/",
149
+ display: "standalone",
150
+ background_color: themeColor,
151
+ theme_color: themeColor,
152
+ icons: [
153
+ { src: busiverseAssets.favicon.androidChrome192, sizes: "192x192", type: "image/png" },
154
+ { src: busiverseAssets.favicon.androidChrome512, sizes: "512x512", type: "image/png" }
155
+ ]
156
+ };
157
+ return `data:application/manifest+json,${encodeURIComponent(JSON.stringify(manifest))}`;
158
+ }
159
+ function applyBusiverseBrandHead({
160
+ title = DEFAULT_TITLE,
161
+ description = DEFAULT_DESCRIPTION,
162
+ siteName = "Busiverse",
163
+ url,
164
+ image = busiverseAssets.social.xHeader,
165
+ twitterSite = "@busiverse1",
166
+ keywords = "Busiverse, AI automation, blockchain-backed trust, modular business services, distributed business infrastructure",
167
+ locale = "en_NG",
168
+ themeColor = DEFAULT_THEME_COLOR,
169
+ appleMobileWebAppTitle = "BUSIVERSE",
170
+ applicationName = "BUSIVERSE"
171
+ } = {}) {
172
+ document.title = title;
173
+ ensureMeta('meta[name="description"]', { name: "description", content: description });
174
+ ensureMeta('meta[name="keywords"]', { name: "keywords", content: keywords });
175
+ ensureMeta('meta[name="theme-color"]', { name: "theme-color", content: themeColor });
176
+ ensureMeta('meta[name="application-name"]', { name: "application-name", content: applicationName });
177
+ ensureMeta('meta[name="apple-mobile-web-app-title"]', { name: "apple-mobile-web-app-title", content: appleMobileWebAppTitle });
178
+ ensureMeta('meta[name="msapplication-TileColor"]', { name: "msapplication-TileColor", content: themeColor });
179
+ ensureMeta('meta[name="msapplication-TileImage"]', { name: "msapplication-TileImage", content: busiverseAssets.favicon.msTile144 });
180
+ ensureLink('link[data-busiverse-ui-head="icon-ico"]', { rel: "icon", type: "image/x-icon", href: busiverseAssets.favicon.ico, "data-busiverse-ui-head": "icon-ico" });
181
+ ensureLink('link[data-busiverse-ui-head="icon-16"]', { rel: "icon", type: "image/png", sizes: "16x16", href: busiverseAssets.favicon.png16, "data-busiverse-ui-head": "icon-16" });
182
+ ensureLink('link[data-busiverse-ui-head="icon-32"]', { rel: "icon", type: "image/png", sizes: "32x32", href: busiverseAssets.favicon.png32, "data-busiverse-ui-head": "icon-32" });
183
+ ensureLink('link[data-busiverse-ui-head="icon-96"]', { rel: "icon", type: "image/png", sizes: "96x96", href: busiverseAssets.favicon.png96, "data-busiverse-ui-head": "icon-96" });
184
+ ensureLink('link[data-busiverse-ui-head="icon-192"]', { rel: "icon", type: "image/png", sizes: "192x192", href: busiverseAssets.favicon.androidIcon192, "data-busiverse-ui-head": "icon-192" });
185
+ ensureLink('link[data-busiverse-ui-head="apple-touch-icon"]', { rel: "apple-touch-icon", sizes: "180x180", href: busiverseAssets.favicon.appleTouchIcon, "data-busiverse-ui-head": "apple-touch-icon" });
186
+ ensureLink('link[data-busiverse-ui-head="manifest"]', { rel: "manifest", href: createManifestDataUrl(title, description, themeColor), "data-busiverse-ui-head": "manifest" });
187
+ ensureMeta('meta[property="og:title"]', { property: "og:title", content: title });
188
+ ensureMeta('meta[property="og:description"]', { property: "og:description", content: description });
189
+ ensureMeta('meta[property="og:type"]', { property: "og:type", content: "website" });
190
+ ensureMeta('meta[property="og:site_name"]', { property: "og:site_name", content: siteName });
191
+ ensureMeta('meta[property="og:locale"]', { property: "og:locale", content: locale });
192
+ ensureMeta('meta[property="og:image"]', { property: "og:image", content: image });
193
+ if (url) ensureMeta('meta[property="og:url"]', { property: "og:url", content: url });
194
+ ensureMeta('meta[name="twitter:card"]', { name: "twitter:card", content: "summary_large_image" });
195
+ ensureMeta('meta[name="twitter:title"]', { name: "twitter:title", content: title });
196
+ ensureMeta('meta[name="twitter:description"]', { name: "twitter:description", content: description });
197
+ ensureMeta('meta[name="twitter:site"]', { name: "twitter:site", content: twitterSite });
198
+ ensureMeta('meta[name="twitter:image"]', { name: "twitter:image", content: image });
199
+ }
200
+ function BusiverseBrandHead(props) {
201
+ React.useEffect(() => {
202
+ applyBusiverseBrandHead(props);
203
+ }, [
204
+ props.title,
205
+ props.description,
206
+ props.siteName,
207
+ props.url,
208
+ props.image,
209
+ props.twitterSite,
210
+ props.keywords,
211
+ props.locale,
212
+ props.themeColor,
213
+ props.appleMobileWebAppTitle,
214
+ props.applicationName
215
+ ]);
216
+ return null;
217
+ }
218
+
219
+ // src/components/primitives/Button.tsx
220
+ import * as React2 from "react";
105
221
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
106
222
  var variants = {
107
223
  primary: "busiverse-btn-primary",
@@ -116,7 +232,7 @@ var sizes = {
116
232
  md: "busiverse-btn-md",
117
233
  lg: "busiverse-btn-lg"
118
234
  };
119
- var Button = React.forwardRef(function Button2({ className, variant = "primary", size = "md", isLoading, children, disabled, ...props }, ref) {
235
+ var Button = React2.forwardRef(function Button2({ className, variant = "primary", size = "md", isLoading, children, disabled, ...props }, ref) {
120
236
  return /* @__PURE__ */ jsxs(
121
237
  "button",
122
238
  {
@@ -158,23 +274,23 @@ function Badge({ className, tone = "blue", ...props }) {
158
274
  }
159
275
 
160
276
  // src/components/primitives/Input.tsx
161
- import * as React2 from "react";
277
+ import * as React3 from "react";
162
278
  import { jsx as jsx5 } from "react/jsx-runtime";
163
- var Input = React2.forwardRef(function Input2({ className, ...props }, ref) {
279
+ var Input = React3.forwardRef(function Input2({ className, ...props }, ref) {
164
280
  return /* @__PURE__ */ jsx5("input", { ref, className: cn("busiverse-focus-ring busiverse-input", className), ...props });
165
281
  });
166
282
 
167
283
  // src/components/primitives/Select.tsx
168
- import * as React3 from "react";
284
+ import * as React4 from "react";
169
285
  import { jsx as jsx6 } from "react/jsx-runtime";
170
- var Select = React3.forwardRef(function Select2({ className, ...props }, ref) {
286
+ var Select = React4.forwardRef(function Select2({ className, ...props }, ref) {
171
287
  return /* @__PURE__ */ jsx6("select", { ref, className: cn("busiverse-focus-ring busiverse-input", className), ...props });
172
288
  });
173
289
 
174
290
  // src/components/primitives/Textarea.tsx
175
- import * as React4 from "react";
291
+ import * as React5 from "react";
176
292
  import { jsx as jsx7 } from "react/jsx-runtime";
177
- var Textarea = React4.forwardRef(function Textarea2({ className, ...props }, ref) {
293
+ var Textarea = React5.forwardRef(function Textarea2({ className, ...props }, ref) {
178
294
  return /* @__PURE__ */ jsx7("textarea", { ref, className: cn("busiverse-focus-ring busiverse-input busiverse-textarea", className), ...props });
179
295
  });
180
296
 
@@ -429,7 +545,7 @@ function UsageQuotaBar({ used, limit, label }) {
429
545
  }
430
546
 
431
547
  // src/components/billing/ServicePricingExplorer.tsx
432
- import * as React6 from "react";
548
+ import * as React7 from "react";
433
549
 
434
550
  // src/pricing/regions.ts
435
551
  var busiverseSupportedRegions = [
@@ -448,7 +564,7 @@ function getSupportedRegion(countryCode) {
448
564
  }
449
565
 
450
566
  // src/i18n/BusiverseI18nProvider.tsx
451
- import * as React5 from "react";
567
+ import * as React6 from "react";
452
568
  import { jsx as jsx20 } from "react/jsx-runtime";
453
569
  var defaultRegion = {
454
570
  locale: "en-NG",
@@ -457,10 +573,10 @@ var defaultRegion = {
457
573
  currencyCode: "NGN",
458
574
  timeZone: "Africa/Lagos"
459
575
  };
460
- var I18nContext = React5.createContext(null);
576
+ var I18nContext = React6.createContext(null);
461
577
  function BusiverseI18nProvider({ children, initialRegion, bundles = {} }) {
462
- const [region, setRegion] = React5.useState({ ...defaultRegion, ...initialRegion });
463
- const t = React5.useCallback((key, fallback, vars) => {
578
+ const [region, setRegion] = React6.useState({ ...defaultRegion, ...initialRegion });
579
+ const t = React6.useCallback((key, fallback, vars) => {
464
580
  const value = bundles[region.locale]?.[key] ?? bundles[region.locale.split("-")[0]]?.[key] ?? fallback ?? key;
465
581
  if (!vars) return value;
466
582
  return Object.entries(vars).reduce((acc, [name, val]) => acc.replaceAll(`{${name}}`, String(val)), value);
@@ -468,7 +584,7 @@ function BusiverseI18nProvider({ children, initialRegion, bundles = {} }) {
468
584
  return /* @__PURE__ */ jsx20(I18nContext.Provider, { value: { region, bundles, setRegion, t }, children });
469
585
  }
470
586
  function useBusiverseI18n() {
471
- const ctx = React5.useContext(I18nContext);
587
+ const ctx = React6.useContext(I18nContext);
472
588
  if (!ctx) throw new Error("useBusiverseI18n must be used inside BusiverseI18nProvider");
473
589
  return ctx;
474
590
  }
@@ -8078,7 +8194,7 @@ function summarizeRange(min, max, region) {
8078
8194
  return `${formatPricingValue(min, region)} \u2013 ${formatPricingValue(max, region)}`;
8079
8195
  }
8080
8196
  function useFilteredSummaries(rows) {
8081
- return React6.useMemo(() => {
8197
+ return React7.useMemo(() => {
8082
8198
  const serviceKeys = [...new Set(rows.map((row) => row.service))];
8083
8199
  return getServicePricingSummaries(busiverseServices.filter((service) => serviceKeys.includes(service.key)));
8084
8200
  }, [rows]);
@@ -8093,19 +8209,19 @@ function ServicePricingExplorer({
8093
8209
  maxInitialRows = 48
8094
8210
  }) {
8095
8211
  const { region } = useBusiverseI18n();
8096
- const [audience, setAudience] = React6.useState(defaultAudience);
8097
- const [category, setCategory] = React6.useState("all");
8098
- const [query, setQuery] = React6.useState("");
8099
- const [showAllRows, setShowAllRows] = React6.useState(false);
8212
+ const [audience, setAudience] = React7.useState(defaultAudience);
8213
+ const [category, setCategory] = React7.useState("all");
8214
+ const [query, setQuery] = React7.useState("");
8215
+ const [showAllRows, setShowAllRows] = React7.useState(false);
8100
8216
  const summaries = useFilteredSummaries(rows);
8101
- const filteredSummaries = React6.useMemo(() => summaries.filter((summary) => {
8217
+ const filteredSummaries = React7.useMemo(() => summaries.filter((summary) => {
8102
8218
  const service = getBusiverseService(summary.service);
8103
8219
  if (category !== "all" && service?.category !== category) return false;
8104
8220
  if (!query.trim()) return true;
8105
8221
  const haystack = `${summary.service} ${service?.name ?? ""} ${service?.description ?? ""}`.toLowerCase();
8106
8222
  return haystack.includes(query.toLowerCase());
8107
8223
  }), [category, query, summaries]);
8108
- const filteredRows = React6.useMemo(() => {
8224
+ const filteredRows = React7.useMemo(() => {
8109
8225
  const allowedServices = new Set(filteredSummaries.map((summary) => summary.service));
8110
8226
  return rows.filter((row) => allowedServices.has(row.service));
8111
8227
  }, [rows, filteredSummaries]);
@@ -8270,14 +8386,14 @@ function createGatewayClient(options) {
8270
8386
  }
8271
8387
 
8272
8388
  // src/auth/AuthSessionProvider.tsx
8273
- import * as React7 from "react";
8389
+ import * as React8 from "react";
8274
8390
  import { jsx as jsx24 } from "react/jsx-runtime";
8275
- var AuthContext = React7.createContext(null);
8391
+ var AuthContext = React8.createContext(null);
8276
8392
  function AuthSessionProvider({ children, session }) {
8277
8393
  return /* @__PURE__ */ jsx24(AuthContext.Provider, { value: session, children });
8278
8394
  }
8279
8395
  function useBusiverseAuth() {
8280
- const value = React7.useContext(AuthContext);
8396
+ const value = React8.useContext(AuthContext);
8281
8397
  if (!value) throw new Error("useBusiverseAuth must be used inside AuthSessionProvider");
8282
8398
  return value;
8283
8399
  }
@@ -8317,6 +8433,7 @@ export {
8317
8433
  AppShell,
8318
8434
  AuthSessionProvider,
8319
8435
  Badge,
8436
+ BusiverseBrandHead,
8320
8437
  BusiverseI18nProvider,
8321
8438
  BusiverseLogo,
8322
8439
  Button,
@@ -8348,6 +8465,7 @@ export {
8348
8465
  TimeSeriesTable,
8349
8466
  UsageQuotaBar,
8350
8467
  UserMenu,
8468
+ applyBusiverseBrandHead,
8351
8469
  busiverseAssets,
8352
8470
  busiverseColors,
8353
8471
  busiverseContainers,
package/dist/styles.css CHANGED
@@ -39,6 +39,36 @@
39
39
  --motion-default: 200ms;
40
40
  --motion-slow: 300ms;
41
41
  --ease-standard: cubic-bezier(0.16,1,0.3,1);
42
+
43
+ /* Shadcn/Tailwind compatibility aliases used by existing Busiverse frontends. */
44
+ --background: 222 47% 4%;
45
+ --foreground: 0 0% 100%;
46
+ --card: 222 84% 5%;
47
+ --card-foreground: 0 0% 100%;
48
+ --popover: 222 47% 11%;
49
+ --popover-foreground: 0 0% 100%;
50
+ --primary: 217 91% 60%;
51
+ --primary-foreground: 0 0% 100%;
52
+ --secondary: 263 70% 50%;
53
+ --secondary-foreground: 0 0% 100%;
54
+ --muted: 215 25% 17%;
55
+ --muted-foreground: 214 16% 65%;
56
+ --accent: 258 90% 66%;
57
+ --accent-foreground: 0 0% 100%;
58
+ --destructive: 0 84% 60%;
59
+ --destructive-foreground: 0 0% 100%;
60
+ --border: 0 0% 100%;
61
+ --input: 0 0% 100%;
62
+ --ring: 217 91% 60%;
63
+ --radius: 0.75rem;
64
+ --sidebar-background: 222 47% 4%;
65
+ --sidebar-foreground: 214 32% 91%;
66
+ --sidebar-primary: 217 91% 60%;
67
+ --sidebar-primary-foreground: 0 0% 100%;
68
+ --sidebar-accent: 215 25% 17%;
69
+ --sidebar-accent-foreground: 0 0% 100%;
70
+ --sidebar-border: 0 0% 100%;
71
+ --sidebar-ring: 217 91% 60%;
42
72
  color-scheme: dark;
43
73
  }
44
74
 
@@ -253,3 +283,42 @@ img, svg { max-width: 100%; display: block; }
253
283
  .busiverse-pricing-grid { grid-template-columns: 1fr; }
254
284
  .busiverse-pricing-controls > input { max-width: none; }
255
285
  }
286
+
287
+ /* Shared BUSIVERSE marketing utilities used by separately deployed frontends. */
288
+ .text-gradient-blue-violet {
289
+ background: linear-gradient(90deg, var(--color-brand-blue), var(--color-brand-violet));
290
+ -webkit-background-clip: text;
291
+ background-clip: text;
292
+ color: transparent;
293
+ }
294
+ .text-gradient-blue-cyan {
295
+ background: linear-gradient(90deg, var(--color-brand-blue), var(--color-brand-cyan));
296
+ -webkit-background-clip: text;
297
+ background-clip: text;
298
+ color: transparent;
299
+ }
300
+ .text-gradient-violet-cyan {
301
+ background: linear-gradient(90deg, var(--color-brand-violet), var(--color-brand-cyan));
302
+ -webkit-background-clip: text;
303
+ background-clip: text;
304
+ color: transparent;
305
+ }
306
+ .text-gradient-full {
307
+ background: linear-gradient(90deg, var(--color-brand-blue) 0%, var(--color-brand-violet) 50%, var(--color-brand-cyan) 100%);
308
+ -webkit-background-clip: text;
309
+ background-clip: text;
310
+ color: transparent;
311
+ }
312
+ .bg-gradient-primary { background: linear-gradient(90deg, var(--color-brand-blue), var(--color-brand-violet)); }
313
+ .bg-gradient-secondary { background: linear-gradient(90deg, var(--color-brand-blue), var(--color-brand-cyan)); }
314
+ .bg-gradient-tertiary { background: linear-gradient(90deg, var(--color-brand-violet), var(--color-brand-cyan)); }
315
+ .bg-gradient-full { background: linear-gradient(90deg, var(--color-brand-blue) 0%, var(--color-brand-violet) 50%, var(--color-brand-cyan) 100%); }
316
+ .bg-gradient-hero { background: linear-gradient(135deg, var(--color-bg-primary) 0%, var(--color-bg-brand-dark) 45%, var(--color-bg-secondary) 100%); }
317
+ .glass-card { background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.10); backdrop-filter: blur(16px); }
318
+ .glass-card-hover { transition: transform 250ms var(--ease-standard), background 250ms, border-color 250ms; }
319
+ .glass-card-hover:hover { background: rgba(255,255,255,.10); border-color: rgba(255,255,255,.20); transform: translateY(-2px); }
320
+ .animate-float { animation: busiverse-float 3s ease-in-out infinite; }
321
+ @keyframes busiverse-float {
322
+ 0%, 100% { transform: translateY(0); }
323
+ 50% { transform: translateY(-16px); }
324
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@busiverse/ui",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
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",