53 lines
1.6 KiB
Svelte
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>
|