@hex-core/themes
Premium theme catalog — midnight, ember, and future presets.
Install
0.1.1Runtime dependencypnpm add @hex-core/themesWhat it does
`@hex-core/themes` is the premium-theme catalog. Today it re-exports `midnightTheme` and `emberTheme` from `@hex-core/tokens` and adds catalog helpers shaped to mirror `tokens.listThemes()`. Future presets — `fintech-dark`, `editorial-warm`, `data-dense`, `pastel-soft`, `monochrome-strict` — land here without bumping `tokens`.
The split exists for release independence. `@hex-core/tokens` ships the foundational three themes plus the transformers; tagging a new preset shouldn't force every consumer to retest the transformers. Keeping the catalog separate gives both surfaces their own minor cadence.
If you only need the default theme, depend on `tokens` and skip this package. If you want the studio's full theme switcher (or want your own switcher to discover new presets automatically), depend on `themes`.
Public API
premiumThemes
import { premiumThemes } from "@hex-core/themes";
import type { Theme } from "@hex-core/registry";
declare const premiumThemes: Record<string, Theme>;Catalog object keyed by theme name. Re-exports `midnightTheme` + `emberTheme` from `@hex-core/tokens` and adds future premium presets here without tokens needing a release.
import { premiumThemes } from "@hex-core/themes";
console.log(Object.keys(premiumThemes));
// → ["midnight", "ember"]listPremiumThemes
function listPremiumThemes(): readonly { name: string; theme: Theme }[];Enumerate the catalog. Mirrors the shape of `tokens.listThemes()` so the studio's theme switcher can concat the two arrays without normalizing.
import { listPremiumThemes } from "@hex-core/themes";
for (const { name, theme } of listPremiumThemes()) {
console.log(name, theme.tokens.light["--color-background"].value);
}getPremiumTheme
function getPremiumTheme(name: string): Theme | undefined;Look up a single premium theme by name. Returns `undefined` if the name isn't in the catalog — callers should fall back to `defaultTheme` from `tokens`.
import { getPremiumTheme } from "@hex-core/themes";
import { defaultTheme } from "@hex-core/tokens";
const theme = getPremiumTheme(slug) ?? defaultTheme;Workflows
Build a unified theme switcher across both packages
Concat the two catalogs and dedupe by name. Drop into the studio sidebar or any settings panel.
import { listThemes } from "@hex-core/tokens";
import { listPremiumThemes } from "@hex-core/themes";
const all = [...listThemes(), ...listPremiumThemes()];
const byName = new Map(all.map((entry) => [entry.name, entry]));
export function ThemePicker({ value, onChange }: { value: string; onChange: (n: string) => void }) {
return (
<select value={value} onChange={(e) => onChange(e.target.value)}>
{[...byName.keys()].map((n) => (
<option key={n} value={n}>{n}</option>
))}
</select>
);
}Resolve a theme name to its strict object
Walk the catalogs in order; if neither owns the name, fall back to `defaultTheme`. Pass the result into the `tokens` transformers.
import { defaultTheme, listThemes } from "@hex-core/tokens";
import { getPremiumTheme } from "@hex-core/themes";
import type { Theme } from "@hex-core/registry";
export function resolveTheme(name: string): Theme {
const builtIn = listThemes().find((t) => t.name === name);
if (builtIn) return builtIn.theme;
return getPremiumTheme(name) ?? defaultTheme;
}Compatibility
- Peer-free — depends only on `@hex-core/registry@^0.2.1` and `@hex-core/tokens@^1.2.0`.
- Zero React dependencies. Same edge/runtime story as `@hex-core/tokens`.
- `@hex-core/tokens` continues to export `midnightTheme` and `emberTheme` directly — moving them into `themes` is non-breaking.