<script lang="ts">
	interface Props {
		label: string;
		hint?: string;
		required?: boolean;
		error?: string;
		children: import('svelte').Snippet;
	}
	let { label, hint, required = false, error, children }: Props = $props();
</script>

<div class="field" class:has-error={!!error}>
	<label>
		{label}
		{#if required}<span class="required" aria-hidden="true">*</span>{/if}
	</label>
	{@render children()}
	{#if error}
		<p class="error-msg">{error}</p>
	{:else if hint}
		<p class="hint">{hint}</p>
	{/if}
</div>

<style>
	.field {
		display: flex;
		flex-direction: column;
		gap: 4px;
	}
	label {
		font-size: var(--font-size-sm);
		font-weight: 500;
		color: var(--text-dim);
		display: flex;
		align-items: center;
		gap: 3px;
	}
	.required {
		color: var(--rose);
		line-height: 1;
	}
	.hint {
		font-size: var(--font-size-xs);
		color: var(--text-muted);
	}
	.error-msg {
		font-size: var(--font-size-xs);
		color: var(--rose);
	}
	.field :global(input),
	.field :global(select),
	.field :global(textarea) {
		background: var(--surface-0);
		border: 1px solid var(--border);
		border-radius: var(--radius);
		padding: 7px 10px;
		color: var(--text);
		transition: border-color var(--duration) var(--ease);
	}
	.field :global(input:focus),
	.field :global(select:focus),
	.field :global(textarea:focus) {
		outline: none;
		border-color: var(--border-focus);
	}
	.has-error :global(input),
	.has-error :global(select),
	.has-error :global(textarea) {
		border-color: var(--rose);
	}
	.has-error :global(input:focus),
	.has-error :global(select:focus),
	.has-error :global(textarea:focus) {
		border-color: var(--rose);
	}
	.field :global(textarea) {
		resize: vertical;
		min-height: 80px;
		font-family: var(--font-mono);
		font-size: var(--font-size-sm);
	}
</style>
