/**
 * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
 * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */
/**
 * @module ui/labeledfield/labeledfieldview
 */
import View from '../view.js';
import LabelView from '../label/labelview.js';
import type { FocusableView } from '../focuscycler.js';
import type ViewCollection from '../viewcollection.js';
import { type Locale } from '@ckeditor/ckeditor5-utils';
import '../../theme/components/labeledfield/labeledfieldview.css';
/**
 * The labeled field view class. It can be used to enhance any view with the following features:
 *
 * * a label,
 * * (optional) an error message,
 * * (optional) an info (status) text,
 *
 * all bound logically by proper DOM attributes for UX and accessibility.  It also provides an interface
 * (e.g. observable properties) that allows controlling those additional features.
 *
 * The constructor of this class requires a callback that returns a view to be labeled. The callback
 * is called with unique ids that allow binding of DOM properties:
 *
 * ```ts
 * const labeledInputView = new LabeledFieldView( locale, ( labeledFieldView, viewUid, statusUid ) => {
 * 	const inputView = new InputTextView( labeledFieldView.locale );
 *
 * 	inputView.set( {
 * 		id: viewUid,
 * 		ariaDescribedById: statusUid
 * 	} );
 *
 * 	inputView.bind( 'isReadOnly' ).to( labeledFieldView, 'isEnabled', value => !value );
 * 	inputView.bind( 'hasError' ).to( labeledFieldView, 'errorText', value => !!value );
 *
 * 	return inputView;
 * } );
 *
 * labeledInputView.label = 'User name';
 * labeledInputView.infoText = 'Full name like for instance, John Doe.';
 * labeledInputView.render();
 *
 * document.body.append( labeledInputView.element );
 * ```
 *
 * See {@link module:ui/labeledfield/utils} to discover ready–to–use labeled input helpers for common
 * UI components.
 */
export default class LabeledFieldView<TFieldView extends FocusableView = FocusableView> extends View {
    /**
     * The field view that gets labeled.
     */
    readonly fieldView: TFieldView;
    /**
     * The label view instance that describes the entire view.
     */
    readonly labelView: LabelView;
    /**
     * The status view for the {@link #fieldView}. It displays {@link #errorText} and
     * {@link #infoText}.
     */
    readonly statusView: View;
    /**
     * A collection of children of the internal wrapper element. Allows inserting additional DOM elements (views) next to
     * the {@link #fieldView} for easy styling (e.g. positioning).
     *
     * By default, the collection contains {@link #fieldView} and {@link #labelView}.
     */
    readonly fieldWrapperChildren: ViewCollection;
    /**
     * The text of the label.
     *
     * @observable
     */
    label: string | undefined;
    /**
     * Controls whether the component is in read-only mode.
     *
     * @observable
     */
    isEnabled: boolean;
    /**
     * An observable flag set to `true` when {@link #fieldView} is empty (`false` otherwise).
     *
     * @readonly
     * @observable
     * @default true
     */
    isEmpty: boolean;
    /**
     * An observable flag set to `true` when {@link #fieldView} is currently focused by
     * the user (`false` otherwise).
     *
     * @readonly
     * @observable
     * @default false
     */
    isFocused: boolean;
    /**
     * The validation error text. When set, it will be displayed
     * next to the {@link #fieldView} as a typical validation error message.
     * Set it to `null` to hide the message.
     *
     * **Note:** Setting this property to anything but `null` will automatically
     * make the `hasError` of the {@link #fieldView} `true`.
     *
     * @observable
     */
    errorText: string | null;
    /**
     * The additional information text displayed next to the {@link #fieldView} which can
     * be used to inform the user about its purpose, provide help or hints.
     *
     * Set it to `null` to hide the message.
     *
     * **Note:** This text will be displayed in the same place as {@link #errorText} but the
     * latter always takes precedence: if the {@link #errorText} is set, it replaces
     * {@link #infoText}.
     *
     * @observable
     * @default null
     */
    infoText: string | null;
    /**
     * (Optional) The additional CSS class set on the dropdown {@link #element}.
     *
     * @observable
     */
    class: string | undefined;
    /**
     * The content of the `placeholder` attribute of the {@link #fieldView}.
     *
     * @observable
     */
    placeholder: string | undefined;
    /**
     * The combined status text made of {@link #errorText} and {@link #infoText}.
     * Note that when present, {@link #errorText} always takes precedence in the
     * status.
     *
     * @see #errorText
     * @see #infoText
     * @see #statusView
     * @private
     * @observable
     */
    _statusText: string | null;
    /**
     * Creates an instance of the labeled field view class using a provided creator function
     * that provides the view to be labeled.
     *
     * @param locale The locale instance.
     * @param viewCreator A function that returns a {@link module:ui/view~View}
     * that will be labeled. The following arguments are passed to the creator function:
     *
     * * an instance of the `LabeledFieldView` to allow binding observable properties,
     * * an UID string that connects the {@link #labelView label} and the labeled field view in DOM,
     * * an UID string that connects the {@link #statusView status} and the labeled field view in DOM.
     */
    constructor(locale: Locale | undefined, viewCreator: LabeledFieldViewCreator<TFieldView>);
    /**
     * Creates label view class instance and bind with view.
     *
     * @param id Unique id to set as labelView#for attribute.
     */
    private _createLabelView;
    /**
     * Creates the status view instance. It displays {@link #errorText} and {@link #infoText}
     * next to the {@link #fieldView}. See {@link #_statusText}.
     *
     * @param statusUid Unique id of the status, shared with the {@link #fieldView view's}
     * `aria-describedby` attribute.
     */
    private _createStatusView;
    /**
     * Focuses the {@link #fieldView}.
     */
    focus(direction?: 1 | -1): void;
}
/**
 * A creator function that returns a focusable view to be labeled by a {@link module:ui/labeledfield/labeledfieldview~LabeledFieldView}
 * instance.
 */
export type LabeledFieldViewCreator<TFieldView extends FocusableView> = (labeledFieldView: LabeledFieldView, viewUid: string, statusUid: string) => TFieldView;
