<script module lang="ts">
	import { tv, type VariantProps } from "tailwind-variants";
	import type { SvelteHTMLElements } from "svelte/elements";

	export const typography = tv({
		base: "font-sans text-foreground-default",
		variants: {
			variant: {
				h0: "typography-heading-0",
				h1: "typography-heading-1",
				h2: "typography-heading-2",
				h3: "typography-heading-3",
				h4: "typography-heading-4",
				large: "typography-paragraph-large",
				regular: "typography-paragraph-regular",
				small: "typography-paragraph-small",
				mini: "typography-paragraph-mini",
				"mono-large": "font-mono typography-monospace-large font-normal",
				mono: "font-mono typography-monospace-regular font-normal",
				"mono-small": "font-mono typography-monospace-small font-normal"
			},
			weight: {
				regular: "",
				semibold: "",
				bold: ""
			}
		},
		compoundVariants: (["large", "regular", "small", "mini"] as const).flatMap((variant) => [
			{ variant, weight: "regular" as const, class: "font-normal" },
			{ variant, weight: "semibold" as const, class: "font-medium" },
			{ variant, weight: "bold" as const, class: "font-semibold" }
		]),
		defaultVariants: {
			variant: "regular",
			weight: "regular"
		}
	});

	export type TypographyVariants = VariantProps<typeof typography>;

	const defaultTag = {
		h0: "h1",
		h1: "h1",
		h2: "h2",
		h3: "h3",
		h4: "h4",
		large: "p",
		regular: "p",
		small: "span",
		mini: "span",
		"mono-large": "code",
		mono: "code",
		"mono-small": "code"
	} as const satisfies Record<NonNullable<TypographyVariants["variant"]>, keyof SvelteHTMLElements>;
</script>

<script lang="ts">
	import type { Snippet } from "svelte";

	interface Props {
		variant?: TypographyVariants["variant"];
		weight?: TypographyVariants["weight"];
		as?: keyof SvelteHTMLElements;
		class?: string;
		children: Snippet;
	}

	let { variant = "regular", weight = "regular", as, class: className, children }: Props = $props();

	const tag = $derived(as ?? defaultTag[variant ?? "regular"]);
	const classes = $derived(typography({ variant, weight, class: className }));
</script>

<svelte:element this={tag} class={classes}>
	{@render children()}
</svelte:element>
