@bsuite/theme 0.5.0 → 0.7.0

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
@@ -126,6 +126,18 @@ Braden keeps separate corporate identity tokens in `@bsuite/theme/braden-css`: B
126
126
 
127
127
  WCAG AA compliance: use semantic text tokens (`text-foreground`, `text-muted-foreground`, `text-text-on-primary`, `text-text-on-accent`) rather than raw `text-white`/`text-black`. Dark-surface text is capped at L=0.94 for extended-session comfort.
128
128
 
129
+ ## Text-role contract (v0.6.0)
130
+
131
+ Six measured tiers — `--role-text-heading`, `--role-text-body`, `--role-text-secondary`, `--role-text-muted`, `--role-text-subtle`, `--role-text-disabled` — each with documented WCAG contrast in both modes. Full numbers + methodology: `docs/TOKEN-MAPPING.md` §8.1.
132
+
133
+ ## Canonical gradient (v0.6.0)
134
+
135
+ Exactly one decorative accent gradient exists suite-wide — `--gradient-accent` / `.bsuite-accent-gradient` (`--role-primary` → `--role-accent`). Marketing heroes only, never functional text. `docs/TOKEN-MAPPING.md` §8.2.
136
+
137
+ ## Grid/dot doctrine (v0.6.0)
138
+
139
+ `<HeroGrid>` (public/pre-auth hero bands) and `<DotPattern>` (authenticated shells, `@bsuite/ui`) are mutually exclusive per context and enforced by `@bsuite/dry-lint`'s `no-grid-dot-doctrine-violation` rule. `docs/TOKEN-MAPPING.md` §8.3.
140
+
129
141
  ## License
130
142
 
131
143
  UNLICENSED — internal BSuite use only.
@@ -43,7 +43,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
43
43
  * </BrandingProvider>
44
44
  */
45
45
  import { createContext, useCallback, useEffect, useMemo, useRef, useState } from 'react';
46
- import { sanitizeBrandingUrl, sanitizeFontFamily, toCssUrl, } from './branding-sanitize';
46
+ import { sanitizeBrandingUrl, sanitizeFontFamily, toCssUrl, } from './branding-sanitize.js';
47
47
  export const BRANDING_STORAGE_KEY = 'bsuite_tenant_branding';
48
48
  export const BRANDING_OVERRIDE_FLAG = 'VITE_ENABLE_BRANDING_OVERRIDE';
49
49
  export const BrandingContext = createContext(undefined);
@@ -1,5 +1,5 @@
1
1
  import type { ReactNode } from 'react';
2
- import { type ThemeContextValue, type ThemeMode } from '../index';
2
+ import { type ThemeContextValue, type ThemeMode } from '../index.js';
3
3
  export declare const ThemeContext: import("react").Context<ThemeContextValue | undefined>;
