Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152<script lang="ts"> import type { Component, Snippet } from "svelte"; import type { HTMLInputAttributes, SvelteHTMLElements } from "svelte/elements"; import { inputField, type InputFieldVariants, type InputTag, type TagCommitKey } from "$lib/components/ui/inputField"; import Spinner from "$lib/components/ui/Spinner.svelte"; import TagInput from "$lib/components/ui/TagInput.svelte";
interface Props extends Omit<HTMLInputAttributes, "class" | "value" | "size" | "list"> { value?: string; size?: InputFieldVariants["size"]; error?: boolean; disabled?: boolean; loading?: boolean; iconLeft?: Component<SvelteHTMLElements["svg"]>; iconRight?: Component<SvelteHTMLElements["svg"]>; suffix?: string; /** classes for the suffix element; override the default muted text, e.g. a gray chip */ suffixClass?: string; suffixInline?: boolean; element?: HTMLInputElement; class?: string; rich?: boolean; // rich only tags?: InputTag[]; maxTags?: number; commitOn?: TagCommitKey[]; allowDuplicates?: boolean; validate?: (value: string) => boolean | string; suggestions?: InputTag[]; onSearch?: (query: string) => void; onAdd?: (tag: InputTag) => void; onRemove?: (tag: InputTag) => void; hint?: string; emptyLabel?: string; label?: string; panelClass?: string; tag?: Snippet<[InputTag]>; suggestion?: Snippet<[InputTag]>; }
let { value = $bindable(""), size = "regular", error = false, disabled = false, loading = false, iconLeft, iconRight, suffix, suffixClass, suffixInline = false, element = $bindable(), class: className, rich = false, tags = $bindable([]), maxTags, commitOn, allowDuplicates, validate, suggestions, onSearch, onAdd, onRemove, hint, emptyLabel, label, panelClass, tag, suggestion, ...rest }: Props = $props();
const classes = $derived(inputField({ size, error, disabled, class: className })); const iconSize = $derived( size === "large" ? "size-4" : size === "mini" ? "size-3" : "size-3.5" ); const mirror = $derived(value || (rest.placeholder ?? ""));</script>
{#if rich} <TagInput bind:tags bind:value bind:element {size} {error} {disabled} {loading} {iconLeft} {maxTags} {commitOn} {allowDuplicates} {validate} {suggestions} {onSearch} {onAdd} {onRemove} {hint} {emptyLabel} {label} {panelClass} {tag} {suggestion} class={className} {...rest} />{:else} <div class={classes}> {#if iconLeft} {@const IconLeft = iconLeft} <IconLeft class="{iconSize} shrink-0 text-foreground-subtle" aria-hidden="true" /> {/if} {#snippet field(sizing: string)} <input bind:this={element} bind:value {disabled} aria-invalid={error} aria-busy={loading} aria-label={label} class="mt-px min-w-0 bg-transparent outline-none placeholder:text-foreground-placeholder disabled:cursor-not-allowed {sizing}" {...rest} /> {/snippet} {#if suffix && suffixInline} <span class="relative min-w-0 shrink"> <span class="invisible block pr-px whitespace-pre" aria-hidden="true">{mirror}</span > {@render field("absolute inset-0 w-full")} </span> {:else} {@render field("flex-1")} {/if} {#if suffix} <span class="shrink-0 select-none {suffixClass ?? 'text-foreground-muted'}" >{suffix}</span > {/if} {#if loading} <Spinner class="{iconSize} shrink-0" /> {:else if iconRight} {@const IconRight = iconRight} <IconRight class="{iconSize} shrink-0 text-foreground-subtle" aria-hidden="true" /> {/if} </div>{/if}