hypnagaga/src/components/Theme/Theme.svelte
2025-03-24 09:57:10 -07:00

53 lines
1.6 KiB
Svelte

<!-- @component `Theme` [Read the docs.](https://reuters-graphics.github.io/graphics-components/?path=/docs/components-theming-theme--docs) -->
<script module lang="ts">
import light from './themes/light.js';
import dark from './themes/dark.js';
/**
* Pre-made themes you can import.
* @type {{ light, dark }}
*/
export const themes = { light, dark };
</script>
<script lang="ts">
import type { CustomTheme } from './@types/component';
type Base = 'light' | 'dark';
import flatten from './utils/flatten';
import mergeThemes from './utils/merge';
interface Props {
/** Custom theme object. Can be a partial theme with just
* what you want to change.
*/
theme?: CustomTheme;
/**
* Base theme is one of `light` or `dark` and will be merged
* with your custom theme to fill in any values you don't
* explicitly set.
*/
base?: Base;
children?: import('svelte').Snippet;
}
let { theme = {}, base = 'light', children }: Props = $props();
/** @type {Theme} */
let mergedTheme = $derived(
mergeThemes({}, themes[base] || themes.light, theme)
);
let cssVariables = $derived(
Object.entries(flatten({ theme: mergedTheme }))
.map(([key, value]) => `--${key}: ${value};`)
.join(' ')
);
</script>
<div class="theme" style={cssVariables} style:display="contents">
<!-- Clients can override the theme above by attaching custom properties to this element. -->
<div class="theme-client-override" style="display: contents;">
<!-- Themed content -->
{@render children?.()}
</div>
</div>