import {classMap} from "lit/directives/class-map.js"; import {defaultValue} from "../../internal/default-value"; import {FormControlController} from "../../internal/form"; import {HasSlotController} from "../../internal/slot"; import {html, unsafeCSS} from 'lit'; import {ifDefined} from "lit/directives/if-defined.js"; import {live} from "lit/directives/live.js"; import {LocalizeController} from "../../utilities/localize"; import {property, query, state} from 'lit/decorators.js'; import {watch} from "../../internal/watch"; import ZincElement from '../../internal/zinc-element'; import ZnIcon from "../icon"; import ZnTooltip from "../tooltip"; import type {ZincFormControl} from '../../internal/zinc-element'; import styles from './input.scss'; /** * @summary Short summary of the component's intended use. * @documentation https://zinc.style/components/input * @status experimental * @since 1.0 * * @dependency zn-icon * @dependency zn-tooltip * * @event zn-blur - Emitted when the control loses focus. * @event zn-change - Emitted when an alteration to the control's value is committed by the user. * @event zn-clear - Emitted when the clear button is activated. * @event zn-focus - Emitted when the control gains focus. * @event zn-input - Emitted when the control receives input. * @event zn-invalid - Emitted when the form control has been checked for validity and its constraints aren't satisfied. * * @slot label - The input's label. Alternatively, you can use the `label` attribute. * @slot label-tooltip - Used to add text that is displayed in a tooltip next to the label. Alternatively, you can use the `label-tooltip` attribute. * @slot context-note - Used to add contextual text that is displayed above the input, on the right. Alternatively, you can use the `context-note` attribute. * @slot prefix - Used to prepend a presentational icon or similar element to the input. * @slot suffix - Used to append a presentational icon or similar element to the input. * @slot clear-icon - An icon to use in lieu of the default clear icon. * @slot show-password-icon - An icon to use in lieu of the default show password icon. * @slot hide-password-icon - An icon to use in lieu of the default hide password icon. * @slot help-text - Text that describes how to use the input. Alternatively, you can use the `help-text` attribute. * * @csspart form-control - The form control that wraps the label, input, and help text. * @csspart form-control-label - The label's wrapper. * @csspart form-control-input - The input's wrapper. * @csspart form-control-help-text - The help text's wrapper. * @csspart base - The component's base wrapper. * @csspart input - The internal `` control. * @csspart prefix - The container that wraps the prefix. * @csspart clear-button - The clear button. * @csspart password-toggle-button - The password toggle button. * @csspart suffix - The container that wraps the suffix. */ export default class ZnInput extends ZincElement implements ZincFormControl { static styles = unsafeCSS(styles); static dependencies = { 'zn-icon': ZnIcon, 'zn-tooltip': ZnTooltip } private readonly formControlController = new FormControlController(this, { assumeInteractionOn: ['zn-blur', 'zn-input'] }); private readonly hasSlotController = new HasSlotController(this, 'help-text', 'label', 'label-tooltip'); private readonly localize = new LocalizeController(this); @query('.input__control') input: HTMLInputElement; @query('.input__color-picker') colorPicker: HTMLInputElement; @state() private hasFocus = false; @state() private isUserTyping = false; @property() title = "" // make reactive pass through private __numberInput = Object.assign(document.createElement('input'), {type: 'number'}); private __dateInput = Object.assign(document.createElement('input'), {type: 'date'}); /** * The type of input. Works the same as native `` element. But only a subset of types is supported. Defaults * to `text` */ @property({reflect: true}) type: 'color' | 'currency' | 'date' | 'datetime-local' | 'email' | 'number' | 'password' | 'search' | 'tel' | 'text' | 'time' | 'url' = 'text'; /** The name of the input, submitted as a name/value pair with form data. */ @property() name: string = ""; /** The current value of the input, submitted as a name/value pair with form data. */ @property() value: any = ''; /** The default value of the form control. Primarily used for resetting the form control. */ @defaultValue() defaultValue: string = ''; /** The inputs size **/ @property({reflect: true}) size: 'x-small' | 'small' | 'medium' | 'large' = 'medium'; /** Draws a pill-styled input **/ @property({type: Boolean, reflect: true}) pill: boolean = false; /** The inputs label. If you need to display HTML, use the `label` slot. **/ @property() label: string = ''; /** Text that appears in a tooltip next to the label. If you need to display HTML in the tooltip, use the * `label-tooltip` slot. * **/ @property({attribute: 'label-tooltip'}) labelTooltip: string = ''; /** * Text that appears above the input, on the right, to add additional context. If you need to display HTML * in this text, use the `context-note` slot instead */ @property({attribute: 'context-note'}) contextNote: string = ''; /** The input's help text. If you need to display HTML, use the `help-text` slot instead. **/ @property({attribute: 'help-text'}) helpText: string = ''; /** Adds a clear button when the input is not empty **/ @property({type: Boolean, reflect: true}) clearable: boolean = false; /** Adds the default optional icon for this input type. Currently only types `email` and `tel` have a default * optional icon. */ @property({attribute: 'optional-icon', type: Boolean}) optionalIcon: boolean = false; /** Disables the input **/ @property({type: Boolean, reflect: true}) disabled: boolean = false; /** Fills the input background white **/ @property({type: Boolean, reflect: true}) filled: boolean = false; /** Placeholder text to show as a hint when the input is empty. */ @property() placeholder: string = ''; /** Makes the input read-only **/ @property({type: Boolean, reflect: true}) readonly: boolean = false; /** Adds a button to toggle the passwords visibility, only applies to password types **/ @property({attribute: 'password-toggle', type: Boolean}) passwordToggle: boolean = false; /** Determines whether or no the password is currently visible. Only applies to password types **/ @property({attribute: 'password-visible', type: Boolean}) passwordVisible: boolean = false; /** Hides the browsers built-in increment/decrement spin buttons for number inputs **/ @property({attribute: 'no-spin-buttons', type: Boolean}) noSpinButtons: boolean = false; /** The color format to display for color inputs. Only applies when type is 'color'. **/ @property({attribute: 'color-format'}) colorFormat: 'hex' | 'rgb' | 'hsl' | 'oklch' = 'hex'; /** * By default, form-controls are associated with the nearest containing `