@lion/ui
Version:
A package of extendable web components
174 lines • 8.28 kB
TypeScript
/**
* Note: one could consider to implement LionInputTelDropdown as a
* [combobox](https://www.w3.org/TR/wai-aria-practices-1.2/#combobox).
* However, the country dropdown does not directly set the textbox value, it only determines
* its region code. Therefore it does not comply to this criterium:
* "A combobox is an input widget with an associated popup that enables users to select a value for
* the combobox from a collection of possible values. In some implementations,
* the popup presents allowed values, while in other implementations, the popup presents suggested
* values, and users may either select one of the suggestions or type a value".
* We therefore decided to consider the dropdown a helper mechanism that does not set, but
* contributes to and helps format and validate the actual value.
*/
/**
* @typedef {import('lit/directives/ref.js').Ref} Ref
* @typedef {import('lit').RenderOptions} RenderOptions
* @typedef {import('../../form-core/types/FormatMixinTypes.js').FormatHost} FormatHost
* @typedef {import('../../input-tel/types/index.js').RegionCode} RegionCode
* @typedef {import('../types/index.js').TemplateDataForDropdownInputTel} TemplateDataForDropdownInputTel
* @typedef {import('../types/index.js').OnDropdownChangeEvent} OnDropdownChangeEvent
* @typedef {import('../types/index.js').DropdownRef} DropdownRef
* @typedef {import('../types/index.js').RegionMeta} RegionMeta
* @typedef {import('../../select-rich/src/LionSelectRich.js').LionSelectRich} LionSelectRich
* @typedef {import('../../overlays/src/OverlayController.js').OverlayController} OverlayController
* @typedef {TemplateDataForDropdownInputTel & {data: {regionMetaList:RegionMeta[]}}} TemplateDataForIntlInputTel
*/
/**
* LionInputTelDropdown renders a dropdown like element next to the text field, inside the
* prefix slot. This could be a LionSelect, a LionSelectRich or a native select.
* By default, the native `<select>` element is used for this, so that it's as lightweight as
* possible. Also, it doesn't need to be a `FormControl`, because it's purely a helper element
* to provide better UX: the modelValue (the text field) contains all needed info, since it's in
* `e164` format that contains all info (both region code and national phone number).
*
* @customElement lion-input-tel-dropdown
*/
export class LionInputTelDropdown extends LionInputTel {
static templates: {
dropdown: (templateDataForDropdown: TemplateDataForDropdownInputTel) => import("lit-html").TemplateResult<1>;
/**
* @param {TemplateDataForDropdownInputTel} templateDataForDropdown
* @param {RegionMeta} contextData
*/
dropdownOption: (templateDataForDropdown: TemplateDataForDropdownInputTel, { regionCode, countryCode, flagSymbol }: RegionMeta) => import("lit-html").TemplateResult<1>;
};
/**
* @configure LitElement
* @enhance LionInputTel
*/
static styles: (import("lit").CSSResult | import("lit").CSSResultArray)[];
refs: {
/** @type {DropdownRef} */
dropdown: DropdownRef;
};
/**
* This method provides a TemplateData object to be fed to pure template functions, a.k.a.
* Pure Templates™. The goal is to totally decouple presentation from logic here, so that
* Subclassers can override all content without having to loose private info contained
* within the template function that was overridden.
*
* Subclassers would need to make sure all the contents of the TemplateData object are implemented
* by making sure they are coupled to the right 'ref' ([data-ref=dropdown] in this example),
* with the help of lit's spread operator directive.
* To enhance this process, the TemplateData object is completely typed. Ideally, this would be
* enhanced by providing linters that make sure all of their required members are implemented by
* a Subclasser.
* When a Subclasser wants to add more data, this can be done via:
* @example
* ```js
* get _templateDataDropdown() {
* return {
* ...super._templateDataDropdown,
* myExtraData: { x: 1, y: 2 },
* }
* }
* ```
* @overridable
* @type {TemplateDataForDropdownInputTel}
*/
get _templateDataDropdown(): import("../types/index.js").TemplateDataForDropdownInputTel;
/**
* @configure SlotMixin
*/
get slots(): {
prefix: () => {
template: import("lit-html").TemplateResult<1>;
renderAsDirectHostChild: boolean;
};
input: () => HTMLInputElement;
};
__namesForLocale: Intl.DisplayNames | undefined;
/**
* Group label for all countries, when preferredCountries are shown
* @protected
*/
protected _allCountriesLabel: string;
/**
* Group label for preferred countries, when preferredCountries are shown
* @protected
*/
protected _preferredCountriesLabel: string;
/**
* Contains everything needed for rendering region options:
* region code, country code, display name according to locale, display name
* @private
* @type {RegionMeta[]}
*/
private __regionMetaList;
/**
* A filtered `this.__regionMetaList`, containing all regions provided in `preferredRegions`
* @private
* @type {RegionMeta[]}
*/
private __regionMetaListPreferred;
/**
* @protected
* @param {OnDropdownChangeEvent} event
*/
protected _onDropdownValueChange(event: OnDropdownChangeEvent): void;
/**
* @private
*/
private __syncRegionWithDropdown;
/**
* @protected
*/
protected _initModelValueBasedOnDropdown(): void;
__initializedRegionCode: string | undefined;
/**
* Used for Required validation and computation of interaction states.
* We need to override this, because we prefill the input with the region code (like +31), but for proper UX,
* we don't consider this as having interaction state `prefilled`
* @param {string} modelValue
* @return {boolean}
* @protected
*/
protected _isEmpty(modelValue?: string): boolean;
/**
* Prepares data for options, like "Greece (Ελλάδα)", where "Greece" is `nameForLocale` and
* "Ελλάδα" `nameForRegion`.
* This should be run on change of:
* - allowedRegions
* - _phoneUtil loaded
* - locale
* @private
*/
private __createRegionMeta;
/**
* Usually, we don't use composition in regular LionFields (non choice-groups). Here we use a LionSelect(Rich) inside.
* We don't want to repropagate any children, since an Application Developer is not concerned with these internals (see repropate logic in FormControlMixin)
* Also, we don't want to give (wrong) info to InteractionStateMixin, that will set the wrong interaction states based on child info.
* TODO: Make "this._repropagationRole !== 'child'" the default for FormControlMixin
* (so that FormControls used within are never repropagated for LionFields)
* @protected
* @configure FormControlMixin: don't repropagate any children
*/
protected _repropagationCondition(): boolean;
}
export type Ref = import('lit/directives/ref.js').Ref;
export type RenderOptions = import('lit').RenderOptions;
export type FormatHost = import('../../form-core/types/FormatMixinTypes.js').FormatHost;
export type RegionCode = import('../../input-tel/types/index.js').RegionCode;
export type TemplateDataForDropdownInputTel = import('../types/index.js').TemplateDataForDropdownInputTel;
export type OnDropdownChangeEvent = import('../types/index.js').OnDropdownChangeEvent;
export type DropdownRef = import('../types/index.js').DropdownRef;
export type RegionMeta = import('../types/index.js').RegionMeta;
export type LionSelectRich = import('../../select-rich/src/LionSelectRich.js').LionSelectRich;
export type OverlayController = import('../../overlays/src/OverlayController.js').OverlayController;
export type TemplateDataForIntlInputTel = TemplateDataForDropdownInputTel & {
data: {
regionMetaList: RegionMeta[];
};
};
import { LionInputTel } from "../../../exports/input-tel.js";
//# sourceMappingURL=LionInputTelDropdown.d.ts.map