4
4
  export interface ThemeProviderProps {
5
5
  children: ReactNode;
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../src/react/ThemeProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,EAAyC,KAAK,iBAAiB,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAA;AAExG,eAAO,MAAM,YAAY,wDAA0D,CAAA;AAEnF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,SAAS,CAAA;IACnB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,SAAS,CAAA;IACxB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AA6BD,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,YAAuB,EACvB,UAA8B,GAC/B,EAAE,kBAAkB,+BA4DpB"}
1
+ {"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../src/react/ThemeProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,EAAyC,KAAK,iBAAiB,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAA;AAE3G,eAAO,MAAM,YAAY,wDAA0D,CAAA;AAEnF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,SAAS,CAAA;IACnB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,SAAS,CAAA;IACxB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AA6BD,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,YAAuB,EACvB,UAA8B,GAC/B,EAAE,kBAAkB,+BA4DpB"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { createContext, useCallback, useEffect, useMemo, useState } from 'react';
3
- import { THEME_STORAGE_KEY } from '../index';
3
+ import { THEME_STORAGE_KEY } from '../index.js';
4
4
  export const ThemeContext = createContext(undefined);
5
5
  /**
6
6
  * Resolve a stored ThemeMode to the effective ResolvedTheme.
@@ -30,8 +30,11 @@ export type BadgeVariant =
30
30
  | 'error'
31
31
  /** Blue — Draft, New, Scheduled */
32
32
  | 'info'
33
- /** Purple — Converted, Promoted */
34
- | 'purple'
33
+ /** Deep blue — Converted, Promoted, Exported, Paid: terminal states that
34
+ * have moved past success. Was `purple`, renamed 0.7.0: the variant was
35
+ * named for a colour rather than a role, and that colour is quarantined
36
+ * from semantics (purple collapses onto primary blue under protanopia). */
37
+ | 'secondary'
35
38
  /** Gray — Inactive, Archived */
36
39
  | 'neutral';
37
40
  export interface StatusBadgeProps {
@@ -1 +1 @@
1
- {"version":3,"file":"StatusBadge.d.ts","sourceRoot":"","sources":["../../../src/react/components/StatusBadge.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3D,MAAM,MAAM,YAAY;AACtB,yCAAyC;AACvC,SAAS;AACX,mCAAmC;GACjC,SAAS;AACX,sCAAsC;GACpC,OAAO;AACT,mCAAmC;GACjC,MAAM;AACR,mCAAmC;GACjC,QAAQ;AACV,gCAAgC;GAC9B,SAAS,CAAC;AAEd,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,8CAA8C;IAC9C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAqBD,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,KAAK,EACL,IAAW,EACX,SAAS,EACT,KAAK,EACL,aAAa,EAAE,MAAM,GACtB,EAAE,gBAAgB,GAAG,SAAS,CAc9B;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,GAChD,YAAY,CAoCd;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CASxD;AAED,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,gBAAgB,EAAE,SAAS,GAAG,OAAO,CAAC;IACvF,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;CAC1D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,KAAK,EACL,gBAAgB,EAChB,GAAG,IAAI,EACR,EAAE,oBAAoB,GAAG,SAAS,CAIlC"}
1
+ {"version":3,"file":"StatusBadge.d.ts","sourceRoot":"","sources":["../../../src/react/components/StatusBadge.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3D,MAAM,MAAM,YAAY;AACtB,yCAAyC;AACvC,SAAS;AACX,mCAAmC;GACjC,SAAS;AACX,sCAAsC;GACpC,OAAO;AACT,mCAAmC;GACjC,MAAM;AACR;;;4EAG4E;GAC1E,WAAW;AACb,gCAAgC;GAC9B,SAAS,CAAC;AAEd,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,8CAA8C;IAC9C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AA2BD,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,KAAK,EACL,IAAW,EACX,SAAS,EACT,KAAK,EACL,aAAa,EAAE,MAAM,GACtB,EAAE,gBAAgB,GAAG,SAAS,CAc9B;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,GAChD,YAAY,CAoCd;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CASxD;AAED,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,gBAAgB,EAAE,SAAS,GAAG,OAAO,CAAC;IACvF,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;CAC1D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,KAAK,EACL,gBAAgB,EAChB,GAAG,IAAI,EACR,EAAE,oBAAoB,GAAG,SAAS,CAIlC"}
@@ -1,10 +1,20 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ /*
3
+ * Role-bound, not palette-bound. Until 0.7.0 these were raw Tailwind palette
4
+ * classes (`bg-emerald-50`, `bg-red-50`, …), which meant the design-system
5
+ * component every app imports was invisible to tenant white-labelling —
6
+ * BrandingProvider mutates the role layer, and these bound below it.
7
+ *
8
+ * Tint is derived from the role colour with a slash-opacity fill plus the
9
+ * AA-safe `*-text` variant for type, so one definition covers light and dark
10
+ * and no `dark:` duplicate is needed.
11
+ */
2
12
  const variantClasses = {
3
- success: 'bg-emerald-50 text-emerald-700 border-emerald-200 dark:bg-emerald-950 dark:text-emerald-300 dark:border-emerald-800',
4
- warning: 'bg-amber-50 text-amber-700 border-amber-200 dark:bg-amber-950 dark:text-amber-300 dark:border-amber-800',
5
- error: 'bg-red-50 text-red-700 border-red-200 dark:bg-red-950 dark:text-red-300 dark:border-red-800',
6
- info: 'bg-sky-50 text-sky-700 border-sky-200 dark:bg-sky-950 dark:text-sky-300 dark:border-sky-800',
7
- purple: 'bg-purple-50 text-purple-700 border-purple-200 dark:bg-purple-950 dark:text-purple-300 dark:border-purple-800',
13
+ success: 'bg-role-success/10 text-success-text border-role-success/30',
14
+ warning: 'bg-role-warning/10 text-warning-text border-role-warning/30',
15
+ error: 'bg-role-error/10 text-error-text border-role-error/30',
16
+ info: 'bg-role-info/10 text-accent-text border-role-info/30',
17
+ secondary: 'bg-role-secondary/10 text-primary-text border-role-secondary/30',
8
18
  neutral: 'bg-muted text-muted-foreground border-border',
9
19
  };
10
20
  const sizeClasses = {
@@ -57,7 +67,7 @@ export function getStatusVariant(status, overrides) {
57
67
  'draft', 'new', 'scheduled', 'open',
58
68
  'applicant', 'interviewing', 'reported',
59
69
  ];
60
- const PURPLE = ['converted', 'promoted', 'shortlisted'];
70
+ const SECONDARY = ['converted', 'promoted', 'shortlisted', 'exported', 'paid', 'qualified'];
61
71
  if (SUCCESS.includes(normalized))
62
72
  return 'success';
63
73
  if (WARNING.includes(normalized))
@@ -66,8 +76,8 @@ export function getStatusVariant(status, overrides) {
66
76
  return 'error';
67
77
  if (INFO.includes(normalized))
68
78
  return 'info';
69
- if (PURPLE.includes(normalized))
70
- return 'purple';
79
+ if (SECONDARY.includes(normalized))
80
+ return 'secondary';
71
81
  return 'neutral';
72
82
  }
73
83
  /**
@@ -1,13 +1,13 @@
1
- export { ThemeProvider } from './ThemeProvider';
2
- export type { ThemeProviderProps } from './ThemeProvider';
3
- export { useTheme } from './useTheme';
4
- export type { ThemeContextValue, ThemeMode, ResolvedTheme } from '../index';
5
- export { THEME_STORAGE_KEY } from '../index';
6
- export { BrandingProvider, BrandingContext, BRANDING_STORAGE_KEY, BRANDING_OVERRIDE_FLAG, } from './BrandingProvider';
7
- export type { TenantBranding, BrandingContextValue } from './BrandingProvider';
8
- export { useBranding } from './useBranding';
9
- export { resolvePlatformLogo, usePlatformLogo } from './usePlatformLogo';
10
- export type { PlatformLogoHookResult, PlatformLogoOptions, PlatformLogoScheme, PlatformLogoSlot, PlatformLogoSource, ResolvedPlatformLogo, } from './usePlatformLogo';
11
- export { StatusBadge, AutoStatusBadge, getStatusVariant, formatStatusLabel, } from './components/StatusBadge';
12
- export type { BadgeVariant, StatusBadgeProps, AutoStatusBadgeProps, } from './components/StatusBadge';
1
+ export { ThemeProvider } from './ThemeProvider.js';
2
+ export type { ThemeProviderProps } from './ThemeProvider.js';
3
+ export { useTheme } from './useTheme.js';
4
+ export type { ThemeContextValue, ThemeMode, ResolvedTheme } from '../index.js';
5
+ export { THEME_STORAGE_KEY } from '../index.js';
6
+ export { BrandingProvider, BrandingContext, BRANDING_STORAGE_KEY, BRANDING_OVERRIDE_FLAG, } from './BrandingProvider.js';
7
+ export type { TenantBranding, BrandingContextValue } from './BrandingProvider.js';
8
+ export { useBranding } from './useBranding.js';
9
+ export { resolvePlatformLogo, usePlatformLogo } from './usePlatformLogo.js';
10
+ export type { PlatformLogoHookResult, PlatformLogoOptions, PlatformLogoScheme, PlatformLogoSlot, PlatformLogoSource, ResolvedPlatformLogo, } from './usePlatformLogo.js';
11
+ export { StatusBadge, AutoStatusBadge, getStatusVariant, formatStatusLabel, } from './components/StatusBadge.js';
12
+ export type { BadgeVariant, StatusBadgeProps, AutoStatusBadgeProps, } from './components/StatusBadge.js';
13
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,YAAY,EAAE,iBAAiB,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAC9E,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACxE,YAAY,EACV,sBAAsB,EACtB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EACL,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,0BAA0B,CAAA;AACjC,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,0BAA0B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,YAAY,EAAE,iBAAiB,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,uBAAuB,CAAA;AAC9B,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC3E,YAAY,EACV,sBAAsB,EACtB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EACL,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,6BAA6B,CAAA;AACpC,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,6BAA6B,CAAA"}
@@ -1,8 +1,8 @@
1
- export { ThemeProvider } from './ThemeProvider';
2
- export { useTheme } from './useTheme';
3
- export { THEME_STORAGE_KEY } from '../index';
4
- export { BrandingProvider, BrandingContext, BRANDING_STORAGE_KEY, BRANDING_OVERRIDE_FLAG, } from './BrandingProvider';
5
- export { useBranding } from './useBranding';
6
- export { resolvePlatformLogo, usePlatformLogo } from './usePlatformLogo';
1
+ export { ThemeProvider } from './ThemeProvider.js';
2
+ export { useTheme } from './useTheme.js';
3
+ export { THEME_STORAGE_KEY } from '../index.js';
4
+ export { BrandingProvider, BrandingContext, BRANDING_STORAGE_KEY, BRANDING_OVERRIDE_FLAG, } from './BrandingProvider.js';
5
+ export { useBranding } from './useBranding.js';
6
+ export { resolvePlatformLogo, usePlatformLogo } from './usePlatformLogo.js';
7
7
  // Components — see ./components/<Name>.tsx
8
- export { StatusBadge, AutoStatusBadge, getStatusVariant, formatStatusLabel, } from './components/StatusBadge';
8
+ export { StatusBadge, AutoStatusBadge, getStatusVariant, formatStatusLabel, } from './components/StatusBadge.js';
@@ -7,5 +7,5 @@
7
7
  * const { branding, isLoading } = useBranding()
8
8
  * const logoUrl = branding?.logo_url ?? '/logos/default-logo.svg'
9
9
  */
10
- export declare function useBranding(): import("./BrandingProvider").BrandingContextValue;
10
+ export declare function useBranding(): import("./BrandingProvider.js").BrandingContextValue;
11
11
  //# sourceMappingURL=useBranding.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useBranding.d.ts","sourceRoot":"","sources":["../../src/react/useBranding.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,wBAAgB,WAAW,sDAM1B"}
1
+ {"version":3,"file":"useBranding.d.ts","sourceRoot":"","sources":["../../src/react/useBranding.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,wBAAgB,WAAW,yDAM1B"}
@@ -1,5 +1,5 @@
1
1
  import { useContext } from 'react';
2
- import { BrandingContext } from './BrandingProvider';
2
+ import { BrandingContext } from './BrandingProvider.js';
3
3
  /**
4
4
  * Access the current tenant branding values and loading state.
5
5
  *
@@ -1,4 +1,4 @@
1
- import type { TenantBranding } from './BrandingProvider';
1
+ import type { TenantBranding } from './BrandingProvider.js';
2
2
  export type PlatformLogoSlot = 'header' | 'sidebar' | 'auth' | 'favicon' | 'mark';
3
3
  export type PlatformLogoScheme = 'light' | 'dark';
4
4
  export type PlatformLogoSource = 'branding' | 'fallback' | 'none';
@@ -1 +1 @@
1
- {"version":3,"file":"usePlatformLogo.d.ts","sourceRoot":"","sources":["../../src/react/usePlatformLogo.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAGxD,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAA;AACjF,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,CAAA;AACjD,MAAM,MAAM,kBAAkB,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,CAAA;AAEjE,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,gBAAgB,CAAA;IACvB,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAA;IACjE,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,gBAAgB,CAAA;IACtB,MAAM,EAAE,kBAAkB,CAAA;IAC1B,MAAM,EAAE,kBAAkB,CAAA;IAC1B,YAAY,EAAE,OAAO,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,sBAAuB,SAAQ,oBAAoB;IAClE,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAA;IAC/B,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;IACnB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7B;AAqDD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,EAC3C,OAAO,GAAE,mBAAwB,GAChC,oBAAoB,CAiBtB;AAED,wBAAgB,eAAe,CAAC,OAAO,GAAE,mBAAwB,GAAG,sBAAsB,CAczF"}
1
+ {"version":3,"file":"usePlatformLogo.d.ts","sourceRoot":"","sources":["../../src/react/usePlatformLogo.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAG3D,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAA;AACjF,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,CAAA;AACjD,MAAM,MAAM,kBAAkB,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,CAAA;AAEjE,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,gBAAgB,CAAA;IACvB,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAA;IACjE,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,gBAAgB,CAAA;IACtB,MAAM,EAAE,kBAAkB,CAAA;IAC1B,MAAM,EAAE,kBAAkB,CAAA;IAC1B,YAAY,EAAE,OAAO,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,sBAAuB,SAAQ,oBAAoB;IAClE,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAA;IAC/B,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;IACnB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7B;AAqDD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,EAC3C,OAAO,GAAE,mBAAwB,GAChC,oBAAoB,CAiBtB;AAED,wBAAgB,eAAe,CAAC,OAAO,GAAE,mBAAwB,GAAG,sBAAsB,CAczF"}
@@ -1,5 +1,5 @@
1
1
  import { useMemo } from 'react';
2
- import { useBranding } from './useBranding';
2
+ import { useBranding } from './useBranding.js';
3
3
  function cleanUrl(value) {
4
4
  const trimmed = value?.trim();
5
5
  return trimmed ? trimmed : null;
@@ -1,4 +1,4 @@
1
- import type { ThemeContextValue } from '../index';
1
+ import type { ThemeContextValue } from '../index.js';
2
2
  /**
3
3
  * Hook to read + update the current theme.
4
4
  *
@@ -1 +1 @@
1
- {"version":3,"file":"useTheme.d.ts","sourceRoot":"","sources":["../../src/react/useTheme.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAGjD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,QAAQ,IAAI,iBAAiB,CAU5C"}
1
+ {"version":3,"file":"useTheme.d.ts","sourceRoot":"","sources":["../../src/react/useTheme.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAGpD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,QAAQ,IAAI,iBAAiB,CAU5C"}
@@ -1,5 +1,5 @@
1
1
  import { useContext } from 'react';
2
- import { ThemeContext } from './ThemeProvider';
2
+ import { ThemeContext } from './ThemeProvider.js';
3
3
  /**
4
4
  * Hook to read + update the current theme.
5
5
  *
package/dist/ssr/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { THEME_STORAGE_KEY } from '../index';
1
+ import { THEME_STORAGE_KEY } from '../index.js';
2
2
  /**
3
3
  * Returns a self-contained JavaScript string that — when executed before
4
4
  * your React app hydrates — applies the correct `.dark` or `.light` class
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsuite/theme",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "type": "module",
5
5
  "license": "UNLICENSED",
6
6
  "publishConfig": {
@@ -15,7 +15,6 @@
15
15
  "files": [
16
16
  "dist",
17
17
  "src/css",
18
- "src/tailwind-preset.js",
19
18
  "src/preset-v4.css"
20
19
  ],
21
20
  "main": "dist/index.js",
@@ -33,7 +32,6 @@
33
32
  "import": "./dist/ssr/index.js",
34
33
  "types": "./dist/ssr/index.d.ts"
35
34
  },
36
- "./tailwind-preset": "./src/tailwind-preset.js",
37
35
  "./preset-v4.css": "./src/preset-v4.css",
38
36
  "./css": "./src/css/index.css",
39
37
  "./vars.css": "./src/css/vars.css",
@@ -78,7 +78,7 @@
78
78
  ============================================================ */
79
79
  --braden-light-bg-body: oklch(0.980 0.002 50); /* warm white */
80
80
  --braden-light-bg-surface: oklch(0.996 0.001 50); /* near white */
81
- --braden-light-bg-panel: oklch(1.000 0 0); /* white */
81
+ --braden-light-bg-panel: oklch(0.994 0.002 250); /* near-white; pure white is banned in every role */
82
82
  --braden-light-bg-input: oklch(0.972 0.003 250); /* cool light grey */
83
83
 
84
84
  /* Braden light text scale — hue 250 (navy cast), capped L=0.22 */
@@ -161,9 +161,9 @@
161
161
  /* ============================================================
162
162
  SHADOWS — corporate subtle, no neon glow
163
163
  ============================================================ */
164
- --shadow-sm: 0 1px 2px oklch(0 0 0 / 0.08);
165
- --shadow-md: 0 4px 6px oklch(0 0 0 / 0.10), 0 2px 4px oklch(0 0 0 / 0.06);
166
- --shadow-lg: 0 10px 15px oklch(0 0 0 / 0.10), 0 4px 6px oklch(0 0 0 / 0.05);
164
+ --shadow-sm: 0 1px 2px oklch(0.30 0.03 250 / 0.08);
165
+ --shadow-md: 0 4px 6px oklch(0.30 0.03 250 / 0.10), 0 2px 4px oklch(0.30 0.03 250 / 0.06);
166
+ --shadow-lg: 0 10px 15px oklch(0.30 0.03 250 / 0.10), 0 4px 6px oklch(0.30 0.03 250 / 0.05);
167
167
 
168
168
  /* Card glow is a dark-mode-only device (see .dark below); light mode
169
169
  stays border-only, consistent with the corporate "no neon glow" rule. */
package/src/css/index.css CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * @bsuite/theme — root CSS entry point (D2C Neon Electric brand)
3
- * Version 0.3.0
3
+ * Version 0.6.0
4
4
  *
5
5
  * DUAL-BRAND ENTRY POINTS:
6
6
  *
@@ -47,6 +47,50 @@
47
47
  box-shadow 300ms ease;
48
48
  }
49
49
 
50
+ /* ============================================================
51
+ CANONICAL ACCENT GRADIENT — W3 §3.1
52
+ Exactly ONE gradient exists suite-wide: --role-primary -> --role-accent
53
+ (Electric Blue -> Cyan by default; follows tenant BrandingProvider
54
+ overrides automatically via the var() chain). Marketing/pre-auth hero
55
+ surfaces ONLY — never functional text, labels, or body copy. Apply to
56
+ a decorative element (underline, badge, background swatch) or to text
57
+ via `background-clip: text` at the call site — this utility only
58
+ supplies the gradient itself.
59
+ ============================================================ */
60
+ .bsuite-accent-gradient {
61
+ background-image: var(--gradient-accent);
62
+ }
63
+
64
+ /* ============================================================
65
+ HERO GRID — W3 §3.3 grid/dot doctrine
66
+ Public/pre-auth marketing hero bands ONLY. Localised to the hero
67
+ wrapper (which must be `position: relative`); never full-viewport,
68
+ never behind authenticated content. Mutually exclusive with the DOT
69
+ pattern (packages/ui DotPattern), which is authenticated-shell-only.
70
+ Consumed via the <HeroGrid> component in @bsuite/ui (packages/ui/src/
71
+ hero-grid.tsx) — do not hand-roll this pattern; the grid/dot lint rule
72
+ (@bsuite/dry-lint no-grid-dot-doctrine-violation) flags duplicates.
73
+ Lifted verbatim from braden's `.platform-hero-grid`
74
+ (braden/src/index.css) so the corporate and D2C marketing surfaces
75
+ share one visual language for this specific device.
76
+ ============================================================ */
77
+ /* Grid lines are hue-matched to the surface, never pure black/white — the
78
+ contract bans both endpoints in every role, alpha forms included. Light
79
+ mode stays neutral and quiet; dark mode takes a faint accent cast, which
80
+ is where the cyber register lives. 32px = the pre-auth marketing tile. */
81
+ .bsuite-hero-grid {
82
+ position: absolute;
83
+ inset: 0;
84
+ --grid-line: oklch(0.40 0.030 258 / 0.07);
85
+ background-image:
86
+ linear-gradient(var(--grid-line) 1px, transparent 1px),
87
+ linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
88
+ background-size: 32px 32px;
89
+ }
90
+ .dark .bsuite-hero-grid {
91
+ --grid-line: oklch(0.82 0.020 262 / 0.055);
92
+ }
93
+
50
94
  /* ===== prefers-reduced-motion — cap animation duration ===== */
51
95
  @media (prefers-reduced-motion: reduce) {
52
96
  *,