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

	export const field = tv({
		slots: {
			root: "flex flex-col gap-1.5",
			label: "typography-paragraph-small font-medium text-foreground-default",
			subtitle: "typography-paragraph-small text-foreground-muted"
		},
		variants: {
			// settings forms label their fields in small caps; the onboarding steps use
			// sentence case, so the casing is a variant rather than baked into the slot
			labelCase: {
				upper: { label: "tracking-wide uppercase" },
				normal: { label: "" }
			}
		},
		defaultVariants: {
			labelCase: "upper"
		}
	});

	export type FieldVariants = VariantProps<typeof field>;
</script>

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

	interface Props extends Omit<HTMLAttributes<HTMLDivElement>, "class" | "children"> {
		label?: string;
		subtitle?: string;
		for?: string;
		required?: boolean;
		labelCase?: FieldVariants["labelCase"];
		class?: string;
		children: Snippet<[{ id: string }]>;
	}

	let {
		label,
		subtitle,
		for: forId,
		required = false,
		labelCase = "upper",
		class: className,
		children,
		...rest
	}: Props = $props();

	const generatedId = $props.id();
	const id = $derived(forId ?? generatedId);
	const slot = $derived(field({ labelCase }));
</script>

<div class={slot.root({ class: className })} {...rest}>
	{#if label}
		<label for={id} class={slot.label()}>
			{label}
			{#if required}
				<span class="text-foreground-danger">*</span>
			{/if}
		</label>
	{/if}
	{@render children({ id })}
	{#if subtitle}
		<p class={slot.subtitle()}>{subtitle}</p>
	{/if}
</div>
