Currently applied theme ID (synchronous access)
Observable for the actually applied theme (resolved theme ID)
All registered themes, for UI consumption (e.g. theme picker menus)
The active org brand overlay id, or null if none is applied.
What Initialize applies when nothing is saved: the first theme REGISTERED with
ThemeDefinition.IsDefault (registration order, not registry slot order — re-registering
a built-in slot with the flag does not jump the queue), else 'system'. Public so a picker
can mark the default.
Whether the service has been initialized
Current theme preference (synchronous access)
Observable for user's theme preference (theme ID or 'system')
Reactive list of the user's starred brand theme ids.
Emits after any saved-theme mutation so open dashboards can refresh their lists.
Apply an org brand overlay **independently of the user's light/dark mode. The overlay layers under whatever base theme is active and is re-asserted whenever the user toggles light/dark. Persists the id to localStorage so the pre-paint script restores the attribute on next load.
id of a brand theme registered via RegisterBrandTheme.
Optionaloptions: { persist?: boolean }Optionalpersist?: booleanpass false for session-only overlays backed by Blob URLs
(e.g. Theme Studio's draft workspace preview) — a Blob URL doesn't survive a
reload, so persisting its id would leave the pre-paint script pointing at a
dangling overlay and clobber the user's real persisted selection. Defaults true.
Remove the active org brand overlay (revert to the base MJ tokens).
Scoped to the brand: only the brand's own <link> is disabled and the data-theme-overlay
attribute is dropped only when it still names that brand. Bootstrap calls this on every login
where the org has no active brand, right after Initialize() applied the user's theme, so a
blanket clear would switch off a user's custom theme on any install that never used Theme Studio.
The brand theme the user last applied (or null to follow the org default).
The user's starred brand theme ids (synchronous).
Look up a theme definition by ID. Returns undefined if the theme ID is not registered.
Initialize the theme service. Call after login when UserInfoEngine is available.
Whether a theme id is starred by the user.
Broadcast that the set of saved themes changed (create/rename/delete/duplicate/default).
Register a brand theme from its seeds.
Derives the full --mj-* token contract with @memberjunction/theme-engine, emits
the [data-theme-overlay="<id>"] CSS, and publishes it as a session-scoped Blob
URL that plugs into the existing CssUrl overlay path — so brand themes apply
through the same machinery as file-based custom themes. Returns the derived
theme so callers can surface the a11y contrast report / previews.
The emitted overlay overrides only the primitive ramps (plus viz/shadow/font/
radius); every semantic token and the [data-theme="dark"] block reference those
primitives, so both light and dark re-point automatically off one block.
OptionalbaseTheme?: "light" | "dark"OptionalcustomCss?: string | nullAdvanced: raw CSS appended to the overlay, auto-scoped to this theme.
Optionaldescription?: stringOptionallogos?: ThemeLogosOptional logo variant URLs + geometry, emitted as --mj-logo-*.
Optionaloverrides?: string | Record<string, string> | nullAdvanced: per-token overrides (JSON map or object) merged over the derived vars.
ThemeSeeds object or the entity's Seeds JSON string.
Register a custom theme. If a theme with the same ID already exists, it is replaced (allowing override of built-in themes if desired).
Reset the service (call on logout)
Put the persisted org brand overlay back BEFORE first paint, from localStorage alone — no registry, no database. Call it from the earliest code that runs in the app (the explorer-app constructor), so the sign-in page and the shell's loading screen paint branded on a cold load instead of waiting for bootstrap to re-emit the overlay.
Injects the persisted CSS as a <style> (bootstrap's real <link> replaces it), sets
data-theme-overlay, and records the id so Initialize does not strip the
attribute before bootstrap registers the brand. A CSS entry whose id no longer matches
the persisted overlay id is stale and is dropped. Returns whether anything was restored.
Persist (or clear, with null) the user's chosen brand theme so login restores it.
Set the theme preference and apply it.
A registered theme ID or 'system'
Toggle a theme's starred state and persist to User Settings.
the new starred state (true = now starred).
Service to manage application themes with pluggable custom theme support.
Built-in themes (light/dark) work identically to before. Custom themes inherit from a base theme and overlay additional CSS token overrides via a dynamically loaded stylesheet.
CSS resolution for custom themes (e.g. "Izzy Dark" extending dark):
:rootlight defaults (from _tokens.scss in this package)[data-theme="dark"]dark overrides (from _tokens.scss in this package)[data-theme-overlay="izzy-dark"]custom overrides (loaded dynamically)Follows the DeveloperModeService pattern: