import { EventEmitter } from '../../stencil-public-runtime'; import type { FileInputChangeDetail, FileInputDropDetail, FileInputErrorDetail, FileInputRemoveDetail, FileInputSize, FileInputVariant } from './mud-file-input.types'; /** * File Input — drag-and-drop / click-to-browse file selection molecule. * * Pattern B (molecule, internal DOM, form-associated): the host owns a hidden * native `` for the browse path, manages the drop zone * affordance, validates by `accept` / `maxSize` / `maxFiles`, and renders a * per-file list of `mud-file-item` rows. Citizens get keyboard parity (Tab * to focus, Enter/Space to open the picker) and a `role="status"` live region * that announces add / remove / reject events. * * The component owns SELECTION + VALIDATION + DISPLAY. Real upload (progress, * network errors, retries) is consumer-driven via the `mudChange` event. * * State model (no style axis — Figma is state-only): * default → hover → focus → active (drag-over) → disabled * `invalid` is a separate validation flag that recolors the dashed border red * without introducing a style variant. * * @element mud-file-input * * @slot label - Rich label content, replaces the `label` prop when present. * @slot helper - Rich helper / hint content, replaces the `helper-text` prop. * @slot icon - Override the centre drop-zone icon-glyph inside the circle. * Defaults to `mud-icon name="cloud-upload"`. */ export declare class MudFileInput { /** * Visual size rung. Drives drop-zone min-height + label / icon scale. * @default 'md' */ size: FileInputSize; /** * Presentation. `dropzone` (default) shows the dashed drag-and-drop area; * `button` shows a plain "Choose file" button (the Figma "Upload Button"). * Both share the same file list, captions and validation. * @default 'dropzone' */ variant: FileInputVariant; /** Disables interactivity — drop zone ignores drops, button is blocked. */ disabled: boolean; /** Marks the field as mandatory. Adds the red asterisk + `aria-required`. */ required: boolean; /** Renders the red-border error treatment + wires `aria-invalid`. */ invalid: boolean; /** Allow selecting more than one file. */ multiple: boolean; /** Native HTML `accept` attribute — MIME types and/or extensions, comma-separated. */ accept?: string; /** Maximum per-file size in bytes; files above are rejected with `code='size'`. */ maxSize?: number; /** Maximum number of files accepted when `multiple` is set. */ maxFiles?: number; /** Form-control `name`. Used during form submission. */ name?: string; /** Plain-text label. Use the `label` slot for richer content. */ label?: string; /** Plain-text helper / hint shown below the drop zone. */ helperText?: string; /** Plain-text error message shown below the drop zone when `invalid` is set. */ errorText?: string; /** * Lead-in CTA body text inside the drop area at rest. Renders BEFORE the * brand-blue inline link. The trailing space is intentional — the link * follows on the same line. * @default 'Trage și plasează sau ' */ ctaText: string; /** * Label for the inline "choose files" link. Rendered as an underlined * brand-blue button that opens the native file picker. * @default 'Alege fișiere' */ chooseFilesText: string; /** * Body text shown while a drag is over the drop zone (Figma "Active" state). * Replaces the resting body + hides the icon for the duration of the drag. * @default 'Eliberează pentru a încărca' */ dropzoneActiveText: string; /** * Top-left caption inside the field row, shown below the dropzone. When * unset and `accept` is provided, this is derived from `accept` as * `Formate acceptate: jpg, png, pdf`. Explicit prop wins. */ supportedFormatsText?: string; /** * Top-right caption inside the field row, shown below the dropzone. When * unset and `maxSize` is provided, this is derived from `maxSize` (bytes) * as `Mărime maximă: 100 MB`. Explicit prop wins. */ maxSizeText?: string; /** * Currently accepted files. Two-way bound: assigning a new array rerenders * the list, the citizen interacting fires events that the consumer may use * to mutate this array externally. */ files: File[]; /** * Accessible name; mirrors to the drop zone's `aria-label` when no visible * label is provided. Setting `aria-label` directly on the host also works — * captured on connect into `resolvedAriaLabel` and stripped to avoid * Stencil's attribute-observer / render-loop antipattern (same pattern as * mud-radio / mud-switch / mud-tooltip / mud-accordion / mud-breadcrumb / * mud-date-picker / mud-modal / mud-pagination / mud-receipt). */ ariaLabel?: string; private hasLabelSlot; private hasHelperSlot; /** Tracks drag-over. Maps to Figma's "Active" state visually. */ private isActive; private isFocused; private fieldsetDisabled; private announcement; private resolvedAriaLabel?; host: HTMLMudFileInputElement; internals: ElementInternals; /** Fires when the accepted file list changes (browse OR drop OR remove). */ mudChange: EventEmitter; /** Fires when a drag enters the drop zone. */ mudDragEnter: EventEmitter; /** Fires when the drag leaves the drop zone. */ mudDragLeave: EventEmitter; /** Fires after a drop, with the accepted / rejected split + the first rejection reason. */ mudDrop: EventEmitter; /** Fires when a file is removed from the inline list. */ mudRemove: EventEmitter; /** Fires for every rejected file (size / type / count). One event per file. */ mudError: EventEmitter; private readonly instanceId; private readonly labelId; private readonly helperId; private readonly errorId; private readonly dropzoneId; private readonly liveId; private nativeInput?; /** Drag enters/leaves fire for child elements too; counter-tracking keeps `isActive` stable. */ private dragDepth; /** Object URLs created for image-preview thumbnails, keyed by File for revocation. */ private previewUrls; componentWillLoad(): void; componentWillRender(): void; disconnectedCallback(): void; /** * Keep the object-URL map in step with `files`: mint a thumbnail URL for every * image file and revoke any whose file left the list. Non-image files keep the * document glyph. Runs in `componentWillRender` so it's idempotent and never leaks. */ private syncPreviewUrls; private captureAriaLabel; protected syncAriaLabelProp(next?: string): void; protected onRequiredChange(): void; validateSize(next: FileInputSize): void; validateVariant(next: FileInputVariant): void; handleFilesChange(next: File[]): void; formDisabledCallback(disabled: boolean): void; formResetCallback(): void; formStateRestoreCallback(state: FormData | string | File | null): void; private syncFormValue; /** * Mirror the component's validation state onto `ElementInternals` so the * native form submission flow respects `required`. Without this, a required * file-input could submit with zero files because the browser asks * `internals.validity`, not the visual `invalid` prop. Anchor on the hidden * native input so focus/scroll-into-view works during constraint validation. */ private syncValidity; private onLabelSlotChange; private onHelperSlotChange; private slotHasContent; private isInert; private hasVisibleLabel; private hasErrorMessage; private hasHelperMessage; private describedBy; private validateFile; private reasonMessage; private intakeFiles; private handleBrowseClick; private handleNativeChange; private handleDragEnter; private handleDragOver; private handleDragLeave; private handleDrop; private handleFocus; private handleBlur; /** * Click handler for the inline "choose files" link. Opens the native file * picker. Calls `stopPropagation` so the dropzone wrapper does not also * fire its own click handler (which would open the picker a second time). */ private handleChooseFilesClick; /** * Best-effort MIME / extension → short human extension list. * `image/jpeg,image/png,application/pdf` → `jpg, png, pdf`. * `.pdf,.docx` → `pdf, docx`. * Result is lowercase, comma-space separated, de-duplicated. */ private formatsFromAccept; /** * Format bytes as a human-readable size string with one decimal at most. * 5_242_880 → `5 MB`, 1500 → `1.5 KB`, 1_000_000_000 → `1 GB`. */ private formatBytes; private resolvedSupportedFormatsText; private resolvedMaxSizeText; private handleRemove; render(): any; }