Buckets:
| import { TextField as Kobalte } from "@kobalte/core/text-field" | |
| import { createSignal, Show, splitProps } from "solid-js" | |
| import type { ComponentProps } from "solid-js" | |
| import { useI18n } from "../context/i18n" | |
| import { IconButton } from "./icon-button" | |
| import { Tooltip } from "./tooltip" | |
| export interface TextFieldProps | |
| extends ComponentProps<typeof Kobalte.Input>, | |
| Partial< | |
| Pick< | |
| ComponentProps<typeof Kobalte>, | |
| | "name" | |
| | "defaultValue" | |
| | "value" | |
| | "onChange" | |
| | "onKeyDown" | |
| | "validationState" | |
| | "required" | |
| | "disabled" | |
| | "readOnly" | |
| > | |
| > { | |
| label?: string | |
| hideLabel?: boolean | |
| description?: string | |
| error?: string | |
| variant?: "normal" | "ghost" | |
| copyable?: boolean | |
| copyKind?: "clipboard" | "link" | |
| multiline?: boolean | |
| } | |
| export function TextField(props: TextFieldProps) { | |
| const i18n = useI18n() | |
| const [local, others] = splitProps(props, [ | |
| "name", | |
| "defaultValue", | |
| "value", | |
| "onChange", | |
| "onKeyDown", | |
| "validationState", | |
| "required", | |
| "disabled", | |
| "readOnly", | |
| "class", | |
| "label", | |
| "hideLabel", | |
| "description", | |
| "error", | |
| "variant", | |
| "copyable", | |
| "copyKind", | |
| "multiline", | |
| ]) | |
| const [copied, setCopied] = createSignal(false) | |
| const label = () => { | |
| if (copied()) return i18n.t("ui.textField.copied") | |
| if (local.copyKind === "link") return i18n.t("ui.textField.copyLink") | |
| return i18n.t("ui.textField.copyToClipboard") | |
| } | |
| const icon = () => { | |
| if (copied()) return "check" | |
| if (local.copyKind === "link") return "link" | |
| return "copy" | |
| } | |
| async function handleCopy() { | |
| const value = local.value ?? local.defaultValue ?? "" | |
| await navigator.clipboard.writeText(value) | |
| setCopied(true) | |
| setTimeout(() => setCopied(false), 2000) | |
| } | |
| function handleClick() { | |
| if (local.copyable) void handleCopy() | |
| } | |
| return ( | |
| <Kobalte | |
| data-component="input" | |
| data-variant={local.variant || "normal"} | |
| name={local.name} | |
| defaultValue={local.defaultValue} | |
| value={local.value} | |
| onChange={local.onChange} | |
| onKeyDown={local.onKeyDown} | |
| onClick={handleClick} | |
| required={local.required} | |
| disabled={local.disabled} | |
| readOnly={local.readOnly} | |
| validationState={local.validationState} | |
| > | |
| <Show when={local.label}> | |
| <Kobalte.Label data-slot="input-label" classList={{ "sr-only": local.hideLabel }}> | |
| {local.label} | |
| </Kobalte.Label> | |
| </Show> | |
| <div data-slot="input-wrapper"> | |
| <Show | |
| when={local.multiline} | |
| fallback={<Kobalte.Input {...others} data-slot="input-input" class={local.class} />} | |
| > | |
| <Kobalte.TextArea {...others} autoResize data-slot="input-input" class={local.class} /> | |
| </Show> | |
| <Show when={local.copyable}> | |
| <Tooltip value={label()} placement="top" gutter={4} forceOpen={copied()} skipDelayDuration={0}> | |
| <IconButton | |
| type="button" | |
| icon={icon()} | |
| variant="ghost" | |
| onClick={handleCopy} | |
| tabIndex={-1} | |
| data-slot="input-copy-button" | |
| aria-label={label()} | |
| /> | |
| </Tooltip> | |
| </Show> | |
| </div> | |
| <Show when={local.description}> | |
| <Kobalte.Description data-slot="input-description">{local.description}</Kobalte.Description> | |
| </Show> | |
| <Kobalte.ErrorMessage data-slot="input-error">{local.error}</Kobalte.ErrorMessage> | |
| </Kobalte> | |
| ) | |
| } | |
Xet Storage Details
- Size:
- 3.56 kB
- Xet hash:
- 3758fcdc526ad6d2cedaa6583cbf5479881f1e0244c5e0a97b7531da7f13ba2f
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.