()
| 850 | } |
| 851 | |
| 852 | render() { |
| 853 | const { disabled, fill, readonly, shape, inputId, labelPlacement, el, hasFocus, clearInputIcon } = this; |
| 854 | const mode = getIonMode(this); |
| 855 | const value = this.getValue(); |
| 856 | const inItem = hostContext('ion-item', this.el); |
| 857 | const shouldRenderHighlight = mode === 'md' && fill !== 'outline' && !inItem; |
| 858 | const defaultClearIcon = mode === 'ios' ? closeCircle : closeSharp; |
| 859 | const clearIconData = clearInputIcon ?? defaultClearIcon; |
| 860 | |
| 861 | const hasValue = this.hasValue(); |
| 862 | const hasStartEndSlots = el.querySelector('[slot="start"], [slot="end"]') !== null; |
| 863 | |
| 864 | /** |
| 865 | * If the label is stacked, it should always sit above the input. |
| 866 | * For floating labels, the label should move above the input if |
| 867 | * the input has a value, is focused, or has anything in either |
| 868 | * the start or end slot. |
| 869 | * |
| 870 | * If there is content in the start slot, the label would overlap |
| 871 | * it if not forced to float. This is also applied to the end slot |
| 872 | * because with the default or solid fills, the input is not |
| 873 | * vertically centered in the container, but the label is. This |
| 874 | * causes the slots and label to appear vertically offset from each |
| 875 | * other when the label isn't floating above the input. This doesn't |
| 876 | * apply to the outline fill, but this was not accounted for to keep |
| 877 | * things consistent. |
| 878 | * |
| 879 | * TODO(FW-5592): Remove hasStartEndSlots condition |
| 880 | */ |
| 881 | const labelShouldFloat = |
| 882 | labelPlacement === 'stacked' || (labelPlacement === 'floating' && (hasValue || hasFocus || hasStartEndSlots)); |
| 883 | |
| 884 | return ( |
| 885 | <Host |
| 886 | class={createColorClasses(this.color, { |
| 887 | [mode]: true, |
| 888 | 'has-value': hasValue, |
| 889 | 'has-focus': hasFocus, |
| 890 | 'label-floating': labelShouldFloat, |
| 891 | [`input-fill-${fill}`]: fill !== undefined, |
| 892 | [`input-shape-${shape}`]: shape !== undefined, |
| 893 | [`input-label-placement-${labelPlacement}`]: true, |
| 894 | 'in-item': inItem, |
| 895 | 'in-item-color': hostContext('ion-item.ion-color', this.el), |
| 896 | 'input-disabled': disabled, |
| 897 | })} |
| 898 | > |
| 899 | {/** |
| 900 | * htmlFor is needed so that clicking the label always focuses |
| 901 | * the input. Otherwise, if the start slot has something |
| 902 | * interactable, clicking the label would focus that instead |
| 903 | * since it comes before the input in the DOM. |
| 904 | */} |
| 905 | <label class="input-wrapper" htmlFor={inputId} onClick={this.onLabelClick}> |
| 906 | {this.renderLabelContainer()} |
| 907 | <div class="native-wrapper" onClick={this.onLabelClick}> |
| 908 | <slot name="start"></slot> |
| 909 | <input |
nothing calls this directly
no test coverage detected